From 4c6fb5a8801a05ec492f10eceb31c0af4972148a Mon Sep 17 00:00:00 2001 From: Anthony Berton <34568357+bb2a@users.noreply.github.com> Date: Thu, 6 May 2021 23:04:27 +0200 Subject: [PATCH 001/826] Update pdf.php --- htdocs/admin/pdf.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/htdocs/admin/pdf.php b/htdocs/admin/pdf.php index 7d7b5e36a40..d16e7c694e5 100644 --- a/htdocs/admin/pdf.php +++ b/htdocs/admin/pdf.php @@ -4,6 +4,7 @@ * Copyright (C) 2005-2011 Regis Houssin * Copyright (C) 2012-2107 Juanjo Menent * Copyright (C) 2019 Ferran Marcet + * Copyright (C) 2021 Anthony Berton * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -417,6 +418,17 @@ print ''.$langs->trans("ShowDetailsInPDFPageFoot").'selectarray('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS', $arraydetailsforpdffoot, (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS) ? $conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS : 0)); print ''; +// Show sales representative + +print ''.$langs->trans("DOC_SHOW_FIRST_SALES_REP").''; +if ($conf->use_javascript_ajax) { + print ajax_constantonoff('DOC_SHOW_FIRST_SALES_REP'); +} else { + $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); + print $form->selectarray("DOC_SHOW_FIRST_SALES_REP", $arrval, $conf->global->DOC_SHOW_FIRST_SALES_REP); +} +print ''; + print ''; print ''; From 3de055bac2efb85566b6445b8e446bd2067485a9 Mon Sep 17 00:00:00 2001 From: Anthony Berton <34568357+bb2a@users.noreply.github.com> Date: Wed, 11 Aug 2021 12:10:17 +0200 Subject: [PATCH 002/826] update --- htdocs/admin/pdf.php | 4 +++- htdocs/langs/en_US/admin.lang | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/htdocs/admin/pdf.php b/htdocs/admin/pdf.php index 8891fb5a4c4..4a42eb2bf23 100644 --- a/htdocs/admin/pdf.php +++ b/htdocs/admin/pdf.php @@ -420,7 +420,9 @@ print ''; // Show sales representative -print ''.$langs->trans("DOC_SHOW_FIRST_SALES_REP").''; +print ''.$langs->trans("DOC_SHOW_FIRST_SALES_REP"); +print ' ('.$langs->trans("SalesRepresentativeInfo").')'; +print ''; if ($conf->use_javascript_ajax) { print ajax_constantonoff('DOC_SHOW_FIRST_SALES_REP'); } else { diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 55a0b0a34c3..6bd56b6ed49 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1994,6 +1994,7 @@ MAIN_PDF_MARGIN_RIGHT=Right margin on PDF MAIN_PDF_MARGIN_TOP=Top margin on PDF MAIN_PDF_MARGIN_BOTTOM=Bottom margin on PDF MAIN_DOCUMENTS_LOGO_HEIGHT=Height for logo on PDF +DOC_SHOW_FIRST_SALES_REP=Show first sales representative MAIN_GENERATE_PROPOSALS_WITH_PICTURE=Add picture on proposal line MAIN_PDF_PROPAL_USE_ELECTRONIC_SIGNING=Add electronic sign in PDF NothingToSetup=There is no specific setup required for this module. @@ -2151,8 +2152,9 @@ NoExternalModuleWithUpdate=No updates found for external modules SwaggerDescriptionFile=Swagger API description file (for use with redoc for example) YouEnableDeprecatedWSAPIsUseRESTAPIsInstead=You enabled deprecated WS API. You should use REST API instead. RandomlySelectedIfSeveral=Randomly selected if several pictures are available +SalesRepresentativeInfo=For Proposals, Orders, Invoces. DatabasePasswordObfuscated=Database password is obfuscated in conf file DatabasePasswordNotObfuscated=Database password is NOT obfuscated in conf file APIsAreNotEnabled=APIs modules are not enabled YouShouldSetThisToOff=You should set this to 0 or off -InstallAndUpgradeLockedBy=Install and upgrades are locked by the file %s \ No newline at end of file +InstallAndUpgradeLockedBy=Install and upgrades are locked by the file %s From 03ff75bccdfa5816638e81daaf8062fe7cab0bac Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Thu, 9 Sep 2021 06:29:33 +0000 Subject: [PATCH 003/826] Fixing style errors. --- htdocs/admin/pdf.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/admin/pdf.php b/htdocs/admin/pdf.php index 22fee77cdd5..ba06aadc8df 100644 --- a/htdocs/admin/pdf.php +++ b/htdocs/admin/pdf.php @@ -166,10 +166,10 @@ if ($action == 'update') { dolibarr_set_const($db, "PDF_SHOW_LINK_TO_ONLINE_PAYMENT", GETPOST('PDF_SHOW_LINK_TO_ONLINE_PAYMENT', 'alpha'), 'chaine', 0, '', $conf->entity); } - if (GETPOSTISSET('DOC_SHOW_FIRST_SALES_REP')) { + if (GETPOSTISSET('DOC_SHOW_FIRST_SALES_REP')) { dolibarr_set_const($db, "DOC_SHOW_FIRST_SALES_REP", GETPOST('DOC_SHOW_FIRST_SALES_REP', 'alpha'), 'chaine', 0, '', $conf->entity); } - + setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); header("Location: ".$_SERVER["PHP_SELF"]."?mainmenu=home&leftmenu=setup"); From 8adfc4fefe381afdac663fe68302f9eb6c63e13c Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Mon, 8 Nov 2021 13:27:01 +0000 Subject: [PATCH 004/826] Fixing style errors. --- htdocs/admin/pdf.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/admin/pdf.php b/htdocs/admin/pdf.php index 513fc7ae4af..30f097d7dd0 100644 --- a/htdocs/admin/pdf.php +++ b/htdocs/admin/pdf.php @@ -168,8 +168,8 @@ if ($action == 'update') { if (GETPOSTISSET('DOC_SHOW_FIRST_SALES_REP')) { dolibarr_set_const($db, "DOC_SHOW_FIRST_SALES_REP", GETPOST('DOC_SHOW_FIRST_SALES_REP', 'alpha'), 'chaine', 0, '', $conf->entity); - } - + } + if (GETPOSTISSET('PDF_USE_A')) { dolibarr_set_const($db, "PDF_USE_A", GETPOST('PDF_USE_A', 'alpha'), 'chaine', 0, '', $conf->entity); } From 5329028d6aa219aba1adb3b6c17027a175a55ba7 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Fri, 7 Jan 2022 12:17:39 +0100 Subject: [PATCH 005/826] Start feature --- .../install/mysql/migration/15.0.0-16.0.0.sql | 34 ++++++++++++ .../mysql/tables/llx_projet_task_time.sql | 1 + htdocs/projet/class/task.class.php | 6 +++ htdocs/projet/tasks/time.php | 53 ++++++++++++++++++- 4 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 htdocs/install/mysql/migration/15.0.0-16.0.0.sql diff --git a/htdocs/install/mysql/migration/15.0.0-16.0.0.sql b/htdocs/install/mysql/migration/15.0.0-16.0.0.sql new file mode 100644 index 00000000000..64df9ca79cb --- /dev/null +++ b/htdocs/install/mysql/migration/15.0.0-16.0.0.sql @@ -0,0 +1,34 @@ +-- +-- Be carefull to requests order. +-- This file must be loaded by calling /install/index.php page +-- when current version is 14.0.0 or higher. +-- +-- To restrict request to Mysql version x.y minimum use -- VMYSQLx.y +-- To restrict request to Pgsql version x.y minimum use -- VPGSQLx.y +-- To rename a table: ALTER TABLE llx_table RENAME TO llx_table_new; +-- To add a column: ALTER TABLE llx_table ADD COLUMN newcol varchar(60) NOT NULL DEFAULT '0' AFTER existingcol; +-- To rename a column: ALTER TABLE llx_table CHANGE COLUMN oldname newname varchar(60); +-- To drop a column: ALTER TABLE llx_table DROP COLUMN oldname; +-- To change type of field: ALTER TABLE llx_table MODIFY COLUMN name varchar(60); +-- To drop a foreign key: ALTER TABLE llx_table DROP FOREIGN KEY fk_name; +-- To create a unique index ALTER TABLE llx_table ADD UNIQUE INDEX uk_table_field (field); +-- To drop an index: -- VMYSQL4.1 DROP INDEX nomindex on llx_table; +-- To drop an index: -- VPGSQL8.2 DROP INDEX nomindex; +-- To make pk to be auto increment (mysql): -- VMYSQL4.3 ALTER TABLE llx_table CHANGE COLUMN rowid rowid INTEGER NOT NULL AUTO_INCREMENT; +-- To make pk to be auto increment (postgres): +-- -- VPGSQL8.2 CREATE SEQUENCE llx_table_rowid_seq OWNED BY llx_table.rowid; +-- -- VPGSQL8.2 ALTER TABLE llx_table ADD PRIMARY KEY (rowid); +-- -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN rowid SET DEFAULT nextval('llx_table_rowid_seq'); +-- -- VPGSQL8.2 SELECT setval('llx_table_rowid_seq', MAX(rowid)) FROM llx_table; +-- To set a field as NULL: -- VMYSQL4.3 ALTER TABLE llx_table MODIFY COLUMN name varchar(60) NULL; +-- To set a field as NULL: -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN name DROP NOT NULL; +-- To set a field as NOT NULL: -- VMYSQL4.3 ALTER TABLE llx_table MODIFY COLUMN name varchar(60) NOT NULL; +-- To set a field as NOT NULL: -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN name SET NOT NULL; +-- To set a field as default NULL: -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN name SET DEFAULT NULL; +-- Note: fields with type BLOB/TEXT can't have default value. +-- To rebuild sequence for postgresql after insert by forcing id autoincrement fields: +-- -- VPGSQL8.2 SELECT dol_util_rebuild_sequences(); + + +-- Missing in v14 or lower +ALTER TABLE llx_projet_task_time ADD COLUMN fk_product integer NULL; diff --git a/htdocs/install/mysql/tables/llx_projet_task_time.sql b/htdocs/install/mysql/tables/llx_projet_task_time.sql index 786d8907588..63eadb1177f 100644 --- a/htdocs/install/mysql/tables/llx_projet_task_time.sql +++ b/htdocs/install/mysql/tables/llx_projet_task_time.sql @@ -24,6 +24,7 @@ create table llx_projet_task_time task_datehour datetime, -- day + hour task_date_withhour integer DEFAULT 0, -- 0 by default, 1 if date was entered with start hour task_duration double, + fk_product integer NULL, fk_user integer, thm double(24,8), invoice_id integer DEFAULT NULL, -- If we need to invoice each line of timespent, we can save invoice id here diff --git a/htdocs/projet/class/task.class.php b/htdocs/projet/class/task.class.php index dac2afa4834..5a6a3e1fba0 100644 --- a/htdocs/projet/class/task.class.php +++ b/htdocs/projet/class/task.class.php @@ -118,6 +118,7 @@ class Task extends CommonObject public $timespent_fk_user; public $timespent_thm; public $timespent_note; + public $timespent_fk_product; public $comments = array(); @@ -1201,6 +1202,7 @@ class Task extends CommonObject $sql .= ", task_date_withhour"; $sql .= ", task_duration"; $sql .= ", fk_user"; + $sql .= ", fk_product"; $sql .= ", note"; $sql .= ") VALUES ("; $sql .= ((int) $this->id); @@ -1209,6 +1211,7 @@ class Task extends CommonObject $sql .= ", ".(empty($this->timespent_withhour) ? 0 : 1); $sql .= ", ".((int) $this->timespent_duration); $sql .= ", ".((int) $this->timespent_fk_user); + $sql .= ", ".((int) $this->timespent_fk_product); $sql .= ", ".(isset($this->timespent_note) ? "'".$this->db->escape($this->timespent_note)."'" : "null"); $sql .= ")"; @@ -1404,6 +1407,7 @@ class Task extends CommonObject $sql .= " t.task_date_withhour,"; $sql .= " t.task_duration,"; $sql .= " t.fk_user,"; + $sql .= " t.fk_product,"; $sql .= " t.thm,"; $sql .= " t.note"; $sql .= " FROM ".MAIN_DB_PREFIX."projet_task_time as t"; @@ -1422,6 +1426,7 @@ class Task extends CommonObject $this->timespent_withhour = $obj->task_date_withhour; $this->timespent_duration = $obj->task_duration; $this->timespent_fk_user = $obj->fk_user; + $this->timespent_fk_product = $obj->fk_product; $this->timespent_thm = $obj->thm; // hourly rate $this->timespent_note = $obj->note; } @@ -1575,6 +1580,7 @@ class Task extends CommonObject $sql .= " task_date_withhour = ".(empty($this->timespent_withhour) ? 0 : 1).","; $sql .= " task_duration = ".((int) $this->timespent_duration).","; $sql .= " fk_user = ".((int) $this->timespent_fk_user).","; + $sql .= " fk_product = ".((int) $this->timespent_fk_product).","; $sql .= " note = ".(isset($this->timespent_note) ? "'".$this->db->escape($this->timespent_note)."'" : "null"); $sql .= " WHERE rowid = ".((int) $this->timespent_id); diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index f9f3a2aca43..03022cfd1c3 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -73,6 +73,7 @@ $search_task_ref = GETPOST('search_task_ref', 'alpha'); $search_task_label = GETPOST('search_task_label', 'alpha'); $search_user = GETPOST('search_user', 'int'); $search_valuebilled = GETPOST('search_valuebilled', 'int'); +$search_product_ref = GETPOST('search_product_ref', 'alpha'); // Security check $socid = 0; @@ -161,6 +162,7 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x' $search_task_label = ''; $search_user = 0; $search_valuebilled = ''; + $search_product_ref = ''; $toselect = ''; $search_array_options = array(); $action = ''; @@ -215,6 +217,7 @@ if ($action == 'addtimespent' && $user->rights->projet->lire) { $object->timespent_date = dol_mktime(12, 0, 0, GETPOST("timemonth", 'int'), GETPOST("timeday", 'int'), GETPOST("timeyear", 'int')); } $object->timespent_fk_user = GETPOST("userid", 'int'); + $object->timespent_fk_product = GETPOST("fk_product", 'int'); $result = $object->addTimeSpent($user); if ($result >= 0) { setEventMessages($langs->trans("RecordSaved"), null, 'mesgs'); @@ -261,6 +264,7 @@ if (($action == 'updateline' || $action == 'updatesplitline') && !$cancel && $us $object->timespent_date = dol_mktime(12, 0, 0, GETPOST("timelinemonth"), GETPOST("timelineday"), GETPOST("timelineyear")); } $object->timespent_fk_user = GETPOST("userid_line", 'int'); + $object->timespent_fk_product = GETPOST("fk_product", 'int'); $result = $object->addTimeSpent($user); if ($result >= 0) { setEventMessages($langs->trans("RecordSaved"), null, 'mesgs'); @@ -284,6 +288,7 @@ if (($action == 'updateline' || $action == 'updatesplitline') && !$cancel && $us $object->timespent_date = dol_mktime(12, 0, 0, GETPOST("timelinemonth", 'int'), GETPOST("timelineday", 'int'), GETPOST("timelineyear", 'int')); } $object->timespent_fk_user = GETPOST("userid_line", 'int'); + $object->timespent_fk_product = GETPOST("fk_product", 'int'); $result = $object->updateTimeSpent($user); if ($result >= 0) { @@ -367,6 +372,7 @@ if ($action == 'confirm_generateinvoice') { $fuser = new User($db); $db->begin(); + //TODO produit du temps passé ou produt id $idprod = GETPOST('productid', 'int'); $generateinvoicemode = GETPOST('generateinvoicemode', 'string'); $invoiceToUse = GETPOST('invoiceid', 'int'); @@ -1029,6 +1035,9 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser } $arrayfields['author'] = array('label'=>$langs->trans("By"), 'checked'=>1); $arrayfields['t.note'] = array('label'=>$langs->trans("Note"), 'checked'=>1); + if ($conf->service->enabled && $projectstatic->thirdparty->id > 0 && $projectstatic->usage_bill_time) { + $arrayfields['t.fk_product'] = array('label' => $langs->trans("Product"), 'checked' => 1); + } $arrayfields['t.task_duration'] = array('label'=>$langs->trans("Duration"), 'checked'=>1); $arrayfields['value'] = array('label'=>$langs->trans("Value"), 'checked'=>1, 'enabled'=>(empty($conf->salaries->enabled) ? 0 : 1)); $arrayfields['valuebilled'] = array('label'=>$langs->trans("Billed"), 'checked'=>1, 'enabled'=>(((!empty($conf->global->PROJECT_HIDE_TASKS) || empty($conf->global->PROJECT_BILL_TIME_SPENT)) ? 0 : 1) && $projectstatic->usage_bill_time)); @@ -1167,6 +1176,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser $form->select_produits('', 'productid', '1', 0, $projectstatic->thirdparty->price_level, 1, 2, '', 0, array(), $projectstatic->thirdparty->id, 'None', 0, 'maxwidth500'); print ''; print ''; + //TODO : Use product of time affect } print ''; @@ -1238,12 +1248,14 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser $tasks = array(); $sql = "SELECT t.rowid, t.fk_task, t.task_date, t.task_datehour, t.task_date_withhour, t.task_duration, t.fk_user, t.note, t.thm,"; + $sql .= " t.fk_product,"; $sql .= " pt.ref, pt.label, pt.fk_projet,"; $sql .= " u.lastname, u.firstname, u.login, u.photo, u.statut as user_status,"; $sql .= " il.fk_facture as invoice_id, inv.fk_statut"; $sql .= " FROM ".MAIN_DB_PREFIX."projet_task_time as t"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facturedet as il ON il.rowid = t.invoice_line_id"; - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facture as inv ON inv.rowid = il.fk_facture,"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facture as inv ON inv.rowid = il.fk_facture"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as prod ON prod.rowid = t.fk_product,"; $sql .= " ".MAIN_DB_PREFIX."projet_task as pt, ".MAIN_DB_PREFIX."user as u"; $sql .= " WHERE t.fk_user = u.rowid AND t.fk_task = pt.rowid"; @@ -1273,6 +1285,9 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser if ($search_user > 0) { $sql .= natural_search('t.fk_user', $search_user, 2); } + if (!empty($search_product_ref)) { + $sql .= natural_search('prod.ref', $search_product_ref); + } if ($search_valuebilled == '1') { $sql .= ' AND t.invoice_id > 0'; } @@ -1365,6 +1380,10 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser print ''.$langs->trans("ProgressDeclared").''; if (empty($conf->global->PROJECT_HIDE_TASKS) && !empty($conf->global->PROJECT_BILL_TIME_SPENT)) { print ''; + + if ($conf->service->enabled && $projectstatic->thirdparty->id > 0 && $projectstatic->usage_bill_time) { + print ''.$langs->trans("Product").''; + } } print ''; print "\n"; @@ -1436,6 +1455,12 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser if (empty($conf->global->PROJECT_HIDE_TASKS) && !empty($conf->global->PROJECT_BILL_TIME_SPENT)) { print ''; print ''; + + if ($conf->service->enabled && $projectstatic->thirdparty->id > 0 && $projectstatic->usage_bill_time) { + print ''; + print $form->select_produits('', 'fk_product', '1', 0, $projectstatic->thirdparty->price_level, 1, 2, '', 0, array(), $projectstatic->thirdparty->id, 'None', 0, 'maxwidth500'); + print ''; + } } print ''; @@ -1509,6 +1534,10 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser if (!empty($arrayfields['t.task_duration']['checked'])) { print ''; } + // Product + if (!empty($arrayfields['t.fk_product']['checked'])) { + print ''; + } // Value in main currency if (!empty($arrayfields['value']['checked'])) { print ''; @@ -1557,6 +1586,10 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser if (!empty($arrayfields['t.task_duration']['checked'])) { print_liste_field_titre($arrayfields['t.task_duration']['label'], $_SERVER['PHP_SELF'], 't.task_duration', '', $param, '', $sortfield, $sortorder, 'right '); } + if (!empty($arrayfields['t.fk_product']['checked'])) { + print_liste_field_titre($arrayfields['t.fk_product']['label'], $_SERVER['PHP_SELF'], 't.fk_product', '', $param, '', $sortfield, $sortorder, 'right '); + } + if (!empty($arrayfields['value']['checked'])) { print_liste_field_titre($arrayfields['value']['label'], $_SERVER['PHP_SELF'], '', '', $param, '', $sortfield, $sortorder, 'right '); } @@ -1732,6 +1765,24 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser $totalarray['totalduration'] += $task_time->task_duration; } + //Product + if (!empty($arrayfields['t.fk_product']['checked'])) { + print ''; + if ($action == 'editline' && $_GET['lineid'] == $task_time->rowid) { + $form->select_produits($task_time->fk_product, 'fk_product', '1', 0, $projectstatic->thirdparty->price_level, 1, 2, '', 0, array(), $projectstatic->thirdparty->id, 'None', 0, 'maxwidth500'); + } elseif (!empty($task_time->fk_product)) { + $product = new Product($db); + $resultFetch = $product->fetch($task_time->fk_product); + if ($resultFetch < 0) { + setEventMessages($product->error, $product->errors, 'errors'); + } else { + + print $product->getNomUrl(1); + } + } + print ''; + } + // Value spent if (!empty($arrayfields['value']['checked'])) { $langs->load("salaries"); From 09d2204effc7abfe9375d1d77a5565074cf55d69 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Fri, 7 Jan 2022 12:19:57 +0100 Subject: [PATCH 006/826] mov dbb change to othger pr --- .../install/mysql/migration/15.0.0-16.0.0.sql | 34 ------------------- .../mysql/tables/llx_projet_task_time.sql | 1 - 2 files changed, 35 deletions(-) delete mode 100644 htdocs/install/mysql/migration/15.0.0-16.0.0.sql diff --git a/htdocs/install/mysql/migration/15.0.0-16.0.0.sql b/htdocs/install/mysql/migration/15.0.0-16.0.0.sql deleted file mode 100644 index 64df9ca79cb..00000000000 --- a/htdocs/install/mysql/migration/15.0.0-16.0.0.sql +++ /dev/null @@ -1,34 +0,0 @@ --- --- Be carefull to requests order. --- This file must be loaded by calling /install/index.php page --- when current version is 14.0.0 or higher. --- --- To restrict request to Mysql version x.y minimum use -- VMYSQLx.y --- To restrict request to Pgsql version x.y minimum use -- VPGSQLx.y --- To rename a table: ALTER TABLE llx_table RENAME TO llx_table_new; --- To add a column: ALTER TABLE llx_table ADD COLUMN newcol varchar(60) NOT NULL DEFAULT '0' AFTER existingcol; --- To rename a column: ALTER TABLE llx_table CHANGE COLUMN oldname newname varchar(60); --- To drop a column: ALTER TABLE llx_table DROP COLUMN oldname; --- To change type of field: ALTER TABLE llx_table MODIFY COLUMN name varchar(60); --- To drop a foreign key: ALTER TABLE llx_table DROP FOREIGN KEY fk_name; --- To create a unique index ALTER TABLE llx_table ADD UNIQUE INDEX uk_table_field (field); --- To drop an index: -- VMYSQL4.1 DROP INDEX nomindex on llx_table; --- To drop an index: -- VPGSQL8.2 DROP INDEX nomindex; --- To make pk to be auto increment (mysql): -- VMYSQL4.3 ALTER TABLE llx_table CHANGE COLUMN rowid rowid INTEGER NOT NULL AUTO_INCREMENT; --- To make pk to be auto increment (postgres): --- -- VPGSQL8.2 CREATE SEQUENCE llx_table_rowid_seq OWNED BY llx_table.rowid; --- -- VPGSQL8.2 ALTER TABLE llx_table ADD PRIMARY KEY (rowid); --- -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN rowid SET DEFAULT nextval('llx_table_rowid_seq'); --- -- VPGSQL8.2 SELECT setval('llx_table_rowid_seq', MAX(rowid)) FROM llx_table; --- To set a field as NULL: -- VMYSQL4.3 ALTER TABLE llx_table MODIFY COLUMN name varchar(60) NULL; --- To set a field as NULL: -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN name DROP NOT NULL; --- To set a field as NOT NULL: -- VMYSQL4.3 ALTER TABLE llx_table MODIFY COLUMN name varchar(60) NOT NULL; --- To set a field as NOT NULL: -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN name SET NOT NULL; --- To set a field as default NULL: -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN name SET DEFAULT NULL; --- Note: fields with type BLOB/TEXT can't have default value. --- To rebuild sequence for postgresql after insert by forcing id autoincrement fields: --- -- VPGSQL8.2 SELECT dol_util_rebuild_sequences(); - - --- Missing in v14 or lower -ALTER TABLE llx_projet_task_time ADD COLUMN fk_product integer NULL; diff --git a/htdocs/install/mysql/tables/llx_projet_task_time.sql b/htdocs/install/mysql/tables/llx_projet_task_time.sql index 63eadb1177f..786d8907588 100644 --- a/htdocs/install/mysql/tables/llx_projet_task_time.sql +++ b/htdocs/install/mysql/tables/llx_projet_task_time.sql @@ -24,7 +24,6 @@ create table llx_projet_task_time task_datehour datetime, -- day + hour task_date_withhour integer DEFAULT 0, -- 0 by default, 1 if date was entered with start hour task_duration double, - fk_product integer NULL, fk_user integer, thm double(24,8), invoice_id integer DEFAULT NULL, -- If we need to invoice each line of timespent, we can save invoice id here From 633ad793cdfbf56e9300fff221758f67389f407d Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Fri, 7 Jan 2022 11:25:53 +0000 Subject: [PATCH 007/826] Fixing style errors. --- htdocs/projet/tasks/time.php | 1 - 1 file changed, 1 deletion(-) diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index 03022cfd1c3..d38ee8e580a 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -1776,7 +1776,6 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser if ($resultFetch < 0) { setEventMessages($product->error, $product->errors, 'errors'); } else { - print $product->getNomUrl(1); } } From 8d3d8fe63b2607b7f875fa96e3c7c1ed7bd24b98 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Mon, 24 Jan 2022 23:24:08 +0100 Subject: [PATCH 008/826] merge --- .../EmailValidator/EmailLexer.php | 494 ++--- .../EmailValidator/EmailParser.php | 196 +- .../EmailValidator/EmailValidator.php | 98 +- .../Exception/DomainAcceptsNoMail.php | 6 +- .../Exception/ExpectingQPair.php | 4 +- .../Exception/LocalOrReservedDomain.php | 6 +- .../EmailValidator/Exception/NoDNSRecord.php | 4 +- .../Exception/UnclosedComment.php | 4 +- .../EmailValidator/Parser/DomainPart.php | 811 ++++--- .../EmailValidator/Parser/LocalPart.php | 210 +- .../EmailValidator/Parser/Parser.php | 379 ++-- .../Validation/DNSCheckValidation.php | 246 +- .../Exception/EmptyValidationList.php | 14 +- .../Validation/MultipleErrors.php | 42 +- .../Validation/MultipleValidationWithAnd.php | 196 +- .../Validation/NoRFCWarningsValidation.php | 50 +- .../Validation/RFCValidation.php | 64 +- .../Validation/SpoofCheckValidation.php | 66 +- .../EmailValidator/Warning/QuotedPart.php | 18 +- .../EmailValidator/Warning/QuotedString.php | 18 +- .../EmailValidator/Warning/Warning.php | 68 +- .../Doctrine/Common/Lexer/AbstractLexer.php | 536 ++--- .../swiftmailer/lib/classes/Swift.php | 104 +- .../lib/classes/Swift/AddressEncoder.php | 14 +- .../AddressEncoder/IdnAddressEncoder.php | 40 +- .../AddressEncoder/Utf8AddressEncoder.php | 14 +- .../classes/Swift/AddressEncoderException.php | 20 +- .../lib/classes/Swift/Attachment.php | 68 +- .../AbstractFilterableInputStream.php | 278 +-- .../Swift/ByteStream/ArrayByteStream.php | 288 +-- .../Swift/ByteStream/FileByteStream.php | 342 +-- .../ByteStream/TemporaryFileByteStream.php | 58 +- .../GenericFixedWidthReader.php | 142 +- .../Swift/CharacterReader/UsAsciiReader.php | 122 +- .../Swift/CharacterReader/Utf8Reader.php | 298 +-- .../SimpleCharacterReaderFactory.php | 182 +- .../lib/classes/Swift/CharacterStream.php | 114 +- .../CharacterStream/ArrayCharacterStream.php | 486 ++-- .../CharacterStream/NgCharacterStream.php | 440 ++-- .../lib/classes/Swift/DependencyContainer.php | 644 +++--- .../lib/classes/Swift/EmbeddedFile.php | 66 +- .../classes/Swift/Encoder/Base64Encoder.php | 72 +- .../lib/classes/Swift/Encoder/QpEncoder.php | 504 ++--- .../classes/Swift/Encoder/Rfc2231Encoder.php | 126 +- .../lib/classes/Swift/Events/CommandEvent.php | 84 +- .../classes/Swift/Events/CommandListener.php | 8 +- .../classes/Swift/Events/EventDispatcher.php | 92 +- .../lib/classes/Swift/Events/EventObject.php | 76 +- .../classes/Swift/Events/ResponseEvent.php | 84 +- .../classes/Swift/Events/ResponseListener.php | 8 +- .../lib/classes/Swift/Events/SendEvent.php | 188 +- .../lib/classes/Swift/Events/SendListener.php | 16 +- .../Swift/Events/SimpleEventDispatcher.php | 224 +- .../Swift/Events/TransportChangeListener.php | 32 +- .../Swift/Events/TransportExceptionEvent.php | 46 +- .../Events/TransportExceptionListener.php | 8 +- .../lib/classes/Swift/FailoverTransport.php | 28 +- .../lib/classes/Swift/FileSpool.php | 330 +-- .../lib/classes/Swift/Filterable.php | 24 +- .../lib/classes/Swift/InputByteStream.php | 100 +- .../lib/classes/Swift/IoException.php | 20 +- .../lib/classes/Swift/KeyCache.php | 154 +- .../classes/Swift/KeyCache/ArrayKeyCache.php | 332 +-- .../classes/Swift/KeyCache/DiskKeyCache.php | 508 ++--- .../Swift/KeyCache/KeyCacheInputStream.php | 50 +- .../classes/Swift/KeyCache/NullKeyCache.php | 176 +- .../KeyCache/SimpleKeyCacheInputStream.php | 184 +- .../classes/Swift/LoadBalancedTransport.php | 28 +- .../swiftmailer/lib/classes/Swift/Mailer.php | 142 +- .../Swift/Mailer/ArrayRecipientIterator.php | 64 +- .../lib/classes/Swift/MemorySpool.php | 162 +- .../swiftmailer/lib/classes/Swift/Message.php | 442 ++-- .../lib/classes/Swift/Mime/Attachment.php | 224 +- .../ContentEncoder/Base64ContentEncoder.php | 144 +- .../ContentEncoder/NativeQpContentEncoder.php | 182 +- .../ContentEncoder/NullContentEncoder.php | 110 +- .../ContentEncoder/PlainContentEncoder.php | 252 +-- .../Mime/ContentEncoder/QpContentEncoder.php | 200 +- .../ContentEncoder/QpContentEncoderProxy.php | 134 +- .../Mime/ContentEncoder/RawContentEncoder.php | 80 +- .../lib/classes/Swift/Mime/EmbeddedFile.php | 44 +- .../classes/Swift/Mime/EncodingObserver.php | 8 +- .../lib/classes/Swift/Mime/Header.php | 126 +- .../HeaderEncoder/Base64HeaderEncoder.php | 68 +- .../Mime/HeaderEncoder/QpHeaderEncoder.php | 88 +- .../Swift/Mime/Headers/AbstractHeader.php | 834 +++---- .../classes/Swift/Mime/Headers/DateHeader.php | 174 +- .../Mime/Headers/IdentificationHeader.php | 298 +-- .../Swift/Mime/Headers/MailboxHeader.php | 626 +++--- .../Swift/Mime/Headers/OpenDKIMHeader.php | 208 +- .../Mime/Headers/ParameterizedHeader.php | 426 ++-- .../classes/Swift/Mime/Headers/PathHeader.php | 242 +- .../Swift/Mime/Headers/UnstructuredHeader.php | 166 +- .../lib/classes/Swift/Mime/IdGenerator.php | 68 +- .../lib/classes/Swift/Mime/MimePart.php | 318 +-- .../Swift/Mime/SimpleHeaderFactory.php | 310 +-- .../classes/Swift/Mime/SimpleHeaderSet.php | 674 +++--- .../lib/classes/Swift/Mime/SimpleMessage.php | 1248 +++++------ .../classes/Swift/Mime/SimpleMimeEntity.php | 1616 +++++++------- .../lib/classes/Swift/MimePart.php | 52 +- .../lib/classes/Swift/NullTransport.php | 16 +- .../classes/Swift/Plugins/AntiFloodPlugin.php | 216 +- .../Swift/Plugins/BandwidthMonitorPlugin.php | 244 +- .../classes/Swift/Plugins/DecoratorPlugin.php | 332 +-- .../Swift/Plugins/ImpersonatePlugin.php | 80 +- .../classes/Swift/Plugins/LoggerPlugin.php | 194 +- .../Swift/Plugins/Loggers/ArrayLogger.php | 98 +- .../classes/Swift/Plugins/MessageLogger.php | 92 +- .../Swift/Plugins/PopBeforeSmtpPlugin.php | 376 ++-- .../Swift/Plugins/RedirectingPlugin.php | 314 +-- .../lib/classes/Swift/Plugins/Reporter.php | 22 +- .../classes/Swift/Plugins/ReporterPlugin.php | 72 +- .../Swift/Plugins/Reporters/HitReporter.php | 72 +- .../Swift/Plugins/Reporters/HtmlReporter.php | 40 +- .../classes/Swift/Plugins/ThrottlerPlugin.php | 312 +-- .../lib/classes/Swift/Preferences.php | 142 +- .../lib/classes/Swift/SendmailTransport.php | 28 +- .../swiftmailer/lib/classes/Swift/Signer.php | 2 +- .../lib/classes/Swift/Signers/BodySigner.php | 24 +- .../lib/classes/Swift/Signers/DKIMSigner.php | 1328 +++++------ .../classes/Swift/Signers/DomainKeySigner.php | 860 +++---- .../classes/Swift/Signers/HeaderSigner.php | 76 +- .../classes/Swift/Signers/OpenDKIMSigner.php | 274 +-- .../lib/classes/Swift/Signers/SMimeSigner.php | 1044 ++++----- .../lib/classes/Swift/SmtpTransport.php | 38 +- .../lib/classes/Swift/SpoolTransport.php | 26 +- .../ByteArrayReplacementFilter.php | 268 +-- .../StringReplacementFilterFactory.php | 46 +- .../lib/classes/Swift/SwiftException.php | 20 +- .../lib/classes/Swift/Transport.php | 106 +- .../Swift/Transport/AbstractSmtpTransport.php | 1046 ++++----- .../Esmtp/Auth/CramMd5Authenticator.php | 98 +- .../Esmtp/Auth/LoginAuthenticator.php | 48 +- .../Esmtp/Auth/NTLMAuthenticator.php | 1322 +++++------ .../Esmtp/Auth/PlainAuthenticator.php | 46 +- .../Esmtp/Auth/XOAuth2Authenticator.php | 64 +- .../Swift/Transport/Esmtp/AuthHandler.php | 448 ++-- .../Swift/Transport/Esmtp/Authenticator.php | 34 +- .../Transport/Esmtp/EightBitMimeHandler.php | 156 +- .../Swift/Transport/Esmtp/SmtpUtf8Handler.php | 144 +- .../classes/Swift/Transport/EsmtpHandler.php | 120 +- .../Swift/Transport/EsmtpTransport.php | 768 +++---- .../Swift/Transport/FailoverTransport.php | 146 +- .../lib/classes/Swift/Transport/IoBuffer.php | 82 +- .../Swift/Transport/LoadBalancedTransport.php | 310 +-- .../classes/Swift/Transport/NullTransport.php | 140 +- .../Swift/Transport/SendmailTransport.php | 241 +- .../lib/classes/Swift/Transport/SmtpAgent.php | 34 +- .../Swift/Transport/SpoolTransport.php | 176 +- .../classes/Swift/Transport/StreamBuffer.php | 540 ++--- .../lib/classes/Swift/TransportException.php | 20 +- .../lib/dependency_maps/cache_deps.php | 29 +- .../lib/dependency_maps/mime_deps.php | 207 +- .../lib/dependency_maps/transport_deps.php | 145 +- .../includes/swiftmailer/lib/mime_types.php | 1972 ++++++++--------- .../lib/swiftmailer_generate_mimes_config.php | 304 +-- htdocs/projet/tasks/time.php | 2 - 157 files changed, 17939 insertions(+), 17947 deletions(-) diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/EmailLexer.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/EmailLexer.php index 59dcd5876fd..567002e5e2c 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/EmailLexer.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/EmailLexer.php @@ -6,278 +6,278 @@ use Doctrine\Common\Lexer\AbstractLexer; class EmailLexer extends AbstractLexer { - //ASCII values - const C_DEL = 127; - const C_NUL = 0; - const S_AT = 64; - const S_BACKSLASH = 92; - const S_DOT = 46; - const S_DQUOTE = 34; - const S_SQUOTE = 39; - const S_BACKTICK = 96; - const S_OPENPARENTHESIS = 49; - const S_CLOSEPARENTHESIS = 261; - const S_OPENBRACKET = 262; - const S_CLOSEBRACKET = 263; - const S_HYPHEN = 264; - const S_COLON = 265; - const S_DOUBLECOLON = 266; - const S_SP = 267; - const S_HTAB = 268; - const S_CR = 269; - const S_LF = 270; - const S_IPV6TAG = 271; - const S_LOWERTHAN = 272; - const S_GREATERTHAN = 273; - const S_COMMA = 274; - const S_SEMICOLON = 275; - const S_OPENQBRACKET = 276; - const S_CLOSEQBRACKET = 277; - const S_SLASH = 278; - const S_EMPTY = null; - const GENERIC = 300; - const CRLF = 301; - const INVALID = 302; - const ASCII_INVALID_FROM = 127; - const ASCII_INVALID_TO = 199; + //ASCII values + const C_DEL = 127; + const C_NUL = 0; + const S_AT = 64; + const S_BACKSLASH = 92; + const S_DOT = 46; + const S_DQUOTE = 34; + const S_SQUOTE = 39; + const S_BACKTICK = 96; + const S_OPENPARENTHESIS = 49; + const S_CLOSEPARENTHESIS = 261; + const S_OPENBRACKET = 262; + const S_CLOSEBRACKET = 263; + const S_HYPHEN = 264; + const S_COLON = 265; + const S_DOUBLECOLON = 266; + const S_SP = 267; + const S_HTAB = 268; + const S_CR = 269; + const S_LF = 270; + const S_IPV6TAG = 271; + const S_LOWERTHAN = 272; + const S_GREATERTHAN = 273; + const S_COMMA = 274; + const S_SEMICOLON = 275; + const S_OPENQBRACKET = 276; + const S_CLOSEQBRACKET = 277; + const S_SLASH = 278; + const S_EMPTY = null; + const GENERIC = 300; + const CRLF = 301; + const INVALID = 302; + const ASCII_INVALID_FROM = 127; + const ASCII_INVALID_TO = 199; - /** - * US-ASCII visible characters not valid for atext (@link http://tools.ietf.org/html/rfc5322#section-3.2.3) - * - * @var array - */ - protected $charValue = array( - '(' => self::S_OPENPARENTHESIS, - ')' => self::S_CLOSEPARENTHESIS, - '<' => self::S_LOWERTHAN, - '>' => self::S_GREATERTHAN, - '[' => self::S_OPENBRACKET, - ']' => self::S_CLOSEBRACKET, - ':' => self::S_COLON, - ';' => self::S_SEMICOLON, - '@' => self::S_AT, - '\\' => self::S_BACKSLASH, - '/' => self::S_SLASH, - ',' => self::S_COMMA, - '.' => self::S_DOT, - "'" => self::S_SQUOTE, - "`" => self::S_BACKTICK, - '"' => self::S_DQUOTE, - '-' => self::S_HYPHEN, - '::' => self::S_DOUBLECOLON, - ' ' => self::S_SP, - "\t" => self::S_HTAB, - "\r" => self::S_CR, - "\n" => self::S_LF, - "\r\n" => self::CRLF, - 'IPv6' => self::S_IPV6TAG, - '{' => self::S_OPENQBRACKET, - '}' => self::S_CLOSEQBRACKET, - '' => self::S_EMPTY, - '\0' => self::C_NUL, - ); + /** + * US-ASCII visible characters not valid for atext (@link http://tools.ietf.org/html/rfc5322#section-3.2.3) + * + * @var array + */ + protected $charValue = array( + '(' => self::S_OPENPARENTHESIS, + ')' => self::S_CLOSEPARENTHESIS, + '<' => self::S_LOWERTHAN, + '>' => self::S_GREATERTHAN, + '[' => self::S_OPENBRACKET, + ']' => self::S_CLOSEBRACKET, + ':' => self::S_COLON, + ';' => self::S_SEMICOLON, + '@' => self::S_AT, + '\\' => self::S_BACKSLASH, + '/' => self::S_SLASH, + ',' => self::S_COMMA, + '.' => self::S_DOT, + "'" => self::S_SQUOTE, + "`" => self::S_BACKTICK, + '"' => self::S_DQUOTE, + '-' => self::S_HYPHEN, + '::' => self::S_DOUBLECOLON, + ' ' => self::S_SP, + "\t" => self::S_HTAB, + "\r" => self::S_CR, + "\n" => self::S_LF, + "\r\n" => self::CRLF, + 'IPv6' => self::S_IPV6TAG, + '{' => self::S_OPENQBRACKET, + '}' => self::S_CLOSEQBRACKET, + '' => self::S_EMPTY, + '\0' => self::C_NUL, + ); - /** - * @var bool - */ - protected $hasInvalidTokens = false; + /** + * @var bool + */ + protected $hasInvalidTokens = false; - /** - * @var array - * - * @psalm-var array{value:string, type:null|int, position:int}|array - */ - protected $previous = []; + /** + * @var array + * + * @psalm-var array{value:string, type:null|int, position:int}|array + */ + protected $previous = []; - /** - * The last matched/seen token. - * - * @var array - * - * @psalm-var array{value:string, type:null|int, position:int} - */ - public $token; + /** + * The last matched/seen token. + * + * @var array + * + * @psalm-var array{value:string, type:null|int, position:int} + */ + public $token; - /** - * The next token in the input. - * - * @var array|null - */ - public $lookahead; + /** + * The next token in the input. + * + * @var array|null + */ + public $lookahead; - /** - * @psalm-var array{value:'', type:null, position:0} - */ - private static $nullToken = [ - 'value' => '', - 'type' => null, - 'position' => 0, - ]; + /** + * @psalm-var array{value:'', type:null, position:0} + */ + private static $nullToken = [ + 'value' => '', + 'type' => null, + 'position' => 0, + ]; - public function __construct() - { - $this->previous = $this->token = self::$nullToken; - $this->lookahead = null; - } + public function __construct() + { + $this->previous = $this->token = self::$nullToken; + $this->lookahead = null; + } - /** - * @return void - */ - public function reset() - { - $this->hasInvalidTokens = false; - parent::reset(); - $this->previous = $this->token = self::$nullToken; - } + /** + * @return void + */ + public function reset() + { + $this->hasInvalidTokens = false; + parent::reset(); + $this->previous = $this->token = self::$nullToken; + } - /** - * @return bool - */ - public function hasInvalidTokens() - { - return $this->hasInvalidTokens; - } + /** + * @return bool + */ + public function hasInvalidTokens() + { + return $this->hasInvalidTokens; + } - /** - * @param int $type - * @throws \UnexpectedValueException - * @return boolean - * - * @psalm-suppress InvalidScalarArgument - */ - public function find($type) - { - $search = clone $this; - $search->skipUntil($type); + /** + * @param int $type + * @throws \UnexpectedValueException + * @return boolean + * + * @psalm-suppress InvalidScalarArgument + */ + public function find($type) + { + $search = clone $this; + $search->skipUntil($type); - if (!$search->lookahead) { - throw new \UnexpectedValueException($type . ' not found'); - } - return true; - } + if (!$search->lookahead) { + throw new \UnexpectedValueException($type . ' not found'); + } + return true; + } - /** - * getPrevious - * - * @return array - */ - public function getPrevious() - { - return $this->previous; - } + /** + * getPrevious + * + * @return array + */ + public function getPrevious() + { + return $this->previous; + } - /** - * moveNext - * - * @return boolean - */ - public function moveNext() - { - $this->previous = $this->token; - $hasNext = parent::moveNext(); - $this->token = $this->token ?: self::$nullToken; + /** + * moveNext + * + * @return boolean + */ + public function moveNext() + { + $this->previous = $this->token; + $hasNext = parent::moveNext(); + $this->token = $this->token ?: self::$nullToken; - return $hasNext; - } + return $hasNext; + } - /** - * Lexical catchable patterns. - * - * @return string[] - */ - protected function getCatchablePatterns() - { - return array( - '[a-zA-Z_]+[46]?', //ASCII and domain literal - '[^\x00-\x7F]', //UTF-8 - '[0-9]+', - '\r\n', - '::', - '\s+?', - '.', - ); - } + /** + * Lexical catchable patterns. + * + * @return string[] + */ + protected function getCatchablePatterns() + { + return array( + '[a-zA-Z_]+[46]?', //ASCII and domain literal + '[^\x00-\x7F]', //UTF-8 + '[0-9]+', + '\r\n', + '::', + '\s+?', + '.', + ); + } - /** - * Lexical non-catchable patterns. - * - * @return string[] - */ - protected function getNonCatchablePatterns() - { - return array('[\xA0-\xff]+'); - } + /** + * Lexical non-catchable patterns. + * + * @return string[] + */ + protected function getNonCatchablePatterns() + { + return array('[\xA0-\xff]+'); + } - /** - * Retrieve token type. Also processes the token value if necessary. - * - * @param string $value - * @throws \InvalidArgumentException - * @return integer - */ - protected function getType(&$value) - { - if ($this->isNullType($value)) { - return self::C_NUL; - } + /** + * Retrieve token type. Also processes the token value if necessary. + * + * @param string $value + * @throws \InvalidArgumentException + * @return integer + */ + protected function getType(&$value) + { + if ($this->isNullType($value)) { + return self::C_NUL; + } - if ($this->isValid($value)) { - return $this->charValue[$value]; - } + if ($this->isValid($value)) { + return $this->charValue[$value]; + } - if ($this->isUTF8Invalid($value)) { - $this->hasInvalidTokens = true; - return self::INVALID; - } + if ($this->isUTF8Invalid($value)) { + $this->hasInvalidTokens = true; + return self::INVALID; + } - return self::GENERIC; - } + return self::GENERIC; + } - /** - * @param string $value - * - * @return bool - */ - protected function isValid($value) - { - if (isset($this->charValue[$value])) { - return true; - } + /** + * @param string $value + * + * @return bool + */ + protected function isValid($value) + { + if (isset($this->charValue[$value])) { + return true; + } - return false; - } + return false; + } - /** - * @param string $value - * @return bool - */ - protected function isNullType($value) - { - if ($value === "\0") { - return true; - } + /** + * @param string $value + * @return bool + */ + protected function isNullType($value) + { + if ($value === "\0") { + return true; + } - return false; - } + return false; + } - /** - * @param string $value - * @return bool - */ - protected function isUTF8Invalid($value) - { - if (preg_match('/\p{Cc}+/u', $value)) { - return true; - } + /** + * @param string $value + * @return bool + */ + protected function isUTF8Invalid($value) + { + if (preg_match('/\p{Cc}+/u', $value)) { + return true; + } - return false; - } + return false; + } - /** - * @return string - */ - protected function getModifiers() - { - return 'iu'; - } + /** + * @return string + */ + protected function getModifiers() + { + return 'iu'; + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/EmailParser.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/EmailParser.php index 6b7bad66927..cf9e7652339 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/EmailParser.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/EmailParser.php @@ -15,123 +15,123 @@ use Egulias\EmailValidator\Warning\EmailTooLong; */ class EmailParser { - const EMAIL_MAX_LENGTH = 254; + const EMAIL_MAX_LENGTH = 254; - /** - * @var array - */ - protected $warnings = []; + /** + * @var array + */ + protected $warnings = []; - /** - * @var string - */ - protected $domainPart = ''; + /** + * @var string + */ + protected $domainPart = ''; - /** - * @var string - */ - protected $localPart = ''; - /** - * @var EmailLexer - */ - protected $lexer; + /** + * @var string + */ + protected $localPart = ''; + /** + * @var EmailLexer + */ + protected $lexer; - /** - * @var LocalPart - */ - protected $localPartParser; + /** + * @var LocalPart + */ + protected $localPartParser; - /** - * @var DomainPart - */ - protected $domainPartParser; + /** + * @var DomainPart + */ + protected $domainPartParser; - public function __construct(EmailLexer $lexer) - { - $this->lexer = $lexer; - $this->localPartParser = new LocalPart($this->lexer); - $this->domainPartParser = new DomainPart($this->lexer); - } + public function __construct(EmailLexer $lexer) + { + $this->lexer = $lexer; + $this->localPartParser = new LocalPart($this->lexer); + $this->domainPartParser = new DomainPart($this->lexer); + } - /** - * @param string $str - * @return array - */ - public function parse($str) - { - $this->lexer->setInput($str); + /** + * @param string $str + * @return array + */ + public function parse($str) + { + $this->lexer->setInput($str); - if (!$this->hasAtToken()) { - throw new NoLocalPart(); - } + if (!$this->hasAtToken()) { + throw new NoLocalPart(); + } - $this->localPartParser->parse($str); - $this->domainPartParser->parse($str); + $this->localPartParser->parse($str); + $this->domainPartParser->parse($str); - $this->setParts($str); + $this->setParts($str); - if ($this->lexer->hasInvalidTokens()) { - throw new ExpectingATEXT(); - } + if ($this->lexer->hasInvalidTokens()) { + throw new ExpectingATEXT(); + } - return array('local' => $this->localPart, 'domain' => $this->domainPart); - } + return array('local' => $this->localPart, 'domain' => $this->domainPart); + } - /** - * @return Warning\Warning[] - */ - public function getWarnings() - { - $localPartWarnings = $this->localPartParser->getWarnings(); - $domainPartWarnings = $this->domainPartParser->getWarnings(); - $this->warnings = array_merge($localPartWarnings, $domainPartWarnings); + /** + * @return Warning\Warning[] + */ + public function getWarnings() + { + $localPartWarnings = $this->localPartParser->getWarnings(); + $domainPartWarnings = $this->domainPartParser->getWarnings(); + $this->warnings = array_merge($localPartWarnings, $domainPartWarnings); - $this->addLongEmailWarning($this->localPart, $this->domainPart); + $this->addLongEmailWarning($this->localPart, $this->domainPart); - return $this->warnings; - } + return $this->warnings; + } - /** - * @return string - */ - public function getParsedDomainPart() - { - return $this->domainPart; - } + /** + * @return string + */ + public function getParsedDomainPart() + { + return $this->domainPart; + } - /** - * @param string $email - */ - protected function setParts($email) - { - $parts = explode('@', $email); - $this->domainPart = $this->domainPartParser->getDomainPart(); - $this->localPart = $parts[0]; - } + /** + * @param string $email + */ + protected function setParts($email) + { + $parts = explode('@', $email); + $this->domainPart = $this->domainPartParser->getDomainPart(); + $this->localPart = $parts[0]; + } - /** - * @return bool - */ - protected function hasAtToken() - { - $this->lexer->moveNext(); - $this->lexer->moveNext(); - if ($this->lexer->token['type'] === EmailLexer::S_AT) { - return false; - } + /** + * @return bool + */ + protected function hasAtToken() + { + $this->lexer->moveNext(); + $this->lexer->moveNext(); + if ($this->lexer->token['type'] === EmailLexer::S_AT) { + return false; + } - return true; - } + return true; + } - /** - * @param string $localPart - * @param string $parsedDomainPart - */ - protected function addLongEmailWarning($localPart, $parsedDomainPart) - { - if (strlen($localPart . '@' . $parsedDomainPart) > self::EMAIL_MAX_LENGTH) { - $this->warnings[EmailTooLong::CODE] = new EmailTooLong(); - } - } + /** + * @param string $localPart + * @param string $parsedDomainPart + */ + protected function addLongEmailWarning($localPart, $parsedDomainPart) + { + if (strlen($localPart . '@' . $parsedDomainPart) > self::EMAIL_MAX_LENGTH) { + $this->warnings[EmailTooLong::CODE] = new EmailTooLong(); + } + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/EmailValidator.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/EmailValidator.php index a30f21dcd30..e0532e618a6 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/EmailValidator.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/EmailValidator.php @@ -7,61 +7,61 @@ use Egulias\EmailValidator\Validation\EmailValidation; class EmailValidator { - /** - * @var EmailLexer - */ - private $lexer; + /** + * @var EmailLexer + */ + private $lexer; - /** - * @var Warning\Warning[] - */ - protected $warnings = []; + /** + * @var Warning\Warning[] + */ + protected $warnings = []; - /** - * @var InvalidEmail|null - */ - protected $error; + /** + * @var InvalidEmail|null + */ + protected $error; - public function __construct() - { - $this->lexer = new EmailLexer(); - } + public function __construct() + { + $this->lexer = new EmailLexer(); + } - /** - * @param string $email - * @param EmailValidation $emailValidation - * @return bool - */ - public function isValid($email, EmailValidation $emailValidation) - { - $isValid = $emailValidation->isValid($email, $this->lexer); - $this->warnings = $emailValidation->getWarnings(); - $this->error = $emailValidation->getError(); + /** + * @param string $email + * @param EmailValidation $emailValidation + * @return bool + */ + public function isValid($email, EmailValidation $emailValidation) + { + $isValid = $emailValidation->isValid($email, $this->lexer); + $this->warnings = $emailValidation->getWarnings(); + $this->error = $emailValidation->getError(); - return $isValid; - } + return $isValid; + } - /** - * @return boolean - */ - public function hasWarnings() - { - return !empty($this->warnings); - } + /** + * @return boolean + */ + public function hasWarnings() + { + return !empty($this->warnings); + } - /** - * @return array - */ - public function getWarnings() - { - return $this->warnings; - } + /** + * @return array + */ + public function getWarnings() + { + return $this->warnings; + } - /** - * @return InvalidEmail|null - */ - public function getError() - { - return $this->error; - } + /** + * @return InvalidEmail|null + */ + public function getError() + { + return $this->error; + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/DomainAcceptsNoMail.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/DomainAcceptsNoMail.php index 40a99705ce9..822258f6f07 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/DomainAcceptsNoMail.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/DomainAcceptsNoMail.php @@ -4,6 +4,6 @@ namespace Egulias\EmailValidator\Exception; class DomainAcceptsNoMail extends InvalidEmail { - const CODE = 154; - const REASON = 'Domain accepts no mail (Null MX, RFC7505)'; -} \ No newline at end of file + const CODE = 154; + const REASON = 'Domain accepts no mail (Null MX, RFC7505)'; +} diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/ExpectingQPair.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/ExpectingQPair.php index a738eeb62f0..ea9fc690bfa 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/ExpectingQPair.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/ExpectingQPair.php @@ -4,6 +4,6 @@ namespace Egulias\EmailValidator\Exception; class ExpectingQPair extends InvalidEmail { - const CODE = 136; - const REASON = "Expecting QPAIR"; + const CODE = 136; + const REASON = "Expecting QPAIR"; } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/LocalOrReservedDomain.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/LocalOrReservedDomain.php index 695b05a46d4..964a6406726 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/LocalOrReservedDomain.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/LocalOrReservedDomain.php @@ -4,6 +4,6 @@ namespace Egulias\EmailValidator\Exception; class LocalOrReservedDomain extends InvalidEmail { - const CODE = 153; - const REASON = 'Local, mDNS or reserved domain (RFC2606, RFC6762)'; -} \ No newline at end of file + const CODE = 153; + const REASON = 'Local, mDNS or reserved domain (RFC2606, RFC6762)'; +} diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/NoDNSRecord.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/NoDNSRecord.php index 0aa5fa78902..3e551ea6c11 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/NoDNSRecord.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/NoDNSRecord.php @@ -4,6 +4,6 @@ namespace Egulias\EmailValidator\Exception; class NoDNSRecord extends InvalidEmail { - const CODE = 5; - const REASON = 'No MX or A DSN record was found for this email'; + const CODE = 5; + const REASON = 'No MX or A DSN record was found for this email'; } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/UnclosedComment.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/UnclosedComment.php index 86b2b09622d..40d9ab31fb7 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/UnclosedComment.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/UnclosedComment.php @@ -4,6 +4,6 @@ namespace Egulias\EmailValidator\Exception; class UnclosedComment extends InvalidEmail { - const CODE = 146; - const REASON = "No closing comment token found"; + const CODE = 146; + const REASON = "No closing comment token found"; } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Parser/DomainPart.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Parser/DomainPart.php index 4dadba8af7c..8a0a8fe2674 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Parser/DomainPart.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Parser/DomainPart.php @@ -34,410 +34,409 @@ use Egulias\EmailValidator\Warning\TLD; class DomainPart extends Parser { - const DOMAIN_MAX_LENGTH = 254; - const LABEL_MAX_LENGTH = 63; - - /** - * @var string - */ - protected $domainPart = ''; - - public function parse($domainPart) - { - $this->lexer->moveNext(); - - $this->performDomainStartChecks(); - - $domain = $this->doParseDomainPart(); - - $prev = $this->lexer->getPrevious(); - $length = strlen($domain); - - if ($prev['type'] === EmailLexer::S_DOT) { - throw new DotAtEnd(); - } - if ($prev['type'] === EmailLexer::S_HYPHEN) { - throw new DomainHyphened(); - } - if ($length > self::DOMAIN_MAX_LENGTH) { - $this->warnings[DomainTooLong::CODE] = new DomainTooLong(); - } - if ($prev['type'] === EmailLexer::S_CR) { - throw new CRLFAtTheEnd(); - } - $this->domainPart = $domain; - } - - private function performDomainStartChecks() - { - $this->checkInvalidTokensAfterAT(); - $this->checkEmptyDomain(); - - if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) { - $this->warnings[DeprecatedComment::CODE] = new DeprecatedComment(); - $this->parseDomainComments(); - } - } - - private function checkEmptyDomain() - { - $thereIsNoDomain = $this->lexer->token['type'] === EmailLexer::S_EMPTY || - ($this->lexer->token['type'] === EmailLexer::S_SP && - !$this->lexer->isNextToken(EmailLexer::GENERIC)); - - if ($thereIsNoDomain) { - throw new NoDomainPart(); - } - } - - private function checkInvalidTokensAfterAT() - { - if ($this->lexer->token['type'] === EmailLexer::S_DOT) { - throw new DotAtStart(); - } - if ($this->lexer->token['type'] === EmailLexer::S_HYPHEN) { - throw new DomainHyphened(); - } - } - - /** - * @return string - */ - public function getDomainPart() - { - return $this->domainPart; - } - - /** - * @param string $addressLiteral - * @param int $maxGroups - */ - public function checkIPV6Tag($addressLiteral, $maxGroups = 8) - { - $prev = $this->lexer->getPrevious(); - if ($prev['type'] === EmailLexer::S_COLON) { - $this->warnings[IPV6ColonEnd::CODE] = new IPV6ColonEnd(); - } - - $IPv6 = substr($addressLiteral, 5); - //Daniel Marschall's new IPv6 testing strategy - $matchesIP = explode(':', $IPv6); - $groupCount = count($matchesIP); - $colons = strpos($IPv6, '::'); - - if (count(preg_grep('/^[0-9A-Fa-f]{0,4}$/', $matchesIP, PREG_GREP_INVERT)) !== 0) { - $this->warnings[IPV6BadChar::CODE] = new IPV6BadChar(); - } - - if ($colons === false) { - // We need exactly the right number of groups - if ($groupCount !== $maxGroups) { - $this->warnings[IPV6GroupCount::CODE] = new IPV6GroupCount(); - } - return; - } - - if ($colons !== strrpos($IPv6, '::')) { - $this->warnings[IPV6DoubleColon::CODE] = new IPV6DoubleColon(); - return; - } - - if ($colons === 0 || $colons === (strlen($IPv6) - 2)) { - // RFC 4291 allows :: at the start or end of an address - //with 7 other groups in addition - ++$maxGroups; - } - - if ($groupCount > $maxGroups) { - $this->warnings[IPV6MaxGroups::CODE] = new IPV6MaxGroups(); - } elseif ($groupCount === $maxGroups) { - $this->warnings[IPV6Deprecated::CODE] = new IPV6Deprecated(); - } - } - - /** - * @return string - */ - protected function doParseDomainPart() - { - $domain = ''; - $label = ''; - $openedParenthesis = 0; - do { - $prev = $this->lexer->getPrevious(); - - $this->checkNotAllowedChars($this->lexer->token); - - if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) { - $this->parseComments(); - $openedParenthesis += $this->getOpenedParenthesis(); - $this->lexer->moveNext(); - $tmpPrev = $this->lexer->getPrevious(); - if ($tmpPrev['type'] === EmailLexer::S_CLOSEPARENTHESIS) { - $openedParenthesis--; - } - } - if ($this->lexer->token['type'] === EmailLexer::S_CLOSEPARENTHESIS) { - if ($openedParenthesis === 0) { - throw new UnopenedComment(); - } else { - $openedParenthesis--; - } - } - - $this->checkConsecutiveDots(); - $this->checkDomainPartExceptions($prev); - - if ($this->hasBrackets()) { - $this->parseDomainLiteral(); - } - - if ($this->lexer->token['type'] === EmailLexer::S_DOT) { - $this->checkLabelLength($label); - $label = ''; - } else { - $label .= $this->lexer->token['value']; - } - - if ($this->isFWS()) { - $this->parseFWS(); - } - - $domain .= $this->lexer->token['value']; - $this->lexer->moveNext(); - if ($this->lexer->token['type'] === EmailLexer::S_SP) { - throw new CharNotAllowed(); - } - } while (null !== $this->lexer->token['type']); - - $this->checkLabelLength($label); - - return $domain; - } - - private function checkNotAllowedChars(array $token) - { - $notAllowed = [EmailLexer::S_BACKSLASH => true, EmailLexer::S_SLASH=> true]; - if (isset($notAllowed[$token['type']])) { - throw new CharNotAllowed(); - } - } - - /** - * @return string|false - */ - protected function parseDomainLiteral() - { - if ($this->lexer->isNextToken(EmailLexer::S_COLON)) { - $this->warnings[IPV6ColonStart::CODE] = new IPV6ColonStart(); - } - if ($this->lexer->isNextToken(EmailLexer::S_IPV6TAG)) { - $lexer = clone $this->lexer; - $lexer->moveNext(); - if ($lexer->isNextToken(EmailLexer::S_DOUBLECOLON)) { - $this->warnings[IPV6ColonStart::CODE] = new IPV6ColonStart(); - } - } - - return $this->doParseDomainLiteral(); - } - - /** - * @return string|false - */ - protected function doParseDomainLiteral() - { - $IPv6TAG = false; - $addressLiteral = ''; - do { - if ($this->lexer->token['type'] === EmailLexer::C_NUL) { - throw new ExpectingDTEXT(); - } - - if ($this->lexer->token['type'] === EmailLexer::INVALID || - $this->lexer->token['type'] === EmailLexer::C_DEL || - $this->lexer->token['type'] === EmailLexer::S_LF - ) { - $this->warnings[ObsoleteDTEXT::CODE] = new ObsoleteDTEXT(); - } - - if ($this->lexer->isNextTokenAny(array(EmailLexer::S_OPENQBRACKET, EmailLexer::S_OPENBRACKET))) { - throw new ExpectingDTEXT(); - } - - if ($this->lexer->isNextTokenAny( - array(EmailLexer::S_HTAB, EmailLexer::S_SP, $this->lexer->token['type'] === EmailLexer::CRLF) - )) { - $this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS(); - $this->parseFWS(); - } - - if ($this->lexer->isNextToken(EmailLexer::S_CR)) { - throw new CRNoLF(); - } - - if ($this->lexer->token['type'] === EmailLexer::S_BACKSLASH) { - $this->warnings[ObsoleteDTEXT::CODE] = new ObsoleteDTEXT(); - $addressLiteral .= $this->lexer->token['value']; - $this->lexer->moveNext(); - $this->validateQuotedPair(); - } - if ($this->lexer->token['type'] === EmailLexer::S_IPV6TAG) { - $IPv6TAG = true; - } - if ($this->lexer->token['type'] === EmailLexer::S_CLOSEQBRACKET) { - break; - } - - $addressLiteral .= $this->lexer->token['value']; - - } while ($this->lexer->moveNext()); - - $addressLiteral = str_replace('[', '', $addressLiteral); - $addressLiteral = $this->checkIPV4Tag($addressLiteral); - - if (false === $addressLiteral) { - return $addressLiteral; - } - - if (!$IPv6TAG) { - $this->warnings[DomainLiteral::CODE] = new DomainLiteral(); - return $addressLiteral; - } - - $this->warnings[AddressLiteral::CODE] = new AddressLiteral(); - - $this->checkIPV6Tag($addressLiteral); - - return $addressLiteral; - } - - /** - * @param string $addressLiteral - * - * @return string|false - */ - protected function checkIPV4Tag($addressLiteral) - { - $matchesIP = array(); - - // Extract IPv4 part from the end of the address-literal (if there is one) - if (preg_match( - '/\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/', - $addressLiteral, - $matchesIP - ) > 0 - ) { - $index = strrpos($addressLiteral, $matchesIP[0]); - if ($index === 0) { - $this->warnings[AddressLiteral::CODE] = new AddressLiteral(); - return false; - } - // Convert IPv4 part to IPv6 format for further testing - $addressLiteral = substr($addressLiteral, 0, (int) $index) . '0:0'; - } - - return $addressLiteral; - } - - protected function checkDomainPartExceptions(array $prev) - { - $invalidDomainTokens = array( - EmailLexer::S_DQUOTE => true, - EmailLexer::S_SQUOTE => true, - EmailLexer::S_BACKTICK => true, - EmailLexer::S_SEMICOLON => true, - EmailLexer::S_GREATERTHAN => true, - EmailLexer::S_LOWERTHAN => true, - ); - - if (isset($invalidDomainTokens[$this->lexer->token['type']])) { - throw new ExpectingATEXT(); - } - - if ($this->lexer->token['type'] === EmailLexer::S_COMMA) { - throw new CommaInDomain(); - } - - if ($this->lexer->token['type'] === EmailLexer::S_AT) { - throw new ConsecutiveAt(); - } - - if ($this->lexer->token['type'] === EmailLexer::S_OPENQBRACKET && $prev['type'] !== EmailLexer::S_AT) { - throw new ExpectingATEXT(); - } - - if ($this->lexer->token['type'] === EmailLexer::S_HYPHEN && $this->lexer->isNextToken(EmailLexer::S_DOT)) { - throw new DomainHyphened(); - } - - if ($this->lexer->token['type'] === EmailLexer::S_BACKSLASH - && $this->lexer->isNextToken(EmailLexer::GENERIC)) { - throw new ExpectingATEXT(); - } - } - - /** - * @return bool - */ - protected function hasBrackets() - { - if ($this->lexer->token['type'] !== EmailLexer::S_OPENBRACKET) { - return false; - } - - try { - $this->lexer->find(EmailLexer::S_CLOSEBRACKET); - } catch (\RuntimeException $e) { - throw new ExpectingDomainLiteralClose(); - } - - return true; - } - - /** - * @param string $label - */ - protected function checkLabelLength($label) - { - if ($this->isLabelTooLong($label)) { - $this->warnings[LabelTooLong::CODE] = new LabelTooLong(); - } - } - - /** - * @param string $label - * @return bool - */ - private function isLabelTooLong($label) - { - if (preg_match('/[^\x00-\x7F]/', $label)) { - idn_to_ascii($label, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46, $idnaInfo); - - return (bool) ($idnaInfo['errors'] & IDNA_ERROR_LABEL_TOO_LONG); - } - - return strlen($label) > self::LABEL_MAX_LENGTH; - } - - protected function parseDomainComments() - { - $this->isUnclosedComment(); - while (!$this->lexer->isNextToken(EmailLexer::S_CLOSEPARENTHESIS)) { - $this->warnEscaping(); - $this->lexer->moveNext(); - } - - $this->lexer->moveNext(); - if ($this->lexer->isNextToken(EmailLexer::S_DOT)) { - throw new ExpectingATEXT(); - } - } - - protected function addTLDWarnings() - { - if ($this->warnings[DomainLiteral::CODE]) { - $this->warnings[TLD::CODE] = new TLD(); - } - } + const DOMAIN_MAX_LENGTH = 254; + const LABEL_MAX_LENGTH = 63; + + /** + * @var string + */ + protected $domainPart = ''; + + public function parse($domainPart) + { + $this->lexer->moveNext(); + + $this->performDomainStartChecks(); + + $domain = $this->doParseDomainPart(); + + $prev = $this->lexer->getPrevious(); + $length = strlen($domain); + + if ($prev['type'] === EmailLexer::S_DOT) { + throw new DotAtEnd(); + } + if ($prev['type'] === EmailLexer::S_HYPHEN) { + throw new DomainHyphened(); + } + if ($length > self::DOMAIN_MAX_LENGTH) { + $this->warnings[DomainTooLong::CODE] = new DomainTooLong(); + } + if ($prev['type'] === EmailLexer::S_CR) { + throw new CRLFAtTheEnd(); + } + $this->domainPart = $domain; + } + + private function performDomainStartChecks() + { + $this->checkInvalidTokensAfterAT(); + $this->checkEmptyDomain(); + + if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) { + $this->warnings[DeprecatedComment::CODE] = new DeprecatedComment(); + $this->parseDomainComments(); + } + } + + private function checkEmptyDomain() + { + $thereIsNoDomain = $this->lexer->token['type'] === EmailLexer::S_EMPTY || + ($this->lexer->token['type'] === EmailLexer::S_SP && + !$this->lexer->isNextToken(EmailLexer::GENERIC)); + + if ($thereIsNoDomain) { + throw new NoDomainPart(); + } + } + + private function checkInvalidTokensAfterAT() + { + if ($this->lexer->token['type'] === EmailLexer::S_DOT) { + throw new DotAtStart(); + } + if ($this->lexer->token['type'] === EmailLexer::S_HYPHEN) { + throw new DomainHyphened(); + } + } + + /** + * @return string + */ + public function getDomainPart() + { + return $this->domainPart; + } + + /** + * @param string $addressLiteral + * @param int $maxGroups + */ + public function checkIPV6Tag($addressLiteral, $maxGroups = 8) + { + $prev = $this->lexer->getPrevious(); + if ($prev['type'] === EmailLexer::S_COLON) { + $this->warnings[IPV6ColonEnd::CODE] = new IPV6ColonEnd(); + } + + $IPv6 = substr($addressLiteral, 5); + //Daniel Marschall's new IPv6 testing strategy + $matchesIP = explode(':', $IPv6); + $groupCount = count($matchesIP); + $colons = strpos($IPv6, '::'); + + if (count(preg_grep('/^[0-9A-Fa-f]{0,4}$/', $matchesIP, PREG_GREP_INVERT)) !== 0) { + $this->warnings[IPV6BadChar::CODE] = new IPV6BadChar(); + } + + if ($colons === false) { + // We need exactly the right number of groups + if ($groupCount !== $maxGroups) { + $this->warnings[IPV6GroupCount::CODE] = new IPV6GroupCount(); + } + return; + } + + if ($colons !== strrpos($IPv6, '::')) { + $this->warnings[IPV6DoubleColon::CODE] = new IPV6DoubleColon(); + return; + } + + if ($colons === 0 || $colons === (strlen($IPv6) - 2)) { + // RFC 4291 allows :: at the start or end of an address + //with 7 other groups in addition + ++$maxGroups; + } + + if ($groupCount > $maxGroups) { + $this->warnings[IPV6MaxGroups::CODE] = new IPV6MaxGroups(); + } elseif ($groupCount === $maxGroups) { + $this->warnings[IPV6Deprecated::CODE] = new IPV6Deprecated(); + } + } + + /** + * @return string + */ + protected function doParseDomainPart() + { + $domain = ''; + $label = ''; + $openedParenthesis = 0; + do { + $prev = $this->lexer->getPrevious(); + + $this->checkNotAllowedChars($this->lexer->token); + + if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) { + $this->parseComments(); + $openedParenthesis += $this->getOpenedParenthesis(); + $this->lexer->moveNext(); + $tmpPrev = $this->lexer->getPrevious(); + if ($tmpPrev['type'] === EmailLexer::S_CLOSEPARENTHESIS) { + $openedParenthesis--; + } + } + if ($this->lexer->token['type'] === EmailLexer::S_CLOSEPARENTHESIS) { + if ($openedParenthesis === 0) { + throw new UnopenedComment(); + } else { + $openedParenthesis--; + } + } + + $this->checkConsecutiveDots(); + $this->checkDomainPartExceptions($prev); + + if ($this->hasBrackets()) { + $this->parseDomainLiteral(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_DOT) { + $this->checkLabelLength($label); + $label = ''; + } else { + $label .= $this->lexer->token['value']; + } + + if ($this->isFWS()) { + $this->parseFWS(); + } + + $domain .= $this->lexer->token['value']; + $this->lexer->moveNext(); + if ($this->lexer->token['type'] === EmailLexer::S_SP) { + throw new CharNotAllowed(); + } + } while (null !== $this->lexer->token['type']); + + $this->checkLabelLength($label); + + return $domain; + } + + private function checkNotAllowedChars(array $token) + { + $notAllowed = [EmailLexer::S_BACKSLASH => true, EmailLexer::S_SLASH=> true]; + if (isset($notAllowed[$token['type']])) { + throw new CharNotAllowed(); + } + } + + /** + * @return string|false + */ + protected function parseDomainLiteral() + { + if ($this->lexer->isNextToken(EmailLexer::S_COLON)) { + $this->warnings[IPV6ColonStart::CODE] = new IPV6ColonStart(); + } + if ($this->lexer->isNextToken(EmailLexer::S_IPV6TAG)) { + $lexer = clone $this->lexer; + $lexer->moveNext(); + if ($lexer->isNextToken(EmailLexer::S_DOUBLECOLON)) { + $this->warnings[IPV6ColonStart::CODE] = new IPV6ColonStart(); + } + } + + return $this->doParseDomainLiteral(); + } + + /** + * @return string|false + */ + protected function doParseDomainLiteral() + { + $IPv6TAG = false; + $addressLiteral = ''; + do { + if ($this->lexer->token['type'] === EmailLexer::C_NUL) { + throw new ExpectingDTEXT(); + } + + if ($this->lexer->token['type'] === EmailLexer::INVALID || + $this->lexer->token['type'] === EmailLexer::C_DEL || + $this->lexer->token['type'] === EmailLexer::S_LF + ) { + $this->warnings[ObsoleteDTEXT::CODE] = new ObsoleteDTEXT(); + } + + if ($this->lexer->isNextTokenAny(array(EmailLexer::S_OPENQBRACKET, EmailLexer::S_OPENBRACKET))) { + throw new ExpectingDTEXT(); + } + + if ($this->lexer->isNextTokenAny( + array(EmailLexer::S_HTAB, EmailLexer::S_SP, $this->lexer->token['type'] === EmailLexer::CRLF) + )) { + $this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS(); + $this->parseFWS(); + } + + if ($this->lexer->isNextToken(EmailLexer::S_CR)) { + throw new CRNoLF(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_BACKSLASH) { + $this->warnings[ObsoleteDTEXT::CODE] = new ObsoleteDTEXT(); + $addressLiteral .= $this->lexer->token['value']; + $this->lexer->moveNext(); + $this->validateQuotedPair(); + } + if ($this->lexer->token['type'] === EmailLexer::S_IPV6TAG) { + $IPv6TAG = true; + } + if ($this->lexer->token['type'] === EmailLexer::S_CLOSEQBRACKET) { + break; + } + + $addressLiteral .= $this->lexer->token['value']; + } while ($this->lexer->moveNext()); + + $addressLiteral = str_replace('[', '', $addressLiteral); + $addressLiteral = $this->checkIPV4Tag($addressLiteral); + + if (false === $addressLiteral) { + return $addressLiteral; + } + + if (!$IPv6TAG) { + $this->warnings[DomainLiteral::CODE] = new DomainLiteral(); + return $addressLiteral; + } + + $this->warnings[AddressLiteral::CODE] = new AddressLiteral(); + + $this->checkIPV6Tag($addressLiteral); + + return $addressLiteral; + } + + /** + * @param string $addressLiteral + * + * @return string|false + */ + protected function checkIPV4Tag($addressLiteral) + { + $matchesIP = array(); + + // Extract IPv4 part from the end of the address-literal (if there is one) + if (preg_match( + '/\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/', + $addressLiteral, + $matchesIP + ) > 0 + ) { + $index = strrpos($addressLiteral, $matchesIP[0]); + if ($index === 0) { + $this->warnings[AddressLiteral::CODE] = new AddressLiteral(); + return false; + } + // Convert IPv4 part to IPv6 format for further testing + $addressLiteral = substr($addressLiteral, 0, (int) $index) . '0:0'; + } + + return $addressLiteral; + } + + protected function checkDomainPartExceptions(array $prev) + { + $invalidDomainTokens = array( + EmailLexer::S_DQUOTE => true, + EmailLexer::S_SQUOTE => true, + EmailLexer::S_BACKTICK => true, + EmailLexer::S_SEMICOLON => true, + EmailLexer::S_GREATERTHAN => true, + EmailLexer::S_LOWERTHAN => true, + ); + + if (isset($invalidDomainTokens[$this->lexer->token['type']])) { + throw new ExpectingATEXT(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_COMMA) { + throw new CommaInDomain(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_AT) { + throw new ConsecutiveAt(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_OPENQBRACKET && $prev['type'] !== EmailLexer::S_AT) { + throw new ExpectingATEXT(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_HYPHEN && $this->lexer->isNextToken(EmailLexer::S_DOT)) { + throw new DomainHyphened(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_BACKSLASH + && $this->lexer->isNextToken(EmailLexer::GENERIC)) { + throw new ExpectingATEXT(); + } + } + + /** + * @return bool + */ + protected function hasBrackets() + { + if ($this->lexer->token['type'] !== EmailLexer::S_OPENBRACKET) { + return false; + } + + try { + $this->lexer->find(EmailLexer::S_CLOSEBRACKET); + } catch (\RuntimeException $e) { + throw new ExpectingDomainLiteralClose(); + } + + return true; + } + + /** + * @param string $label + */ + protected function checkLabelLength($label) + { + if ($this->isLabelTooLong($label)) { + $this->warnings[LabelTooLong::CODE] = new LabelTooLong(); + } + } + + /** + * @param string $label + * @return bool + */ + private function isLabelTooLong($label) + { + if (preg_match('/[^\x00-\x7F]/', $label)) { + idn_to_ascii($label, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46, $idnaInfo); + + return (bool) ($idnaInfo['errors'] & IDNA_ERROR_LABEL_TOO_LONG); + } + + return strlen($label) > self::LABEL_MAX_LENGTH; + } + + protected function parseDomainComments() + { + $this->isUnclosedComment(); + while (!$this->lexer->isNextToken(EmailLexer::S_CLOSEPARENTHESIS)) { + $this->warnEscaping(); + $this->lexer->moveNext(); + } + + $this->lexer->moveNext(); + if ($this->lexer->isNextToken(EmailLexer::S_DOT)) { + throw new ExpectingATEXT(); + } + } + + protected function addTLDWarnings() + { + if ($this->warnings[DomainLiteral::CODE]) { + $this->warnings[TLD::CODE] = new TLD(); + } + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Parser/LocalPart.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Parser/LocalPart.php index 3c21f34ac07..b804b412863 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Parser/LocalPart.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Parser/LocalPart.php @@ -14,132 +14,132 @@ use Egulias\EmailValidator\Warning\LocalTooLong; class LocalPart extends Parser { - public function parse($localPart) - { - $parseDQuote = true; - $closingQuote = false; - $openedParenthesis = 0; - $totalLength = 0; + public function parse($localPart) + { + $parseDQuote = true; + $closingQuote = false; + $openedParenthesis = 0; + $totalLength = 0; - while ($this->lexer->token['type'] !== EmailLexer::S_AT && null !== $this->lexer->token['type']) { - if ($this->lexer->token['type'] === EmailLexer::S_DOT && null === $this->lexer->getPrevious()['type']) { - throw new DotAtStart(); - } + while ($this->lexer->token['type'] !== EmailLexer::S_AT && null !== $this->lexer->token['type']) { + if ($this->lexer->token['type'] === EmailLexer::S_DOT && null === $this->lexer->getPrevious()['type']) { + throw new DotAtStart(); + } - $closingQuote = $this->checkDQUOTE($closingQuote); - if ($closingQuote && $parseDQuote) { - $parseDQuote = $this->parseDoubleQuote(); - } + $closingQuote = $this->checkDQUOTE($closingQuote); + if ($closingQuote && $parseDQuote) { + $parseDQuote = $this->parseDoubleQuote(); + } - if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) { - $this->parseComments(); - $openedParenthesis += $this->getOpenedParenthesis(); - } + if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) { + $this->parseComments(); + $openedParenthesis += $this->getOpenedParenthesis(); + } - if ($this->lexer->token['type'] === EmailLexer::S_CLOSEPARENTHESIS) { - if ($openedParenthesis === 0) { - throw new UnopenedComment(); - } + if ($this->lexer->token['type'] === EmailLexer::S_CLOSEPARENTHESIS) { + if ($openedParenthesis === 0) { + throw new UnopenedComment(); + } - $openedParenthesis--; - } + $openedParenthesis--; + } - $this->checkConsecutiveDots(); + $this->checkConsecutiveDots(); - if ($this->lexer->token['type'] === EmailLexer::S_DOT && - $this->lexer->isNextToken(EmailLexer::S_AT) - ) { - throw new DotAtEnd(); - } + if ($this->lexer->token['type'] === EmailLexer::S_DOT && + $this->lexer->isNextToken(EmailLexer::S_AT) + ) { + throw new DotAtEnd(); + } - $this->warnEscaping(); - $this->isInvalidToken($this->lexer->token, $closingQuote); + $this->warnEscaping(); + $this->isInvalidToken($this->lexer->token, $closingQuote); - if ($this->isFWS()) { - $this->parseFWS(); - } + if ($this->isFWS()) { + $this->parseFWS(); + } - $totalLength += strlen($this->lexer->token['value']); - $this->lexer->moveNext(); - } + $totalLength += strlen($this->lexer->token['value']); + $this->lexer->moveNext(); + } - if ($totalLength > LocalTooLong::LOCAL_PART_LENGTH) { - $this->warnings[LocalTooLong::CODE] = new LocalTooLong(); - } - } + if ($totalLength > LocalTooLong::LOCAL_PART_LENGTH) { + $this->warnings[LocalTooLong::CODE] = new LocalTooLong(); + } + } - /** - * @return bool - */ - protected function parseDoubleQuote() - { - $parseAgain = true; - $special = array( - EmailLexer::S_CR => true, - EmailLexer::S_HTAB => true, - EmailLexer::S_LF => true - ); + /** + * @return bool + */ + protected function parseDoubleQuote() + { + $parseAgain = true; + $special = array( + EmailLexer::S_CR => true, + EmailLexer::S_HTAB => true, + EmailLexer::S_LF => true + ); - $invalid = array( - EmailLexer::C_NUL => true, - EmailLexer::S_HTAB => true, - EmailLexer::S_CR => true, - EmailLexer::S_LF => true - ); - $setSpecialsWarning = true; + $invalid = array( + EmailLexer::C_NUL => true, + EmailLexer::S_HTAB => true, + EmailLexer::S_CR => true, + EmailLexer::S_LF => true + ); + $setSpecialsWarning = true; - $this->lexer->moveNext(); + $this->lexer->moveNext(); - while ($this->lexer->token['type'] !== EmailLexer::S_DQUOTE && null !== $this->lexer->token['type']) { - $parseAgain = false; - if (isset($special[$this->lexer->token['type']]) && $setSpecialsWarning) { - $this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS(); - $setSpecialsWarning = false; - } - if ($this->lexer->token['type'] === EmailLexer::S_BACKSLASH && $this->lexer->isNextToken(EmailLexer::S_DQUOTE)) { - $this->lexer->moveNext(); - } + while ($this->lexer->token['type'] !== EmailLexer::S_DQUOTE && null !== $this->lexer->token['type']) { + $parseAgain = false; + if (isset($special[$this->lexer->token['type']]) && $setSpecialsWarning) { + $this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS(); + $setSpecialsWarning = false; + } + if ($this->lexer->token['type'] === EmailLexer::S_BACKSLASH && $this->lexer->isNextToken(EmailLexer::S_DQUOTE)) { + $this->lexer->moveNext(); + } - $this->lexer->moveNext(); + $this->lexer->moveNext(); - if (!$this->escaped() && isset($invalid[$this->lexer->token['type']])) { - throw new ExpectingATEXT(); - } - } + if (!$this->escaped() && isset($invalid[$this->lexer->token['type']])) { + throw new ExpectingATEXT(); + } + } - $prev = $this->lexer->getPrevious(); + $prev = $this->lexer->getPrevious(); - if ($prev['type'] === EmailLexer::S_BACKSLASH) { - if (!$this->checkDQUOTE(false)) { - throw new UnclosedQuotedString(); - } - } + if ($prev['type'] === EmailLexer::S_BACKSLASH) { + if (!$this->checkDQUOTE(false)) { + throw new UnclosedQuotedString(); + } + } - if (!$this->lexer->isNextToken(EmailLexer::S_AT) && $prev['type'] !== EmailLexer::S_BACKSLASH) { - throw new ExpectingAT(); - } + if (!$this->lexer->isNextToken(EmailLexer::S_AT) && $prev['type'] !== EmailLexer::S_BACKSLASH) { + throw new ExpectingAT(); + } - return $parseAgain; - } + return $parseAgain; + } - /** - * @param bool $closingQuote - */ - protected function isInvalidToken(array $token, $closingQuote) - { - $forbidden = array( - EmailLexer::S_COMMA, - EmailLexer::S_CLOSEBRACKET, - EmailLexer::S_OPENBRACKET, - EmailLexer::S_GREATERTHAN, - EmailLexer::S_LOWERTHAN, - EmailLexer::S_COLON, - EmailLexer::S_SEMICOLON, - EmailLexer::INVALID - ); + /** + * @param bool $closingQuote + */ + protected function isInvalidToken(array $token, $closingQuote) + { + $forbidden = array( + EmailLexer::S_COMMA, + EmailLexer::S_CLOSEBRACKET, + EmailLexer::S_OPENBRACKET, + EmailLexer::S_GREATERTHAN, + EmailLexer::S_LOWERTHAN, + EmailLexer::S_COLON, + EmailLexer::S_SEMICOLON, + EmailLexer::INVALID + ); - if (in_array($token['type'], $forbidden) && !$closingQuote) { - throw new ExpectingATEXT(); - } - } + if (in_array($token['type'], $forbidden) && !$closingQuote) { + throw new ExpectingATEXT(); + } + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Parser/Parser.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Parser/Parser.php index ccdc93889a2..9ebb95ae0a0 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Parser/Parser.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Parser/Parser.php @@ -21,229 +21,228 @@ use Egulias\EmailValidator\Warning\QuotedString; abstract class Parser { - /** - * @var array - */ - protected $warnings = []; + /** + * @var array + */ + protected $warnings = []; - /** - * @var EmailLexer - */ - protected $lexer; + /** + * @var EmailLexer + */ + protected $lexer; - /** - * @var int - */ - protected $openedParenthesis = 0; + /** + * @var int + */ + protected $openedParenthesis = 0; - public function __construct(EmailLexer $lexer) - { - $this->lexer = $lexer; - } + public function __construct(EmailLexer $lexer) + { + $this->lexer = $lexer; + } - /** - * @return \Egulias\EmailValidator\Warning\Warning[] - */ - public function getWarnings() - { - return $this->warnings; - } + /** + * @return \Egulias\EmailValidator\Warning\Warning[] + */ + public function getWarnings() + { + return $this->warnings; + } - /** - * @param string $str - */ - abstract public function parse($str); + /** + * @param string $str + */ + abstract public function parse($str); - /** @return int */ - public function getOpenedParenthesis() - { - return $this->openedParenthesis; - } + /** @return int */ + public function getOpenedParenthesis() + { + return $this->openedParenthesis; + } - /** - * validateQuotedPair - */ - protected function validateQuotedPair() - { - if (!($this->lexer->token['type'] === EmailLexer::INVALID - || $this->lexer->token['type'] === EmailLexer::C_DEL)) { - throw new ExpectingQPair(); - } + /** + * validateQuotedPair + */ + protected function validateQuotedPair() + { + if (!($this->lexer->token['type'] === EmailLexer::INVALID + || $this->lexer->token['type'] === EmailLexer::C_DEL)) { + throw new ExpectingQPair(); + } - $this->warnings[QuotedPart::CODE] = - new QuotedPart($this->lexer->getPrevious()['type'], $this->lexer->token['type']); - } + $this->warnings[QuotedPart::CODE] = + new QuotedPart($this->lexer->getPrevious()['type'], $this->lexer->token['type']); + } - protected function parseComments() - { - $this->openedParenthesis = 1; - $this->isUnclosedComment(); - $this->warnings[Comment::CODE] = new Comment(); - while (!$this->lexer->isNextToken(EmailLexer::S_CLOSEPARENTHESIS)) { - if ($this->lexer->isNextToken(EmailLexer::S_OPENPARENTHESIS)) { - $this->openedParenthesis++; - } - $this->warnEscaping(); - $this->lexer->moveNext(); - } + protected function parseComments() + { + $this->openedParenthesis = 1; + $this->isUnclosedComment(); + $this->warnings[Comment::CODE] = new Comment(); + while (!$this->lexer->isNextToken(EmailLexer::S_CLOSEPARENTHESIS)) { + if ($this->lexer->isNextToken(EmailLexer::S_OPENPARENTHESIS)) { + $this->openedParenthesis++; + } + $this->warnEscaping(); + $this->lexer->moveNext(); + } - $this->lexer->moveNext(); - if ($this->lexer->isNextTokenAny(array(EmailLexer::GENERIC, EmailLexer::S_EMPTY))) { - throw new ExpectingATEXT(); - } + $this->lexer->moveNext(); + if ($this->lexer->isNextTokenAny(array(EmailLexer::GENERIC, EmailLexer::S_EMPTY))) { + throw new ExpectingATEXT(); + } - if ($this->lexer->isNextToken(EmailLexer::S_AT)) { - $this->warnings[CFWSNearAt::CODE] = new CFWSNearAt(); - } - } + if ($this->lexer->isNextToken(EmailLexer::S_AT)) { + $this->warnings[CFWSNearAt::CODE] = new CFWSNearAt(); + } + } - /** - * @return bool - */ - protected function isUnclosedComment() - { - try { - $this->lexer->find(EmailLexer::S_CLOSEPARENTHESIS); - return true; - } catch (\RuntimeException $e) { - throw new UnclosedComment(); - } - } + /** + * @return bool + */ + protected function isUnclosedComment() + { + try { + $this->lexer->find(EmailLexer::S_CLOSEPARENTHESIS); + return true; + } catch (\RuntimeException $e) { + throw new UnclosedComment(); + } + } - protected function parseFWS() - { - $previous = $this->lexer->getPrevious(); + protected function parseFWS() + { + $previous = $this->lexer->getPrevious(); - $this->checkCRLFInFWS(); + $this->checkCRLFInFWS(); - if ($this->lexer->token['type'] === EmailLexer::S_CR) { - throw new CRNoLF(); - } + if ($this->lexer->token['type'] === EmailLexer::S_CR) { + throw new CRNoLF(); + } - if ($this->lexer->isNextToken(EmailLexer::GENERIC) && $previous['type'] !== EmailLexer::S_AT) { - throw new AtextAfterCFWS(); - } + if ($this->lexer->isNextToken(EmailLexer::GENERIC) && $previous['type'] !== EmailLexer::S_AT) { + throw new AtextAfterCFWS(); + } - if ($this->lexer->token['type'] === EmailLexer::S_LF || $this->lexer->token['type'] === EmailLexer::C_NUL) { - throw new ExpectingCTEXT(); - } + if ($this->lexer->token['type'] === EmailLexer::S_LF || $this->lexer->token['type'] === EmailLexer::C_NUL) { + throw new ExpectingCTEXT(); + } - if ($this->lexer->isNextToken(EmailLexer::S_AT) || $previous['type'] === EmailLexer::S_AT) { - $this->warnings[CFWSNearAt::CODE] = new CFWSNearAt(); - } else { - $this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS(); - } - } + if ($this->lexer->isNextToken(EmailLexer::S_AT) || $previous['type'] === EmailLexer::S_AT) { + $this->warnings[CFWSNearAt::CODE] = new CFWSNearAt(); + } else { + $this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS(); + } + } - protected function checkConsecutiveDots() - { - if ($this->lexer->token['type'] === EmailLexer::S_DOT && $this->lexer->isNextToken(EmailLexer::S_DOT)) { - throw new ConsecutiveDot(); - } - } + protected function checkConsecutiveDots() + { + if ($this->lexer->token['type'] === EmailLexer::S_DOT && $this->lexer->isNextToken(EmailLexer::S_DOT)) { + throw new ConsecutiveDot(); + } + } - /** - * @return bool - */ - protected function isFWS() - { - if ($this->escaped()) { - return false; - } + /** + * @return bool + */ + protected function isFWS() + { + if ($this->escaped()) { + return false; + } - if ($this->lexer->token['type'] === EmailLexer::S_SP || - $this->lexer->token['type'] === EmailLexer::S_HTAB || - $this->lexer->token['type'] === EmailLexer::S_CR || - $this->lexer->token['type'] === EmailLexer::S_LF || - $this->lexer->token['type'] === EmailLexer::CRLF - ) { - return true; - } + if ($this->lexer->token['type'] === EmailLexer::S_SP || + $this->lexer->token['type'] === EmailLexer::S_HTAB || + $this->lexer->token['type'] === EmailLexer::S_CR || + $this->lexer->token['type'] === EmailLexer::S_LF || + $this->lexer->token['type'] === EmailLexer::CRLF + ) { + return true; + } - return false; - } + return false; + } - /** - * @return bool - */ - protected function escaped() - { - $previous = $this->lexer->getPrevious(); + /** + * @return bool + */ + protected function escaped() + { + $previous = $this->lexer->getPrevious(); - if ($previous && $previous['type'] === EmailLexer::S_BACKSLASH - && - $this->lexer->token['type'] !== EmailLexer::GENERIC - ) { - return true; - } + if ($previous && $previous['type'] === EmailLexer::S_BACKSLASH + && + $this->lexer->token['type'] !== EmailLexer::GENERIC + ) { + return true; + } - return false; - } + return false; + } - /** - * @return bool - */ - protected function warnEscaping() - { - if ($this->lexer->token['type'] !== EmailLexer::S_BACKSLASH) { - return false; - } + /** + * @return bool + */ + protected function warnEscaping() + { + if ($this->lexer->token['type'] !== EmailLexer::S_BACKSLASH) { + return false; + } - if ($this->lexer->isNextToken(EmailLexer::GENERIC)) { - throw new ExpectingATEXT(); - } + if ($this->lexer->isNextToken(EmailLexer::GENERIC)) { + throw new ExpectingATEXT(); + } - if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB, EmailLexer::C_DEL))) { - return false; - } + if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB, EmailLexer::C_DEL))) { + return false; + } - $this->warnings[QuotedPart::CODE] = - new QuotedPart($this->lexer->getPrevious()['type'], $this->lexer->token['type']); - return true; + $this->warnings[QuotedPart::CODE] = + new QuotedPart($this->lexer->getPrevious()['type'], $this->lexer->token['type']); + return true; + } - } + /** + * @param bool $hasClosingQuote + * + * @return bool + */ + protected function checkDQUOTE($hasClosingQuote) + { + if ($this->lexer->token['type'] !== EmailLexer::S_DQUOTE) { + return $hasClosingQuote; + } + if ($hasClosingQuote) { + return $hasClosingQuote; + } + $previous = $this->lexer->getPrevious(); + if ($this->lexer->isNextToken(EmailLexer::GENERIC) && $previous['type'] === EmailLexer::GENERIC) { + throw new ExpectingATEXT(); + } - /** - * @param bool $hasClosingQuote - * - * @return bool - */ - protected function checkDQUOTE($hasClosingQuote) - { - if ($this->lexer->token['type'] !== EmailLexer::S_DQUOTE) { - return $hasClosingQuote; - } - if ($hasClosingQuote) { - return $hasClosingQuote; - } - $previous = $this->lexer->getPrevious(); - if ($this->lexer->isNextToken(EmailLexer::GENERIC) && $previous['type'] === EmailLexer::GENERIC) { - throw new ExpectingATEXT(); - } + try { + $this->lexer->find(EmailLexer::S_DQUOTE); + $hasClosingQuote = true; + } catch (\Exception $e) { + throw new UnclosedQuotedString(); + } + $this->warnings[QuotedString::CODE] = new QuotedString($previous['value'], $this->lexer->token['value']); - try { - $this->lexer->find(EmailLexer::S_DQUOTE); - $hasClosingQuote = true; - } catch (\Exception $e) { - throw new UnclosedQuotedString(); - } - $this->warnings[QuotedString::CODE] = new QuotedString($previous['value'], $this->lexer->token['value']); + return $hasClosingQuote; + } - return $hasClosingQuote; - } + protected function checkCRLFInFWS() + { + if ($this->lexer->token['type'] !== EmailLexer::CRLF) { + return; + } - protected function checkCRLFInFWS() - { - if ($this->lexer->token['type'] !== EmailLexer::CRLF) { - return; - } + if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB))) { + throw new CRLFX2(); + } - if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB))) { - throw new CRLFX2(); - } - - if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB))) { - throw new CRLFAtTheEnd(); - } - } + if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB))) { + throw new CRLFAtTheEnd(); + } + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/DNSCheckValidation.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/DNSCheckValidation.php index 491082a590f..0d02f11a0a6 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/DNSCheckValidation.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/DNSCheckValidation.php @@ -11,156 +11,156 @@ use Egulias\EmailValidator\Exception\NoDNSRecord; class DNSCheckValidation implements EmailValidation { - /** - * @var array - */ - private $warnings = []; + /** + * @var array + */ + private $warnings = []; - /** - * @var InvalidEmail|null - */ - private $error; + /** + * @var InvalidEmail|null + */ + private $error; - /** - * @var array - */ - private $mxRecords = []; + /** + * @var array + */ + private $mxRecords = []; - public function __construct() - { - if (!function_exists('idn_to_ascii')) { - throw new \LogicException(sprintf('The %s class requires the Intl extension.', __CLASS__)); - } - } + public function __construct() + { + if (!function_exists('idn_to_ascii')) { + throw new \LogicException(sprintf('The %s class requires the Intl extension.', __CLASS__)); + } + } - public function isValid($email, EmailLexer $emailLexer) - { - // use the input to check DNS if we cannot extract something similar to a domain - $host = $email; + public function isValid($email, EmailLexer $emailLexer) + { + // use the input to check DNS if we cannot extract something similar to a domain + $host = $email; - // Arguable pattern to extract the domain. Not aiming to validate the domain nor the email - if (false !== $lastAtPos = strrpos($email, '@')) { - $host = substr($email, $lastAtPos + 1); - } + // Arguable pattern to extract the domain. Not aiming to validate the domain nor the email + if (false !== $lastAtPos = strrpos($email, '@')) { + $host = substr($email, $lastAtPos + 1); + } - // Get the domain parts - $hostParts = explode('.', $host); + // Get the domain parts + $hostParts = explode('.', $host); - // Reserved Top Level DNS Names (https://tools.ietf.org/html/rfc2606#section-2), - // mDNS and private DNS Namespaces (https://tools.ietf.org/html/rfc6762#appendix-G) - $reservedTopLevelDnsNames = [ - // Reserved Top Level DNS Names - 'test', - 'example', - 'invalid', - 'localhost', + // Reserved Top Level DNS Names (https://tools.ietf.org/html/rfc2606#section-2), + // mDNS and private DNS Namespaces (https://tools.ietf.org/html/rfc6762#appendix-G) + $reservedTopLevelDnsNames = [ + // Reserved Top Level DNS Names + 'test', + 'example', + 'invalid', + 'localhost', - // mDNS - 'local', + // mDNS + 'local', - // Private DNS Namespaces - 'intranet', - 'internal', - 'private', - 'corp', - 'home', - 'lan', - ]; + // Private DNS Namespaces + 'intranet', + 'internal', + 'private', + 'corp', + 'home', + 'lan', + ]; - $isLocalDomain = count($hostParts) <= 1; - $isReservedTopLevel = in_array($hostParts[(count($hostParts) - 1)], $reservedTopLevelDnsNames, true); + $isLocalDomain = count($hostParts) <= 1; + $isReservedTopLevel = in_array($hostParts[(count($hostParts) - 1)], $reservedTopLevelDnsNames, true); - // Exclude reserved top level DNS names - if ($isLocalDomain || $isReservedTopLevel) { - $this->error = new LocalOrReservedDomain(); - return false; - } + // Exclude reserved top level DNS names + if ($isLocalDomain || $isReservedTopLevel) { + $this->error = new LocalOrReservedDomain(); + return false; + } - return $this->checkDns($host); - } + return $this->checkDns($host); + } - public function getError() - { - return $this->error; - } + public function getError() + { + return $this->error; + } - public function getWarnings() - { - return $this->warnings; - } + public function getWarnings() + { + return $this->warnings; + } - /** - * @param string $host - * - * @return bool - */ - protected function checkDns($host) - { - $variant = INTL_IDNA_VARIANT_UTS46; + /** + * @param string $host + * + * @return bool + */ + protected function checkDns($host) + { + $variant = INTL_IDNA_VARIANT_UTS46; - $host = rtrim(idn_to_ascii($host, IDNA_DEFAULT, $variant), '.') . '.'; + $host = rtrim(idn_to_ascii($host, IDNA_DEFAULT, $variant), '.') . '.'; - return $this->validateDnsRecords($host); - } + return $this->validateDnsRecords($host); + } - /** - * Validate the DNS records for given host. - * - * @param string $host A set of DNS records in the format returned by dns_get_record. - * - * @return bool True on success. - */ - private function validateDnsRecords($host) - { - // Get all MX, A and AAAA DNS records for host - // Using @ as workaround to fix https://bugs.php.net/bug.php?id=73149 - $dnsRecords = @dns_get_record($host, DNS_MX + DNS_A + DNS_AAAA); + /** + * Validate the DNS records for given host. + * + * @param string $host A set of DNS records in the format returned by dns_get_record. + * + * @return bool True on success. + */ + private function validateDnsRecords($host) + { + // Get all MX, A and AAAA DNS records for host + // Using @ as workaround to fix https://bugs.php.net/bug.php?id=73149 + $dnsRecords = @dns_get_record($host, DNS_MX + DNS_A + DNS_AAAA); - // No MX, A or AAAA DNS records - if (empty($dnsRecords)) { - $this->error = new NoDNSRecord(); - return false; - } + // No MX, A or AAAA DNS records + if (empty($dnsRecords)) { + $this->error = new NoDNSRecord(); + return false; + } - // For each DNS record - foreach ($dnsRecords as $dnsRecord) { - if (!$this->validateMXRecord($dnsRecord)) { - return false; - } - } + // For each DNS record + foreach ($dnsRecords as $dnsRecord) { + if (!$this->validateMXRecord($dnsRecord)) { + return false; + } + } - // No MX records (fallback to A or AAAA records) - if (empty($this->mxRecords)) { - $this->warnings[NoDNSMXRecord::CODE] = new NoDNSMXRecord(); - } + // No MX records (fallback to A or AAAA records) + if (empty($this->mxRecords)) { + $this->warnings[NoDNSMXRecord::CODE] = new NoDNSMXRecord(); + } - return true; - } + return true; + } - /** - * Validate an MX record - * - * @param array $dnsRecord Given DNS record. - * - * @return bool True if valid. - */ - private function validateMxRecord($dnsRecord) - { - if ($dnsRecord['type'] !== 'MX') { - return true; - } + /** + * Validate an MX record + * + * @param array $dnsRecord Given DNS record. + * + * @return bool True if valid. + */ + private function validateMxRecord($dnsRecord) + { + if ($dnsRecord['type'] !== 'MX') { + return true; + } - // "Null MX" record indicates the domain accepts no mail (https://tools.ietf.org/html/rfc7505) - if (empty($dnsRecord['target']) || $dnsRecord['target'] === '.') { - $this->error = new DomainAcceptsNoMail(); - return false; - } + // "Null MX" record indicates the domain accepts no mail (https://tools.ietf.org/html/rfc7505) + if (empty($dnsRecord['target']) || $dnsRecord['target'] === '.') { + $this->error = new DomainAcceptsNoMail(); + return false; + } - $this->mxRecords[] = $dnsRecord; + $this->mxRecords[] = $dnsRecord; - return true; - } + return true; + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/Exception/EmptyValidationList.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/Exception/EmptyValidationList.php index ee7c41aa033..98d0d12a6d1 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/Exception/EmptyValidationList.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/Exception/EmptyValidationList.php @@ -6,11 +6,11 @@ use Exception; class EmptyValidationList extends \InvalidArgumentException { - /** - * @param int $code - */ - public function __construct($code = 0, Exception $previous = null) - { - parent::__construct("Empty validation list is not allowed", $code, $previous); - } + /** + * @param int $code + */ + public function __construct($code = 0, Exception $previous = null) + { + parent::__construct("Empty validation list is not allowed", $code, $previous); + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/MultipleErrors.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/MultipleErrors.php index 3be59732664..cd10ec7aaf8 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/MultipleErrors.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/MultipleErrors.php @@ -6,27 +6,27 @@ use Egulias\EmailValidator\Exception\InvalidEmail; class MultipleErrors extends InvalidEmail { - const CODE = 999; - const REASON = "Accumulated errors for multiple validations"; - /** - * @var InvalidEmail[] - */ - private $errors = []; + const CODE = 999; + const REASON = "Accumulated errors for multiple validations"; + /** + * @var InvalidEmail[] + */ + private $errors = []; - /** - * @param InvalidEmail[] $errors - */ - public function __construct(array $errors) - { - $this->errors = $errors; - parent::__construct(); - } + /** + * @param InvalidEmail[] $errors + */ + public function __construct(array $errors) + { + $this->errors = $errors; + parent::__construct(); + } - /** - * @return InvalidEmail[] - */ - public function getErrors() - { - return $this->errors; - } + /** + * @return InvalidEmail[] + */ + public function getErrors() + { + return $this->errors; + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/MultipleValidationWithAnd.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/MultipleValidationWithAnd.php index feb224023da..55aad31459b 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/MultipleValidationWithAnd.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/MultipleValidationWithAnd.php @@ -7,118 +7,118 @@ use Egulias\EmailValidator\Validation\Exception\EmptyValidationList; class MultipleValidationWithAnd implements EmailValidation { - /** - * If one of validations gets failure skips all succeeding validation. - * This means MultipleErrors will only contain a single error which first found. - */ - const STOP_ON_ERROR = 0; + /** + * If one of validations gets failure skips all succeeding validation. + * This means MultipleErrors will only contain a single error which first found. + */ + const STOP_ON_ERROR = 0; - /** - * All of validations will be invoked even if one of them got failure. - * So MultipleErrors will contain all causes. - */ - const ALLOW_ALL_ERRORS = 1; + /** + * All of validations will be invoked even if one of them got failure. + * So MultipleErrors will contain all causes. + */ + const ALLOW_ALL_ERRORS = 1; - /** - * @var EmailValidation[] - */ - private $validations = []; + /** + * @var EmailValidation[] + */ + private $validations = []; - /** - * @var array - */ - private $warnings = []; + /** + * @var array + */ + private $warnings = []; - /** - * @var MultipleErrors|null - */ - private $error; + /** + * @var MultipleErrors|null + */ + private $error; - /** - * @var int - */ - private $mode; + /** + * @var int + */ + private $mode; - /** - * @param EmailValidation[] $validations The validations. - * @param int $mode The validation mode (one of the constants). - */ - public function __construct(array $validations, $mode = self::ALLOW_ALL_ERRORS) - { - if (count($validations) == 0) { - throw new EmptyValidationList(); - } + /** + * @param EmailValidation[] $validations The validations. + * @param int $mode The validation mode (one of the constants). + */ + public function __construct(array $validations, $mode = self::ALLOW_ALL_ERRORS) + { + if (count($validations) == 0) { + throw new EmptyValidationList(); + } - $this->validations = $validations; - $this->mode = $mode; - } + $this->validations = $validations; + $this->mode = $mode; + } - /** - * {@inheritdoc} - */ - public function isValid($email, EmailLexer $emailLexer) - { - $result = true; - $errors = []; - foreach ($this->validations as $validation) { - $emailLexer->reset(); - $validationResult = $validation->isValid($email, $emailLexer); - $result = $result && $validationResult; - $this->warnings = array_merge($this->warnings, $validation->getWarnings()); - $errors = $this->addNewError($validation->getError(), $errors); + /** + * {@inheritdoc} + */ + public function isValid($email, EmailLexer $emailLexer) + { + $result = true; + $errors = []; + foreach ($this->validations as $validation) { + $emailLexer->reset(); + $validationResult = $validation->isValid($email, $emailLexer); + $result = $result && $validationResult; + $this->warnings = array_merge($this->warnings, $validation->getWarnings()); + $errors = $this->addNewError($validation->getError(), $errors); - if ($this->shouldStop($result)) { - break; - } - } + if ($this->shouldStop($result)) { + break; + } + } - if (!empty($errors)) { - $this->error = new MultipleErrors($errors); - } + if (!empty($errors)) { + $this->error = new MultipleErrors($errors); + } - return $result; - } + return $result; + } - /** - * @param \Egulias\EmailValidator\Exception\InvalidEmail|null $possibleError - * @param \Egulias\EmailValidator\Exception\InvalidEmail[] $errors - * - * @return \Egulias\EmailValidator\Exception\InvalidEmail[] - */ - private function addNewError($possibleError, array $errors) - { - if (null !== $possibleError) { - $errors[] = $possibleError; - } + /** + * @param \Egulias\EmailValidator\Exception\InvalidEmail|null $possibleError + * @param \Egulias\EmailValidator\Exception\InvalidEmail[] $errors + * + * @return \Egulias\EmailValidator\Exception\InvalidEmail[] + */ + private function addNewError($possibleError, array $errors) + { + if (null !== $possibleError) { + $errors[] = $possibleError; + } - return $errors; - } + return $errors; + } - /** - * @param bool $result - * - * @return bool - */ - private function shouldStop($result) - { - return !$result && $this->mode === self::STOP_ON_ERROR; - } + /** + * @param bool $result + * + * @return bool + */ + private function shouldStop($result) + { + return !$result && $this->mode === self::STOP_ON_ERROR; + } - /** - * Returns the validation errors. - * - * @return MultipleErrors|null - */ - public function getError() - { - return $this->error; - } + /** + * Returns the validation errors. + * + * @return MultipleErrors|null + */ + public function getError() + { + return $this->error; + } - /** - * {@inheritdoc} - */ - public function getWarnings() - { - return $this->warnings; - } + /** + * {@inheritdoc} + */ + public function getWarnings() + { + return $this->warnings; + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/NoRFCWarningsValidation.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/NoRFCWarningsValidation.php index 6b31e5440ec..b7b3bb90910 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/NoRFCWarningsValidation.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/NoRFCWarningsValidation.php @@ -8,34 +8,34 @@ use Egulias\EmailValidator\Validation\Error\RFCWarnings; class NoRFCWarningsValidation extends RFCValidation { - /** - * @var InvalidEmail|null - */ - private $error; + /** + * @var InvalidEmail|null + */ + private $error; - /** - * {@inheritdoc} - */ - public function isValid($email, EmailLexer $emailLexer) - { - if (!parent::isValid($email, $emailLexer)) { - return false; - } + /** + * {@inheritdoc} + */ + public function isValid($email, EmailLexer $emailLexer) + { + if (!parent::isValid($email, $emailLexer)) { + return false; + } - if (empty($this->getWarnings())) { - return true; - } + if (empty($this->getWarnings())) { + return true; + } - $this->error = new RFCWarnings(); + $this->error = new RFCWarnings(); - return false; - } + return false; + } - /** - * {@inheritdoc} - */ - public function getError() - { - return $this->error ?: parent::getError(); - } + /** + * {@inheritdoc} + */ + public function getError() + { + return $this->error ?: parent::getError(); + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/RFCValidation.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/RFCValidation.php index 8781e0b62d1..813da231844 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/RFCValidation.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/RFCValidation.php @@ -8,42 +8,42 @@ use Egulias\EmailValidator\Exception\InvalidEmail; class RFCValidation implements EmailValidation { - /** - * @var EmailParser|null - */ - private $parser; + /** + * @var EmailParser|null + */ + private $parser; - /** - * @var array - */ - private $warnings = []; + /** + * @var array + */ + private $warnings = []; - /** - * @var InvalidEmail|null - */ - private $error; + /** + * @var InvalidEmail|null + */ + private $error; - public function isValid($email, EmailLexer $emailLexer) - { - $this->parser = new EmailParser($emailLexer); - try { - $this->parser->parse((string)$email); - } catch (InvalidEmail $invalid) { - $this->error = $invalid; - return false; - } + public function isValid($email, EmailLexer $emailLexer) + { + $this->parser = new EmailParser($emailLexer); + try { + $this->parser->parse((string) $email); + } catch (InvalidEmail $invalid) { + $this->error = $invalid; + return false; + } - $this->warnings = $this->parser->getWarnings(); - return true; - } + $this->warnings = $this->parser->getWarnings(); + return true; + } - public function getError() - { - return $this->error; - } + public function getError() + { + return $this->error; + } - public function getWarnings() - { - return $this->warnings; - } + public function getWarnings() + { + return $this->warnings; + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/SpoofCheckValidation.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/SpoofCheckValidation.php index e10bfabd92f..65c017a3ce2 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/SpoofCheckValidation.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/SpoofCheckValidation.php @@ -9,43 +9,43 @@ use \Spoofchecker; class SpoofCheckValidation implements EmailValidation { - /** - * @var InvalidEmail|null - */ - private $error; + /** + * @var InvalidEmail|null + */ + private $error; - public function __construct() - { - if (!extension_loaded('intl')) { - throw new \LogicException(sprintf('The %s class requires the Intl extension.', __CLASS__)); - } - } + public function __construct() + { + if (!extension_loaded('intl')) { + throw new \LogicException(sprintf('The %s class requires the Intl extension.', __CLASS__)); + } + } - /** - * @psalm-suppress InvalidArgument - */ - public function isValid($email, EmailLexer $emailLexer) - { - $checker = new Spoofchecker(); - $checker->setChecks(Spoofchecker::SINGLE_SCRIPT); + /** + * @psalm-suppress InvalidArgument + */ + public function isValid($email, EmailLexer $emailLexer) + { + $checker = new Spoofchecker(); + $checker->setChecks(Spoofchecker::SINGLE_SCRIPT); - if ($checker->isSuspicious($email)) { - $this->error = new SpoofEmail(); - } + if ($checker->isSuspicious($email)) { + $this->error = new SpoofEmail(); + } - return $this->error === null; - } + return $this->error === null; + } - /** - * @return InvalidEmail|null - */ - public function getError() - { - return $this->error; - } + /** + * @return InvalidEmail|null + */ + public function getError() + { + return $this->error; + } - public function getWarnings() - { - return []; - } + public function getWarnings() + { + return []; + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Warning/QuotedPart.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Warning/QuotedPart.php index 36a4265a515..dd2cf28d0d8 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Warning/QuotedPart.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Warning/QuotedPart.php @@ -4,14 +4,14 @@ namespace Egulias\EmailValidator\Warning; class QuotedPart extends Warning { - const CODE = 36; + const CODE = 36; - /** - * @param scalar $prevToken - * @param scalar $postToken - */ - public function __construct($prevToken, $postToken) - { - $this->message = "Deprecated Quoted String found between $prevToken and $postToken"; - } + /** + * @param scalar $prevToken + * @param scalar $postToken + */ + public function __construct($prevToken, $postToken) + { + $this->message = "Deprecated Quoted String found between $prevToken and $postToken"; + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Warning/QuotedString.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Warning/QuotedString.php index 817e4e84b07..d1f99b905c6 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Warning/QuotedString.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Warning/QuotedString.php @@ -4,14 +4,14 @@ namespace Egulias\EmailValidator\Warning; class QuotedString extends Warning { - const CODE = 11; + const CODE = 11; - /** - * @param scalar $prevToken - * @param scalar $postToken - */ - public function __construct($prevToken, $postToken) - { - $this->message = "Quoted String found between $prevToken and $postToken"; - } + /** + * @param scalar $prevToken + * @param scalar $postToken + */ + public function __construct($prevToken, $postToken) + { + $this->message = "Quoted String found between $prevToken and $postToken"; + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Warning/Warning.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Warning/Warning.php index a2ee7b0de1e..0ecd5ab9244 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Warning/Warning.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Warning/Warning.php @@ -4,44 +4,44 @@ namespace Egulias\EmailValidator\Warning; abstract class Warning { - const CODE = 0; + const CODE = 0; - /** - * @var string - */ - protected $message = ''; + /** + * @var string + */ + protected $message = ''; - /** - * @var int - */ - protected $rfcNumber = 0; + /** + * @var int + */ + protected $rfcNumber = 0; - /** - * @return string - */ - public function message() - { - return $this->message; - } + /** + * @return string + */ + public function message() + { + return $this->message; + } - /** - * @return int - */ - public function code() - { - return static::CODE; - } + /** + * @return int + */ + public function code() + { + return static::CODE; + } - /** - * @return int - */ - public function RFCNumber() - { - return $this->rfcNumber; - } + /** + * @return int + */ + public function RFCNumber() + { + return $this->rfcNumber; + } - public function __toString() - { - return $this->message() . " rfc: " . $this->rfcNumber . "interal code: " . static::CODE; - } + public function __toString() + { + return $this->message() . " rfc: " . $this->rfcNumber . "interal code: " . static::CODE; + } } diff --git a/htdocs/includes/swiftmailer/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php b/htdocs/includes/swiftmailer/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php index dd3ea768e3b..a561a6678f9 100644 --- a/htdocs/includes/swiftmailer/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php +++ b/htdocs/includes/swiftmailer/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php @@ -29,304 +29,304 @@ namespace Doctrine\Common\Lexer; */ abstract class AbstractLexer { - /** - * Lexer original input string. - * - * @var string - */ - private $input; + /** + * Lexer original input string. + * + * @var string + */ + private $input; - /** - * Array of scanned tokens. - * - * Each token is an associative array containing three items: - * - 'value' : the string value of the token in the input string - * - 'type' : the type of the token (identifier, numeric, string, input - * parameter, none) - * - 'position' : the position of the token in the input string - * - * @var array - */ - private $tokens = array(); + /** + * Array of scanned tokens. + * + * Each token is an associative array containing three items: + * - 'value' : the string value of the token in the input string + * - 'type' : the type of the token (identifier, numeric, string, input + * parameter, none) + * - 'position' : the position of the token in the input string + * + * @var array + */ + private $tokens = array(); - /** - * Current lexer position in input string. - * - * @var integer - */ - private $position = 0; + /** + * Current lexer position in input string. + * + * @var integer + */ + private $position = 0; - /** - * Current peek of current lexer position. - * - * @var integer - */ - private $peek = 0; + /** + * Current peek of current lexer position. + * + * @var integer + */ + private $peek = 0; - /** - * The next token in the input. - * - * @var array - */ - public $lookahead; + /** + * The next token in the input. + * + * @var array + */ + public $lookahead; - /** - * The last matched/seen token. - * - * @var array - */ - public $token; + /** + * The last matched/seen token. + * + * @var array + */ + public $token; - /** - * Sets the input data to be tokenized. - * - * The Lexer is immediately reset and the new input tokenized. - * Any unprocessed tokens from any previous input are lost. - * - * @param string $input The input to be tokenized. - * - * @return void - */ - public function setInput($input) - { - $this->input = $input; - $this->tokens = array(); + /** + * Sets the input data to be tokenized. + * + * The Lexer is immediately reset and the new input tokenized. + * Any unprocessed tokens from any previous input are lost. + * + * @param string $input The input to be tokenized. + * + * @return void + */ + public function setInput($input) + { + $this->input = $input; + $this->tokens = array(); - $this->reset(); - $this->scan($input); - } + $this->reset(); + $this->scan($input); + } - /** - * Resets the lexer. - * - * @return void - */ - public function reset() - { - $this->lookahead = null; - $this->token = null; - $this->peek = 0; - $this->position = 0; - } + /** + * Resets the lexer. + * + * @return void + */ + public function reset() + { + $this->lookahead = null; + $this->token = null; + $this->peek = 0; + $this->position = 0; + } - /** - * Resets the peek pointer to 0. - * - * @return void - */ - public function resetPeek() - { - $this->peek = 0; - } + /** + * Resets the peek pointer to 0. + * + * @return void + */ + public function resetPeek() + { + $this->peek = 0; + } - /** - * Resets the lexer position on the input to the given position. - * - * @param integer $position Position to place the lexical scanner. - * - * @return void - */ - public function resetPosition($position = 0) - { - $this->position = $position; - } + /** + * Resets the lexer position on the input to the given position. + * + * @param integer $position Position to place the lexical scanner. + * + * @return void + */ + public function resetPosition($position = 0) + { + $this->position = $position; + } - /** - * Retrieve the original lexer's input until a given position. - * - * @param integer $position - * - * @return string - */ - public function getInputUntilPosition($position) - { - return substr($this->input, 0, $position); - } + /** + * Retrieve the original lexer's input until a given position. + * + * @param integer $position + * + * @return string + */ + public function getInputUntilPosition($position) + { + return substr($this->input, 0, $position); + } - /** - * Checks whether a given token matches the current lookahead. - * - * @param integer|string $token - * - * @return boolean - */ - public function isNextToken($token) - { - return null !== $this->lookahead && $this->lookahead['type'] === $token; - } + /** + * Checks whether a given token matches the current lookahead. + * + * @param integer|string $token + * + * @return boolean + */ + public function isNextToken($token) + { + return null !== $this->lookahead && $this->lookahead['type'] === $token; + } - /** - * Checks whether any of the given tokens matches the current lookahead. - * - * @param array $tokens - * - * @return boolean - */ - public function isNextTokenAny(array $tokens) - { - return null !== $this->lookahead && in_array($this->lookahead['type'], $tokens, true); - } + /** + * Checks whether any of the given tokens matches the current lookahead. + * + * @param array $tokens + * + * @return boolean + */ + public function isNextTokenAny(array $tokens) + { + return null !== $this->lookahead && in_array($this->lookahead['type'], $tokens, true); + } - /** - * Moves to the next token in the input string. - * - * @return boolean - */ - public function moveNext() - { - $this->peek = 0; - $this->token = $this->lookahead; - $this->lookahead = (isset($this->tokens[$this->position])) - ? $this->tokens[$this->position++] : null; + /** + * Moves to the next token in the input string. + * + * @return boolean + */ + public function moveNext() + { + $this->peek = 0; + $this->token = $this->lookahead; + $this->lookahead = (isset($this->tokens[$this->position])) + ? $this->tokens[$this->position++] : null; - return $this->lookahead !== null; - } + return $this->lookahead !== null; + } - /** - * Tells the lexer to skip input tokens until it sees a token with the given value. - * - * @param string $type The token type to skip until. - * - * @return void - */ - public function skipUntil($type) - { - while ($this->lookahead !== null && $this->lookahead['type'] !== $type) { - $this->moveNext(); - } - } + /** + * Tells the lexer to skip input tokens until it sees a token with the given value. + * + * @param string $type The token type to skip until. + * + * @return void + */ + public function skipUntil($type) + { + while ($this->lookahead !== null && $this->lookahead['type'] !== $type) { + $this->moveNext(); + } + } - /** - * Checks if given value is identical to the given token. - * - * @param mixed $value - * @param integer $token - * - * @return boolean - */ - public function isA($value, $token) - { - return $this->getType($value) === $token; - } + /** + * Checks if given value is identical to the given token. + * + * @param mixed $value + * @param integer $token + * + * @return boolean + */ + public function isA($value, $token) + { + return $this->getType($value) === $token; + } - /** - * Moves the lookahead token forward. - * - * @return array|null The next token or NULL if there are no more tokens ahead. - */ - public function peek() - { - if (isset($this->tokens[$this->position + $this->peek])) { - return $this->tokens[$this->position + $this->peek++]; - } else { - return null; - } - } + /** + * Moves the lookahead token forward. + * + * @return array|null The next token or NULL if there are no more tokens ahead. + */ + public function peek() + { + if (isset($this->tokens[$this->position + $this->peek])) { + return $this->tokens[$this->position + $this->peek++]; + } else { + return null; + } + } - /** - * Peeks at the next token, returns it and immediately resets the peek. - * - * @return array|null The next token or NULL if there are no more tokens ahead. - */ - public function glimpse() - { - $peek = $this->peek(); - $this->peek = 0; - return $peek; - } + /** + * Peeks at the next token, returns it and immediately resets the peek. + * + * @return array|null The next token or NULL if there are no more tokens ahead. + */ + public function glimpse() + { + $peek = $this->peek(); + $this->peek = 0; + return $peek; + } - /** - * Scans the input string for tokens. - * - * @param string $input A query string. - * - * @return void - */ - protected function scan($input) - { - static $regex; + /** + * Scans the input string for tokens. + * + * @param string $input A query string. + * + * @return void + */ + protected function scan($input) + { + static $regex; - if ( ! isset($regex)) { - $regex = sprintf( - '/(%s)|%s/%s', - implode(')|(', $this->getCatchablePatterns()), - implode('|', $this->getNonCatchablePatterns()), - $this->getModifiers() - ); - } + if ( ! isset($regex)) { + $regex = sprintf( + '/(%s)|%s/%s', + implode(')|(', $this->getCatchablePatterns()), + implode('|', $this->getNonCatchablePatterns()), + $this->getModifiers() + ); + } - $flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE; - $matches = preg_split($regex, $input, -1, $flags); + $flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE; + $matches = preg_split($regex, $input, -1, $flags); - if (false === $matches) { - // Work around https://bugs.php.net/78122 - $matches = array(array($input, 0)); - } + if (false === $matches) { + // Work around https://bugs.php.net/78122 + $matches = array(array($input, 0)); + } - foreach ($matches as $match) { - // Must remain before 'value' assignment since it can change content - $type = $this->getType($match[0]); + foreach ($matches as $match) { + // Must remain before 'value' assignment since it can change content + $type = $this->getType($match[0]); - $this->tokens[] = array( - 'value' => $match[0], - 'type' => $type, - 'position' => $match[1], - ); - } - } + $this->tokens[] = array( + 'value' => $match[0], + 'type' => $type, + 'position' => $match[1], + ); + } + } - /** - * Gets the literal for a given token. - * - * @param integer $token - * - * @return string - */ - public function getLiteral($token) - { - $className = get_class($this); - $reflClass = new \ReflectionClass($className); - $constants = $reflClass->getConstants(); + /** + * Gets the literal for a given token. + * + * @param integer $token + * + * @return string + */ + public function getLiteral($token) + { + $className = get_class($this); + $reflClass = new \ReflectionClass($className); + $constants = $reflClass->getConstants(); - foreach ($constants as $name => $value) { - if ($value === $token) { - return $className . '::' . $name; - } - } + foreach ($constants as $name => $value) { + if ($value === $token) { + return $className . '::' . $name; + } + } - return $token; - } + return $token; + } - /** - * Regex modifiers - * - * @return string - */ - protected function getModifiers() - { - return 'i'; - } + /** + * Regex modifiers + * + * @return string + */ + protected function getModifiers() + { + return 'i'; + } - /** - * Lexical catchable patterns. - * - * @return array - */ - abstract protected function getCatchablePatterns(); + /** + * Lexical catchable patterns. + * + * @return array + */ + abstract protected function getCatchablePatterns(); - /** - * Lexical non-catchable patterns. - * - * @return array - */ - abstract protected function getNonCatchablePatterns(); + /** + * Lexical non-catchable patterns. + * + * @return array + */ + abstract protected function getNonCatchablePatterns(); - /** - * Retrieve token type. Also processes the token value if necessary. - * - * @param string $value - * - * @return integer - */ - abstract protected function getType(&$value); + /** + * Retrieve token type. Also processes the token value if necessary. + * + * @param string $value + * + * @return integer + */ + abstract protected function getType(&$value); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift.php b/htdocs/includes/swiftmailer/lib/classes/Swift.php index 51b19c9cb4e..09cdc4fbefd 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift.php @@ -15,64 +15,64 @@ */ abstract class Swift { - const VERSION = '6.3.0'; + const VERSION = '6.3.0'; - public static $initialized = false; - public static $inits = []; + public static $initialized = false; + public static $inits = []; - /** - * Registers an initializer callable that will be called the first time - * a SwiftMailer class is autoloaded. - * - * This enables you to tweak the default configuration in a lazy way. - * - * @param mixed $callable A valid PHP callable that will be called when autoloading the first Swift class - */ - public static function init($callable) - { - self::$inits[] = $callable; - } + /** + * Registers an initializer callable that will be called the first time + * a SwiftMailer class is autoloaded. + * + * This enables you to tweak the default configuration in a lazy way. + * + * @param mixed $callable A valid PHP callable that will be called when autoloading the first Swift class + */ + public static function init($callable) + { + self::$inits[] = $callable; + } - /** - * Internal autoloader for spl_autoload_register(). - * - * @param string $class - */ - public static function autoload($class) - { - // Don't interfere with other autoloaders - if (0 !== strpos($class, 'Swift_')) { - return; - } + /** + * Internal autoloader for spl_autoload_register(). + * + * @param string $class + */ + public static function autoload($class) + { + // Don't interfere with other autoloaders + if (0 !== strpos($class, 'Swift_')) { + return; + } - $path = __DIR__.'/'.str_replace('_', '/', $class).'.php'; + $path = __DIR__.'/'.str_replace('_', '/', $class).'.php'; - if (!file_exists($path)) { - return; - } + if (!file_exists($path)) { + return; + } - require $path; + require $path; - if (self::$inits && !self::$initialized) { - self::$initialized = true; - foreach (self::$inits as $init) { - \call_user_func($init); - } - } - } + if (self::$inits && !self::$initialized) { + self::$initialized = true; + foreach (self::$inits as $init) { + \call_user_func($init); + } + } + } - /** - * Configure autoloading using Swift Mailer. - * - * This is designed to play nicely with other autoloaders. - * - * @param mixed $callable A valid PHP callable that will be called when autoloading the first Swift class - */ - public static function registerAutoload($callable = null) - { - if (null !== $callable) { - self::$inits[] = $callable; - } - spl_autoload_register(['Swift', 'autoload']); - } + /** + * Configure autoloading using Swift Mailer. + * + * This is designed to play nicely with other autoloaders. + * + * @param mixed $callable A valid PHP callable that will be called when autoloading the first Swift class + */ + public static function registerAutoload($callable = null) + { + if (null !== $callable) { + self::$inits[] = $callable; + } + spl_autoload_register(['Swift', 'autoload']); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoder.php b/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoder.php index a1704ffb40a..643060e12c1 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoder.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoder.php @@ -15,11 +15,11 @@ */ interface Swift_AddressEncoder { - /** - * Encodes an email address. - * - * @throws Swift_AddressEncoderException if the email cannot be represented in - * the encoding implemented by this class - */ - public function encodeString(string $address): string; + /** + * Encodes an email address. + * + * @throws Swift_AddressEncoderException if the email cannot be represented in + * the encoding implemented by this class + */ + public function encodeString(string $address): string; } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoder/IdnAddressEncoder.php b/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoder/IdnAddressEncoder.php index a373ef9d546..a00f90efa5e 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoder/IdnAddressEncoder.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoder/IdnAddressEncoder.php @@ -24,27 +24,27 @@ */ class Swift_AddressEncoder_IdnAddressEncoder implements Swift_AddressEncoder { - /** - * Encodes the domain part of an address using IDN. - * - * @throws Swift_AddressEncoderException If local-part contains non-ASCII characters - */ - public function encodeString(string $address): string - { - $i = strrpos($address, '@'); - if (false !== $i) { - $local = substr($address, 0, $i); - $domain = substr($address, $i + 1); + /** + * Encodes the domain part of an address using IDN. + * + * @throws Swift_AddressEncoderException If local-part contains non-ASCII characters + */ + public function encodeString(string $address): string + { + $i = strrpos($address, '@'); + if (false !== $i) { + $local = substr($address, 0, $i); + $domain = substr($address, $i + 1); - if (preg_match('/[^\x00-\x7F]/', $local)) { - throw new Swift_AddressEncoderException('Non-ASCII characters not supported in local-part', $address); - } + if (preg_match('/[^\x00-\x7F]/', $local)) { + throw new Swift_AddressEncoderException('Non-ASCII characters not supported in local-part', $address); + } - if (preg_match('/[^\x00-\x7F]/', $domain)) { - $address = sprintf('%s@%s', $local, idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46)); - } - } + if (preg_match('/[^\x00-\x7F]/', $domain)) { + $address = sprintf('%s@%s', $local, idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46)); + } + } - return $address; - } + return $address; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoder/Utf8AddressEncoder.php b/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoder/Utf8AddressEncoder.php index 1b454305678..29de0f5cc93 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoder/Utf8AddressEncoder.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoder/Utf8AddressEncoder.php @@ -26,11 +26,11 @@ */ class Swift_AddressEncoder_Utf8AddressEncoder implements Swift_AddressEncoder { - /** - * Returns the address verbatimly. - */ - public function encodeString(string $address): string - { - return $address; - } + /** + * Returns the address verbatimly. + */ + public function encodeString(string $address): string + { + return $address; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoderException.php b/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoderException.php index 9b405476bcb..7d499f1deaf 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoderException.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoderException.php @@ -16,17 +16,17 @@ */ class Swift_AddressEncoderException extends Swift_RfcComplianceException { - protected $address; + protected $address; - public function __construct(string $message, string $address) - { - parent::__construct($message); + public function __construct(string $message, string $address) + { + parent::__construct($message); - $this->address = $address; - } + $this->address = $address; + } - public function getAddress(): string - { - return $this->address; - } + public function getAddress(): string + { + return $this->address; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Attachment.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Attachment.php index 7a1420f7986..f759001ad4e 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Attachment.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Attachment.php @@ -15,40 +15,40 @@ */ class Swift_Attachment extends Swift_Mime_Attachment { - /** - * Create a new Attachment. - * - * Details may be optionally provided to the constructor. - * - * @param string|Swift_OutputByteStream $data - * @param string $filename - * @param string $contentType - */ - public function __construct($data = null, $filename = null, $contentType = null) - { - \call_user_func_array( - [$this, 'Swift_Mime_Attachment::__construct'], - Swift_DependencyContainer::getInstance() - ->createDependenciesFor('mime.attachment') - ); + /** + * Create a new Attachment. + * + * Details may be optionally provided to the constructor. + * + * @param string|Swift_OutputByteStream $data + * @param string $filename + * @param string $contentType + */ + public function __construct($data = null, $filename = null, $contentType = null) + { + \call_user_func_array( + [$this, 'Swift_Mime_Attachment::__construct'], + Swift_DependencyContainer::getInstance() + ->createDependenciesFor('mime.attachment') + ); - $this->setBody($data, $contentType); - $this->setFilename($filename); - } + $this->setBody($data, $contentType); + $this->setFilename($filename); + } - /** - * Create a new Attachment from a filesystem path. - * - * @param string $path - * @param string $contentType optional - * - * @return self - */ - public static function fromPath($path, $contentType = null) - { - return (new self())->setFile( - new Swift_ByteStream_FileByteStream($path), - $contentType - ); - } + /** + * Create a new Attachment from a filesystem path. + * + * @param string $path + * @param string $contentType optional + * + * @return self + */ + public static function fromPath($path, $contentType = null) + { + return (new self())->setFile( + new Swift_ByteStream_FileByteStream($path), + $contentType + ); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/AbstractFilterableInputStream.php b/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/AbstractFilterableInputStream.php index 3a69c15f1c4..0f7833c3a19 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/AbstractFilterableInputStream.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/AbstractFilterableInputStream.php @@ -15,162 +15,162 @@ */ abstract class Swift_ByteStream_AbstractFilterableInputStream implements Swift_InputByteStream, Swift_Filterable { - /** - * Write sequence. - */ - protected $sequence = 0; + /** + * Write sequence. + */ + protected $sequence = 0; - /** - * StreamFilters. - * - * @var Swift_StreamFilter[] - */ - private $filters = []; + /** + * StreamFilters. + * + * @var Swift_StreamFilter[] + */ + private $filters = []; - /** - * A buffer for writing. - */ - private $writeBuffer = ''; + /** + * A buffer for writing. + */ + private $writeBuffer = ''; - /** - * Bound streams. - * - * @var Swift_InputByteStream[] - */ - private $mirrors = []; + /** + * Bound streams. + * + * @var Swift_InputByteStream[] + */ + private $mirrors = []; - /** - * Commit the given bytes to the storage medium immediately. - * - * @param string $bytes - */ - abstract protected function doCommit($bytes); + /** + * Commit the given bytes to the storage medium immediately. + * + * @param string $bytes + */ + abstract protected function doCommit($bytes); - /** - * Flush any buffers/content with immediate effect. - */ - abstract protected function flush(); + /** + * Flush any buffers/content with immediate effect. + */ + abstract protected function flush(); - /** - * Add a StreamFilter to this InputByteStream. - * - * @param string $key - */ - public function addFilter(Swift_StreamFilter $filter, $key) - { - $this->filters[$key] = $filter; - } + /** + * Add a StreamFilter to this InputByteStream. + * + * @param string $key + */ + public function addFilter(Swift_StreamFilter $filter, $key) + { + $this->filters[$key] = $filter; + } - /** - * Remove an already present StreamFilter based on its $key. - * - * @param string $key - */ - public function removeFilter($key) - { - unset($this->filters[$key]); - } + /** + * Remove an already present StreamFilter based on its $key. + * + * @param string $key + */ + public function removeFilter($key) + { + unset($this->filters[$key]); + } - /** - * Writes $bytes to the end of the stream. - * - * @param string $bytes - * - * @throws Swift_IoException - * - * @return int - */ - public function write($bytes) - { - $this->writeBuffer .= $bytes; - foreach ($this->filters as $filter) { - if ($filter->shouldBuffer($this->writeBuffer)) { - return; - } - } - $this->doWrite($this->writeBuffer); + /** + * Writes $bytes to the end of the stream. + * + * @param string $bytes + * + * @throws Swift_IoException + * + * @return int + */ + public function write($bytes) + { + $this->writeBuffer .= $bytes; + foreach ($this->filters as $filter) { + if ($filter->shouldBuffer($this->writeBuffer)) { + return; + } + } + $this->doWrite($this->writeBuffer); - return ++$this->sequence; - } + return ++$this->sequence; + } - /** - * For any bytes that are currently buffered inside the stream, force them - * off the buffer. - * - * @throws Swift_IoException - */ - public function commit() - { - $this->doWrite($this->writeBuffer); - } + /** + * For any bytes that are currently buffered inside the stream, force them + * off the buffer. + * + * @throws Swift_IoException + */ + public function commit() + { + $this->doWrite($this->writeBuffer); + } - /** - * Attach $is to this stream. - * - * The stream acts as an observer, receiving all data that is written. - * All {@link write()} and {@link flushBuffers()} operations will be mirrored. - */ - public function bind(Swift_InputByteStream $is) - { - $this->mirrors[] = $is; - } + /** + * Attach $is to this stream. + * + * The stream acts as an observer, receiving all data that is written. + * All {@link write()} and {@link flushBuffers()} operations will be mirrored. + */ + public function bind(Swift_InputByteStream $is) + { + $this->mirrors[] = $is; + } - /** - * Remove an already bound stream. - * - * If $is is not bound, no errors will be raised. - * If the stream currently has any buffered data it will be written to $is - * before unbinding occurs. - */ - public function unbind(Swift_InputByteStream $is) - { - foreach ($this->mirrors as $k => $stream) { - if ($is === $stream) { - if ('' !== $this->writeBuffer) { - $stream->write($this->writeBuffer); - } - unset($this->mirrors[$k]); - } - } - } + /** + * Remove an already bound stream. + * + * If $is is not bound, no errors will be raised. + * If the stream currently has any buffered data it will be written to $is + * before unbinding occurs. + */ + public function unbind(Swift_InputByteStream $is) + { + foreach ($this->mirrors as $k => $stream) { + if ($is === $stream) { + if ('' !== $this->writeBuffer) { + $stream->write($this->writeBuffer); + } + unset($this->mirrors[$k]); + } + } + } - /** - * Flush the contents of the stream (empty it) and set the internal pointer - * to the beginning. - * - * @throws Swift_IoException - */ - public function flushBuffers() - { - if ('' !== $this->writeBuffer) { - $this->doWrite($this->writeBuffer); - } - $this->flush(); + /** + * Flush the contents of the stream (empty it) and set the internal pointer + * to the beginning. + * + * @throws Swift_IoException + */ + public function flushBuffers() + { + if ('' !== $this->writeBuffer) { + $this->doWrite($this->writeBuffer); + } + $this->flush(); - foreach ($this->mirrors as $stream) { - $stream->flushBuffers(); - } - } + foreach ($this->mirrors as $stream) { + $stream->flushBuffers(); + } + } - /** Run $bytes through all filters */ - private function filter($bytes) - { - foreach ($this->filters as $filter) { - $bytes = $filter->filter($bytes); - } + /** Run $bytes through all filters */ + private function filter($bytes) + { + foreach ($this->filters as $filter) { + $bytes = $filter->filter($bytes); + } - return $bytes; - } + return $bytes; + } - /** Just write the bytes to the stream */ - private function doWrite($bytes) - { - $this->doCommit($this->filter($bytes)); + /** Just write the bytes to the stream */ + private function doWrite($bytes) + { + $this->doCommit($this->filter($bytes)); - foreach ($this->mirrors as $stream) { - $stream->write($bytes); - } + foreach ($this->mirrors as $stream) { + $stream->write($bytes); + } - $this->writeBuffer = ''; - } + $this->writeBuffer = ''; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/ArrayByteStream.php b/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/ArrayByteStream.php index 4f3dcc37745..53d5cef10a0 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/ArrayByteStream.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/ArrayByteStream.php @@ -15,164 +15,164 @@ */ class Swift_ByteStream_ArrayByteStream implements Swift_InputByteStream, Swift_OutputByteStream { - /** - * The internal stack of bytes. - * - * @var string[] - */ - private $array = []; + /** + * The internal stack of bytes. + * + * @var string[] + */ + private $array = []; - /** - * The size of the stack. - * - * @var int - */ - private $arraySize = 0; + /** + * The size of the stack. + * + * @var int + */ + private $arraySize = 0; - /** - * The internal pointer offset. - * - * @var int - */ - private $offset = 0; + /** + * The internal pointer offset. + * + * @var int + */ + private $offset = 0; - /** - * Bound streams. - * - * @var Swift_InputByteStream[] - */ - private $mirrors = []; + /** + * Bound streams. + * + * @var Swift_InputByteStream[] + */ + private $mirrors = []; - /** - * Create a new ArrayByteStream. - * - * If $stack is given the stream will be populated with the bytes it contains. - * - * @param mixed $stack of bytes in string or array form, optional - */ - public function __construct($stack = null) - { - if (\is_array($stack)) { - $this->array = $stack; - $this->arraySize = \count($stack); - } elseif (\is_string($stack)) { - $this->write($stack); - } else { - $this->array = []; - } - } + /** + * Create a new ArrayByteStream. + * + * If $stack is given the stream will be populated with the bytes it contains. + * + * @param mixed $stack of bytes in string or array form, optional + */ + public function __construct($stack = null) + { + if (\is_array($stack)) { + $this->array = $stack; + $this->arraySize = \count($stack); + } elseif (\is_string($stack)) { + $this->write($stack); + } else { + $this->array = []; + } + } - /** - * Reads $length bytes from the stream into a string and moves the pointer - * through the stream by $length. - * - * If less bytes exist than are requested the - * remaining bytes are given instead. If no bytes are remaining at all, boolean - * false is returned. - * - * @param int $length - * - * @return string - */ - public function read($length) - { - if ($this->offset == $this->arraySize) { - return false; - } + /** + * Reads $length bytes from the stream into a string and moves the pointer + * through the stream by $length. + * + * If less bytes exist than are requested the + * remaining bytes are given instead. If no bytes are remaining at all, boolean + * false is returned. + * + * @param int $length + * + * @return string + */ + public function read($length) + { + if ($this->offset == $this->arraySize) { + return false; + } - // Don't use array slice - $end = $length + $this->offset; - $end = $this->arraySize < $end ? $this->arraySize : $end; - $ret = ''; - for (; $this->offset < $end; ++$this->offset) { - $ret .= $this->array[$this->offset]; - } + // Don't use array slice + $end = $length + $this->offset; + $end = $this->arraySize < $end ? $this->arraySize : $end; + $ret = ''; + for (; $this->offset < $end; ++$this->offset) { + $ret .= $this->array[$this->offset]; + } - return $ret; - } + return $ret; + } - /** - * Writes $bytes to the end of the stream. - * - * @param string $bytes - */ - public function write($bytes) - { - $to_add = str_split($bytes); - foreach ($to_add as $value) { - $this->array[] = $value; - } - $this->arraySize = \count($this->array); + /** + * Writes $bytes to the end of the stream. + * + * @param string $bytes + */ + public function write($bytes) + { + $to_add = str_split($bytes); + foreach ($to_add as $value) { + $this->array[] = $value; + } + $this->arraySize = \count($this->array); - foreach ($this->mirrors as $stream) { - $stream->write($bytes); - } - } + foreach ($this->mirrors as $stream) { + $stream->write($bytes); + } + } - /** - * Not used. - */ - public function commit() - { - } + /** + * Not used. + */ + public function commit() + { + } - /** - * Attach $is to this stream. - * - * The stream acts as an observer, receiving all data that is written. - * All {@link write()} and {@link flushBuffers()} operations will be mirrored. - */ - public function bind(Swift_InputByteStream $is) - { - $this->mirrors[] = $is; - } + /** + * Attach $is to this stream. + * + * The stream acts as an observer, receiving all data that is written. + * All {@link write()} and {@link flushBuffers()} operations will be mirrored. + */ + public function bind(Swift_InputByteStream $is) + { + $this->mirrors[] = $is; + } - /** - * Remove an already bound stream. - * - * If $is is not bound, no errors will be raised. - * If the stream currently has any buffered data it will be written to $is - * before unbinding occurs. - */ - public function unbind(Swift_InputByteStream $is) - { - foreach ($this->mirrors as $k => $stream) { - if ($is === $stream) { - unset($this->mirrors[$k]); - } - } - } + /** + * Remove an already bound stream. + * + * If $is is not bound, no errors will be raised. + * If the stream currently has any buffered data it will be written to $is + * before unbinding occurs. + */ + public function unbind(Swift_InputByteStream $is) + { + foreach ($this->mirrors as $k => $stream) { + if ($is === $stream) { + unset($this->mirrors[$k]); + } + } + } - /** - * Move the internal read pointer to $byteOffset in the stream. - * - * @param int $byteOffset - * - * @return bool - */ - public function setReadPointer($byteOffset) - { - if ($byteOffset > $this->arraySize) { - $byteOffset = $this->arraySize; - } elseif ($byteOffset < 0) { - $byteOffset = 0; - } + /** + * Move the internal read pointer to $byteOffset in the stream. + * + * @param int $byteOffset + * + * @return bool + */ + public function setReadPointer($byteOffset) + { + if ($byteOffset > $this->arraySize) { + $byteOffset = $this->arraySize; + } elseif ($byteOffset < 0) { + $byteOffset = 0; + } - $this->offset = $byteOffset; - } + $this->offset = $byteOffset; + } - /** - * Flush the contents of the stream (empty it) and set the internal pointer - * to the beginning. - */ - public function flushBuffers() - { - $this->offset = 0; - $this->array = []; - $this->arraySize = 0; + /** + * Flush the contents of the stream (empty it) and set the internal pointer + * to the beginning. + */ + public function flushBuffers() + { + $this->offset = 0; + $this->array = []; + $this->arraySize = 0; - foreach ($this->mirrors as $stream) { - $stream->flushBuffers(); - } - } + foreach ($this->mirrors as $stream) { + $stream->flushBuffers(); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/FileByteStream.php b/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/FileByteStream.php index f6391219e71..b27d96a1760 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/FileByteStream.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/FileByteStream.php @@ -15,200 +15,200 @@ */ class Swift_ByteStream_FileByteStream extends Swift_ByteStream_AbstractFilterableInputStream implements Swift_FileStream { - /** The internal pointer offset */ - private $offset = 0; + /** The internal pointer offset */ + private $offset = 0; - /** The path to the file */ - private $path; + /** The path to the file */ + private $path; - /** The mode this file is opened in for writing */ - private $mode; + /** The mode this file is opened in for writing */ + private $mode; - /** A lazy-loaded resource handle for reading the file */ - private $reader; + /** A lazy-loaded resource handle for reading the file */ + private $reader; - /** A lazy-loaded resource handle for writing the file */ - private $writer; + /** A lazy-loaded resource handle for writing the file */ + private $writer; - /** If stream is seekable true/false, or null if not known */ - private $seekable = null; + /** If stream is seekable true/false, or null if not known */ + private $seekable = null; - /** - * Create a new FileByteStream for $path. - * - * @param string $path - * @param bool $writable if true - */ - public function __construct($path, $writable = false) - { - if (empty($path)) { - throw new Swift_IoException('The path cannot be empty'); - } - $this->path = $path; - $this->mode = $writable ? 'w+b' : 'rb'; - } + /** + * Create a new FileByteStream for $path. + * + * @param string $path + * @param bool $writable if true + */ + public function __construct($path, $writable = false) + { + if (empty($path)) { + throw new Swift_IoException('The path cannot be empty'); + } + $this->path = $path; + $this->mode = $writable ? 'w+b' : 'rb'; + } - /** - * Get the complete path to the file. - * - * @return string - */ - public function getPath() - { - return $this->path; - } + /** + * Get the complete path to the file. + * + * @return string + */ + public function getPath() + { + return $this->path; + } - /** - * Reads $length bytes from the stream into a string and moves the pointer - * through the stream by $length. - * - * If less bytes exist than are requested the - * remaining bytes are given instead. If no bytes are remaining at all, boolean - * false is returned. - * - * @param int $length - * - * @return string|bool - * - * @throws Swift_IoException - */ - public function read($length) - { - $fp = $this->getReadHandle(); - if (!feof($fp)) { - $bytes = fread($fp, $length); - $this->offset = ftell($fp); + /** + * Reads $length bytes from the stream into a string and moves the pointer + * through the stream by $length. + * + * If less bytes exist than are requested the + * remaining bytes are given instead. If no bytes are remaining at all, boolean + * false is returned. + * + * @param int $length + * + * @return string|bool + * + * @throws Swift_IoException + */ + public function read($length) + { + $fp = $this->getReadHandle(); + if (!feof($fp)) { + $bytes = fread($fp, $length); + $this->offset = ftell($fp); - // If we read one byte after reaching the end of the file - // feof() will return false and an empty string is returned - if ((false === $bytes || '' === $bytes) && feof($fp)) { - $this->resetReadHandle(); + // If we read one byte after reaching the end of the file + // feof() will return false and an empty string is returned + if ((false === $bytes || '' === $bytes) && feof($fp)) { + $this->resetReadHandle(); - return false; - } + return false; + } - return $bytes; - } + return $bytes; + } - $this->resetReadHandle(); + $this->resetReadHandle(); - return false; - } + return false; + } - /** - * Move the internal read pointer to $byteOffset in the stream. - * - * @param int $byteOffset - * - * @return bool - */ - public function setReadPointer($byteOffset) - { - if (isset($this->reader)) { - $this->seekReadStreamToPosition($byteOffset); - } - $this->offset = $byteOffset; - } + /** + * Move the internal read pointer to $byteOffset in the stream. + * + * @param int $byteOffset + * + * @return bool + */ + public function setReadPointer($byteOffset) + { + if (isset($this->reader)) { + $this->seekReadStreamToPosition($byteOffset); + } + $this->offset = $byteOffset; + } - /** Just write the bytes to the file */ - protected function doCommit($bytes) - { - fwrite($this->getWriteHandle(), $bytes); - $this->resetReadHandle(); - } + /** Just write the bytes to the file */ + protected function doCommit($bytes) + { + fwrite($this->getWriteHandle(), $bytes); + $this->resetReadHandle(); + } - /** Not used */ - protected function flush() - { - } + /** Not used */ + protected function flush() + { + } - /** Get the resource for reading */ - private function getReadHandle() - { - if (!isset($this->reader)) { - $pointer = @fopen($this->path, 'rb'); - if (!$pointer) { - throw new Swift_IoException('Unable to open file for reading ['.$this->path.']'); - } - $this->reader = $pointer; - if (0 != $this->offset) { - $this->getReadStreamSeekableStatus(); - $this->seekReadStreamToPosition($this->offset); - } - } + /** Get the resource for reading */ + private function getReadHandle() + { + if (!isset($this->reader)) { + $pointer = @fopen($this->path, 'rb'); + if (!$pointer) { + throw new Swift_IoException('Unable to open file for reading ['.$this->path.']'); + } + $this->reader = $pointer; + if (0 != $this->offset) { + $this->getReadStreamSeekableStatus(); + $this->seekReadStreamToPosition($this->offset); + } + } - return $this->reader; - } + return $this->reader; + } - /** Get the resource for writing */ - private function getWriteHandle() - { - if (!isset($this->writer)) { - if (!$this->writer = fopen($this->path, $this->mode)) { - throw new Swift_IoException('Unable to open file for writing ['.$this->path.']'); - } - } + /** Get the resource for writing */ + private function getWriteHandle() + { + if (!isset($this->writer)) { + if (!$this->writer = fopen($this->path, $this->mode)) { + throw new Swift_IoException('Unable to open file for writing ['.$this->path.']'); + } + } - return $this->writer; - } + return $this->writer; + } - /** Force a reload of the resource for reading */ - private function resetReadHandle() - { - if (isset($this->reader)) { - fclose($this->reader); - $this->reader = null; - } - } + /** Force a reload of the resource for reading */ + private function resetReadHandle() + { + if (isset($this->reader)) { + fclose($this->reader); + $this->reader = null; + } + } - /** Check if ReadOnly Stream is seekable */ - private function getReadStreamSeekableStatus() - { - $metas = stream_get_meta_data($this->reader); - $this->seekable = $metas['seekable']; - } + /** Check if ReadOnly Stream is seekable */ + private function getReadStreamSeekableStatus() + { + $metas = stream_get_meta_data($this->reader); + $this->seekable = $metas['seekable']; + } - /** Streams in a readOnly stream ensuring copy if needed */ - private function seekReadStreamToPosition($offset) - { - if (null === $this->seekable) { - $this->getReadStreamSeekableStatus(); - } - if (false === $this->seekable) { - $currentPos = ftell($this->reader); - if ($currentPos < $offset) { - $toDiscard = $offset - $currentPos; - fread($this->reader, $toDiscard); + /** Streams in a readOnly stream ensuring copy if needed */ + private function seekReadStreamToPosition($offset) + { + if (null === $this->seekable) { + $this->getReadStreamSeekableStatus(); + } + if (false === $this->seekable) { + $currentPos = ftell($this->reader); + if ($currentPos < $offset) { + $toDiscard = $offset - $currentPos; + fread($this->reader, $toDiscard); - return; - } - $this->copyReadStream(); - } - fseek($this->reader, $offset, SEEK_SET); - } + return; + } + $this->copyReadStream(); + } + fseek($this->reader, $offset, SEEK_SET); + } - /** Copy a readOnly Stream to ensure seekability */ - private function copyReadStream() - { - if ($tmpFile = fopen('php://temp/maxmemory:4096', 'w+b')) { - /* We have opened a php:// Stream Should work without problem */ - } elseif (\function_exists('sys_get_temp_dir') && is_writable(sys_get_temp_dir()) && ($tmpFile = tmpfile())) { - /* We have opened a tmpfile */ - } else { - throw new Swift_IoException('Unable to copy the file to make it seekable, sys_temp_dir is not writable, php://memory not available'); - } - $currentPos = ftell($this->reader); - fclose($this->reader); - $source = fopen($this->path, 'rb'); - if (!$source) { - throw new Swift_IoException('Unable to open file for copying ['.$this->path.']'); - } - fseek($tmpFile, 0, SEEK_SET); - while (!feof($source)) { - fwrite($tmpFile, fread($source, 4096)); - } - fseek($tmpFile, $currentPos, SEEK_SET); - fclose($source); - $this->reader = $tmpFile; - } + /** Copy a readOnly Stream to ensure seekability */ + private function copyReadStream() + { + if ($tmpFile = fopen('php://temp/maxmemory:4096', 'w+b')) { + /* We have opened a php:// Stream Should work without problem */ + } elseif (\function_exists('sys_get_temp_dir') && is_writable(sys_get_temp_dir()) && ($tmpFile = tmpfile())) { + /* We have opened a tmpfile */ + } else { + throw new Swift_IoException('Unable to copy the file to make it seekable, sys_temp_dir is not writable, php://memory not available'); + } + $currentPos = ftell($this->reader); + fclose($this->reader); + $source = fopen($this->path, 'rb'); + if (!$source) { + throw new Swift_IoException('Unable to open file for copying ['.$this->path.']'); + } + fseek($tmpFile, 0, SEEK_SET); + while (!feof($source)) { + fwrite($tmpFile, fread($source, 4096)); + } + fseek($tmpFile, $currentPos, SEEK_SET); + fclose($source); + $this->reader = $tmpFile; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/TemporaryFileByteStream.php b/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/TemporaryFileByteStream.php index 0dc61909d31..5ea62c5a389 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/TemporaryFileByteStream.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/TemporaryFileByteStream.php @@ -13,40 +13,40 @@ */ class Swift_ByteStream_TemporaryFileByteStream extends Swift_ByteStream_FileByteStream { - public function __construct() - { - $filePath = tempnam(sys_get_temp_dir(), 'FileByteStream'); + public function __construct() + { + $filePath = tempnam(sys_get_temp_dir(), 'FileByteStream'); - if (false === $filePath) { - throw new Swift_IoException('Failed to retrieve temporary file name.'); - } + if (false === $filePath) { + throw new Swift_IoException('Failed to retrieve temporary file name.'); + } - parent::__construct($filePath, true); - } + parent::__construct($filePath, true); + } - public function getContent() - { - if (false === ($content = file_get_contents($this->getPath()))) { - throw new Swift_IoException('Failed to get temporary file content.'); - } + public function getContent() + { + if (false === ($content = file_get_contents($this->getPath()))) { + throw new Swift_IoException('Failed to get temporary file content.'); + } - return $content; - } + return $content; + } - public function __destruct() - { - if (file_exists($this->getPath())) { - @unlink($this->getPath()); - } - } + public function __destruct() + { + if (file_exists($this->getPath())) { + @unlink($this->getPath()); + } + } - public function __sleep() - { - throw new \BadMethodCallException('Cannot serialize '.__CLASS__); - } + public function __sleep() + { + throw new \BadMethodCallException('Cannot serialize '.__CLASS__); + } - public function __wakeup() - { - throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); - } + public function __wakeup() + { + throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReader/GenericFixedWidthReader.php b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReader/GenericFixedWidthReader.php index 3e055afd9dc..3e074eaf4e9 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReader/GenericFixedWidthReader.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReader/GenericFixedWidthReader.php @@ -16,82 +16,82 @@ */ class Swift_CharacterReader_GenericFixedWidthReader implements Swift_CharacterReader { - /** - * The number of bytes in a single character. - * - * @var int - */ - private $width; + /** + * The number of bytes in a single character. + * + * @var int + */ + private $width; - /** - * Creates a new GenericFixedWidthReader using $width bytes per character. - * - * @param int $width - */ - public function __construct($width) - { - $this->width = $width; - } + /** + * Creates a new GenericFixedWidthReader using $width bytes per character. + * + * @param int $width + */ + public function __construct($width) + { + $this->width = $width; + } - /** - * Returns the complete character map. - * - * @param string $string - * @param int $startOffset - * @param array $currentMap - * @param mixed $ignoredChars - * - * @return int - */ - public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars) - { - $strlen = \strlen($string); - // % and / are CPU intensive, so, maybe find a better way - $ignored = $strlen % $this->width; - $ignoredChars = $ignored ? substr($string, -$ignored) : ''; - $currentMap = $this->width; + /** + * Returns the complete character map. + * + * @param string $string + * @param int $startOffset + * @param array $currentMap + * @param mixed $ignoredChars + * + * @return int + */ + public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars) + { + $strlen = \strlen($string); + // % and / are CPU intensive, so, maybe find a better way + $ignored = $strlen % $this->width; + $ignoredChars = $ignored ? substr($string, -$ignored) : ''; + $currentMap = $this->width; - return ($strlen - $ignored) / $this->width; - } + return ($strlen - $ignored) / $this->width; + } - /** - * Returns the mapType. - * - * @return int - */ - public function getMapType() - { - return self::MAP_TYPE_FIXED_LEN; - } + /** + * Returns the mapType. + * + * @return int + */ + public function getMapType() + { + return self::MAP_TYPE_FIXED_LEN; + } - /** - * Returns an integer which specifies how many more bytes to read. - * - * A positive integer indicates the number of more bytes to fetch before invoking - * this method again. - * - * A value of zero means this is already a valid character. - * A value of -1 means this cannot possibly be a valid character. - * - * @param string $bytes - * @param int $size - * - * @return int - */ - public function validateByteSequence($bytes, $size) - { - $needed = $this->width - $size; + /** + * Returns an integer which specifies how many more bytes to read. + * + * A positive integer indicates the number of more bytes to fetch before invoking + * this method again. + * + * A value of zero means this is already a valid character. + * A value of -1 means this cannot possibly be a valid character. + * + * @param string $bytes + * @param int $size + * + * @return int + */ + public function validateByteSequence($bytes, $size) + { + $needed = $this->width - $size; - return $needed > -1 ? $needed : -1; - } + return $needed > -1 ? $needed : -1; + } - /** - * Returns the number of bytes which should be read to start each character. - * - * @return int - */ - public function getInitialByteSize() - { - return $this->width; - } + /** + * Returns the number of bytes which should be read to start each character. + * + * @return int + */ + public function getInitialByteSize() + { + return $this->width; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReader/UsAsciiReader.php b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReader/UsAsciiReader.php index ffc05f7166a..7ddc72a6610 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReader/UsAsciiReader.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReader/UsAsciiReader.php @@ -15,70 +15,70 @@ */ class Swift_CharacterReader_UsAsciiReader implements Swift_CharacterReader { - /** - * Returns the complete character map. - * - * @param string $string - * @param int $startOffset - * @param array $currentMap - * @param string $ignoredChars - * - * @return int - */ - public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars) - { - $strlen = \strlen($string); - $ignoredChars = ''; - for ($i = 0; $i < $strlen; ++$i) { - if ($string[$i] > "\x07F") { - // Invalid char - $currentMap[$i + $startOffset] = $string[$i]; - } - } + /** + * Returns the complete character map. + * + * @param string $string + * @param int $startOffset + * @param array $currentMap + * @param string $ignoredChars + * + * @return int + */ + public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars) + { + $strlen = \strlen($string); + $ignoredChars = ''; + for ($i = 0; $i < $strlen; ++$i) { + if ($string[$i] > "\x07F") { + // Invalid char + $currentMap[$i + $startOffset] = $string[$i]; + } + } - return $strlen; - } + return $strlen; + } - /** - * Returns mapType. - * - * @return int mapType - */ - public function getMapType() - { - return self::MAP_TYPE_INVALID; - } + /** + * Returns mapType. + * + * @return int mapType + */ + public function getMapType() + { + return self::MAP_TYPE_INVALID; + } - /** - * Returns an integer which specifies how many more bytes to read. - * - * A positive integer indicates the number of more bytes to fetch before invoking - * this method again. - * A value of zero means this is already a valid character. - * A value of -1 means this cannot possibly be a valid character. - * - * @param string $bytes - * @param int $size - * - * @return int - */ - public function validateByteSequence($bytes, $size) - { - $byte = reset($bytes); - if (1 == \count($bytes) && $byte >= 0x00 && $byte <= 0x7F) { - return 0; - } + /** + * Returns an integer which specifies how many more bytes to read. + * + * A positive integer indicates the number of more bytes to fetch before invoking + * this method again. + * A value of zero means this is already a valid character. + * A value of -1 means this cannot possibly be a valid character. + * + * @param string $bytes + * @param int $size + * + * @return int + */ + public function validateByteSequence($bytes, $size) + { + $byte = reset($bytes); + if (1 == \count($bytes) && $byte >= 0x00 && $byte <= 0x7F) { + return 0; + } - return -1; - } + return -1; + } - /** - * Returns the number of bytes which should be read to start each character. - * - * @return int - */ - public function getInitialByteSize() - { - return 1; - } + /** + * Returns the number of bytes which should be read to start each character. + * + * @return int + */ + public function getInitialByteSize() + { + return 1; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReader/Utf8Reader.php b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReader/Utf8Reader.php index da37e0da9ab..f828f151121 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReader/Utf8Reader.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReader/Utf8Reader.php @@ -16,161 +16,161 @@ */ class Swift_CharacterReader_Utf8Reader implements Swift_CharacterReader { - /** Pre-computed for optimization */ - private static $length_map = [ - // N=0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x0N - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x1N - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x2N - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x3N - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x4N - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x5N - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x6N - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x7N - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x8N - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x9N - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xAN - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xBN - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xCN - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xDN - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xEN - 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0, // 0xFN - ]; + /** Pre-computed for optimization */ + private static $length_map = [ + // N=0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x0N + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x1N + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x2N + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x3N + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x4N + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x5N + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x6N + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x7N + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x8N + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x9N + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xAN + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xBN + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xCN + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xDN + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xEN + 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0, // 0xFN + ]; - private static $s_length_map = [ - "\x00" => 1, "\x01" => 1, "\x02" => 1, "\x03" => 1, "\x04" => 1, "\x05" => 1, "\x06" => 1, "\x07" => 1, - "\x08" => 1, "\x09" => 1, "\x0a" => 1, "\x0b" => 1, "\x0c" => 1, "\x0d" => 1, "\x0e" => 1, "\x0f" => 1, - "\x10" => 1, "\x11" => 1, "\x12" => 1, "\x13" => 1, "\x14" => 1, "\x15" => 1, "\x16" => 1, "\x17" => 1, - "\x18" => 1, "\x19" => 1, "\x1a" => 1, "\x1b" => 1, "\x1c" => 1, "\x1d" => 1, "\x1e" => 1, "\x1f" => 1, - "\x20" => 1, "\x21" => 1, "\x22" => 1, "\x23" => 1, "\x24" => 1, "\x25" => 1, "\x26" => 1, "\x27" => 1, - "\x28" => 1, "\x29" => 1, "\x2a" => 1, "\x2b" => 1, "\x2c" => 1, "\x2d" => 1, "\x2e" => 1, "\x2f" => 1, - "\x30" => 1, "\x31" => 1, "\x32" => 1, "\x33" => 1, "\x34" => 1, "\x35" => 1, "\x36" => 1, "\x37" => 1, - "\x38" => 1, "\x39" => 1, "\x3a" => 1, "\x3b" => 1, "\x3c" => 1, "\x3d" => 1, "\x3e" => 1, "\x3f" => 1, - "\x40" => 1, "\x41" => 1, "\x42" => 1, "\x43" => 1, "\x44" => 1, "\x45" => 1, "\x46" => 1, "\x47" => 1, - "\x48" => 1, "\x49" => 1, "\x4a" => 1, "\x4b" => 1, "\x4c" => 1, "\x4d" => 1, "\x4e" => 1, "\x4f" => 1, - "\x50" => 1, "\x51" => 1, "\x52" => 1, "\x53" => 1, "\x54" => 1, "\x55" => 1, "\x56" => 1, "\x57" => 1, - "\x58" => 1, "\x59" => 1, "\x5a" => 1, "\x5b" => 1, "\x5c" => 1, "\x5d" => 1, "\x5e" => 1, "\x5f" => 1, - "\x60" => 1, "\x61" => 1, "\x62" => 1, "\x63" => 1, "\x64" => 1, "\x65" => 1, "\x66" => 1, "\x67" => 1, - "\x68" => 1, "\x69" => 1, "\x6a" => 1, "\x6b" => 1, "\x6c" => 1, "\x6d" => 1, "\x6e" => 1, "\x6f" => 1, - "\x70" => 1, "\x71" => 1, "\x72" => 1, "\x73" => 1, "\x74" => 1, "\x75" => 1, "\x76" => 1, "\x77" => 1, - "\x78" => 1, "\x79" => 1, "\x7a" => 1, "\x7b" => 1, "\x7c" => 1, "\x7d" => 1, "\x7e" => 1, "\x7f" => 1, - "\x80" => 0, "\x81" => 0, "\x82" => 0, "\x83" => 0, "\x84" => 0, "\x85" => 0, "\x86" => 0, "\x87" => 0, - "\x88" => 0, "\x89" => 0, "\x8a" => 0, "\x8b" => 0, "\x8c" => 0, "\x8d" => 0, "\x8e" => 0, "\x8f" => 0, - "\x90" => 0, "\x91" => 0, "\x92" => 0, "\x93" => 0, "\x94" => 0, "\x95" => 0, "\x96" => 0, "\x97" => 0, - "\x98" => 0, "\x99" => 0, "\x9a" => 0, "\x9b" => 0, "\x9c" => 0, "\x9d" => 0, "\x9e" => 0, "\x9f" => 0, - "\xa0" => 0, "\xa1" => 0, "\xa2" => 0, "\xa3" => 0, "\xa4" => 0, "\xa5" => 0, "\xa6" => 0, "\xa7" => 0, - "\xa8" => 0, "\xa9" => 0, "\xaa" => 0, "\xab" => 0, "\xac" => 0, "\xad" => 0, "\xae" => 0, "\xaf" => 0, - "\xb0" => 0, "\xb1" => 0, "\xb2" => 0, "\xb3" => 0, "\xb4" => 0, "\xb5" => 0, "\xb6" => 0, "\xb7" => 0, - "\xb8" => 0, "\xb9" => 0, "\xba" => 0, "\xbb" => 0, "\xbc" => 0, "\xbd" => 0, "\xbe" => 0, "\xbf" => 0, - "\xc0" => 2, "\xc1" => 2, "\xc2" => 2, "\xc3" => 2, "\xc4" => 2, "\xc5" => 2, "\xc6" => 2, "\xc7" => 2, - "\xc8" => 2, "\xc9" => 2, "\xca" => 2, "\xcb" => 2, "\xcc" => 2, "\xcd" => 2, "\xce" => 2, "\xcf" => 2, - "\xd0" => 2, "\xd1" => 2, "\xd2" => 2, "\xd3" => 2, "\xd4" => 2, "\xd5" => 2, "\xd6" => 2, "\xd7" => 2, - "\xd8" => 2, "\xd9" => 2, "\xda" => 2, "\xdb" => 2, "\xdc" => 2, "\xdd" => 2, "\xde" => 2, "\xdf" => 2, - "\xe0" => 3, "\xe1" => 3, "\xe2" => 3, "\xe3" => 3, "\xe4" => 3, "\xe5" => 3, "\xe6" => 3, "\xe7" => 3, - "\xe8" => 3, "\xe9" => 3, "\xea" => 3, "\xeb" => 3, "\xec" => 3, "\xed" => 3, "\xee" => 3, "\xef" => 3, - "\xf0" => 4, "\xf1" => 4, "\xf2" => 4, "\xf3" => 4, "\xf4" => 4, "\xf5" => 4, "\xf6" => 4, "\xf7" => 4, - "\xf8" => 5, "\xf9" => 5, "\xfa" => 5, "\xfb" => 5, "\xfc" => 6, "\xfd" => 6, "\xfe" => 0, "\xff" => 0, - ]; + private static $s_length_map = [ + "\x00" => 1, "\x01" => 1, "\x02" => 1, "\x03" => 1, "\x04" => 1, "\x05" => 1, "\x06" => 1, "\x07" => 1, + "\x08" => 1, "\x09" => 1, "\x0a" => 1, "\x0b" => 1, "\x0c" => 1, "\x0d" => 1, "\x0e" => 1, "\x0f" => 1, + "\x10" => 1, "\x11" => 1, "\x12" => 1, "\x13" => 1, "\x14" => 1, "\x15" => 1, "\x16" => 1, "\x17" => 1, + "\x18" => 1, "\x19" => 1, "\x1a" => 1, "\x1b" => 1, "\x1c" => 1, "\x1d" => 1, "\x1e" => 1, "\x1f" => 1, + "\x20" => 1, "\x21" => 1, "\x22" => 1, "\x23" => 1, "\x24" => 1, "\x25" => 1, "\x26" => 1, "\x27" => 1, + "\x28" => 1, "\x29" => 1, "\x2a" => 1, "\x2b" => 1, "\x2c" => 1, "\x2d" => 1, "\x2e" => 1, "\x2f" => 1, + "\x30" => 1, "\x31" => 1, "\x32" => 1, "\x33" => 1, "\x34" => 1, "\x35" => 1, "\x36" => 1, "\x37" => 1, + "\x38" => 1, "\x39" => 1, "\x3a" => 1, "\x3b" => 1, "\x3c" => 1, "\x3d" => 1, "\x3e" => 1, "\x3f" => 1, + "\x40" => 1, "\x41" => 1, "\x42" => 1, "\x43" => 1, "\x44" => 1, "\x45" => 1, "\x46" => 1, "\x47" => 1, + "\x48" => 1, "\x49" => 1, "\x4a" => 1, "\x4b" => 1, "\x4c" => 1, "\x4d" => 1, "\x4e" => 1, "\x4f" => 1, + "\x50" => 1, "\x51" => 1, "\x52" => 1, "\x53" => 1, "\x54" => 1, "\x55" => 1, "\x56" => 1, "\x57" => 1, + "\x58" => 1, "\x59" => 1, "\x5a" => 1, "\x5b" => 1, "\x5c" => 1, "\x5d" => 1, "\x5e" => 1, "\x5f" => 1, + "\x60" => 1, "\x61" => 1, "\x62" => 1, "\x63" => 1, "\x64" => 1, "\x65" => 1, "\x66" => 1, "\x67" => 1, + "\x68" => 1, "\x69" => 1, "\x6a" => 1, "\x6b" => 1, "\x6c" => 1, "\x6d" => 1, "\x6e" => 1, "\x6f" => 1, + "\x70" => 1, "\x71" => 1, "\x72" => 1, "\x73" => 1, "\x74" => 1, "\x75" => 1, "\x76" => 1, "\x77" => 1, + "\x78" => 1, "\x79" => 1, "\x7a" => 1, "\x7b" => 1, "\x7c" => 1, "\x7d" => 1, "\x7e" => 1, "\x7f" => 1, + "\x80" => 0, "\x81" => 0, "\x82" => 0, "\x83" => 0, "\x84" => 0, "\x85" => 0, "\x86" => 0, "\x87" => 0, + "\x88" => 0, "\x89" => 0, "\x8a" => 0, "\x8b" => 0, "\x8c" => 0, "\x8d" => 0, "\x8e" => 0, "\x8f" => 0, + "\x90" => 0, "\x91" => 0, "\x92" => 0, "\x93" => 0, "\x94" => 0, "\x95" => 0, "\x96" => 0, "\x97" => 0, + "\x98" => 0, "\x99" => 0, "\x9a" => 0, "\x9b" => 0, "\x9c" => 0, "\x9d" => 0, "\x9e" => 0, "\x9f" => 0, + "\xa0" => 0, "\xa1" => 0, "\xa2" => 0, "\xa3" => 0, "\xa4" => 0, "\xa5" => 0, "\xa6" => 0, "\xa7" => 0, + "\xa8" => 0, "\xa9" => 0, "\xaa" => 0, "\xab" => 0, "\xac" => 0, "\xad" => 0, "\xae" => 0, "\xaf" => 0, + "\xb0" => 0, "\xb1" => 0, "\xb2" => 0, "\xb3" => 0, "\xb4" => 0, "\xb5" => 0, "\xb6" => 0, "\xb7" => 0, + "\xb8" => 0, "\xb9" => 0, "\xba" => 0, "\xbb" => 0, "\xbc" => 0, "\xbd" => 0, "\xbe" => 0, "\xbf" => 0, + "\xc0" => 2, "\xc1" => 2, "\xc2" => 2, "\xc3" => 2, "\xc4" => 2, "\xc5" => 2, "\xc6" => 2, "\xc7" => 2, + "\xc8" => 2, "\xc9" => 2, "\xca" => 2, "\xcb" => 2, "\xcc" => 2, "\xcd" => 2, "\xce" => 2, "\xcf" => 2, + "\xd0" => 2, "\xd1" => 2, "\xd2" => 2, "\xd3" => 2, "\xd4" => 2, "\xd5" => 2, "\xd6" => 2, "\xd7" => 2, + "\xd8" => 2, "\xd9" => 2, "\xda" => 2, "\xdb" => 2, "\xdc" => 2, "\xdd" => 2, "\xde" => 2, "\xdf" => 2, + "\xe0" => 3, "\xe1" => 3, "\xe2" => 3, "\xe3" => 3, "\xe4" => 3, "\xe5" => 3, "\xe6" => 3, "\xe7" => 3, + "\xe8" => 3, "\xe9" => 3, "\xea" => 3, "\xeb" => 3, "\xec" => 3, "\xed" => 3, "\xee" => 3, "\xef" => 3, + "\xf0" => 4, "\xf1" => 4, "\xf2" => 4, "\xf3" => 4, "\xf4" => 4, "\xf5" => 4, "\xf6" => 4, "\xf7" => 4, + "\xf8" => 5, "\xf9" => 5, "\xfa" => 5, "\xfb" => 5, "\xfc" => 6, "\xfd" => 6, "\xfe" => 0, "\xff" => 0, + ]; - /** - * Returns the complete character map. - * - * @param string $string - * @param int $startOffset - * @param array $currentMap - * @param mixed $ignoredChars - * - * @return int - */ - public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars) - { - if (!isset($currentMap['i']) || !isset($currentMap['p'])) { - $currentMap['p'] = $currentMap['i'] = []; - } + /** + * Returns the complete character map. + * + * @param string $string + * @param int $startOffset + * @param array $currentMap + * @param mixed $ignoredChars + * + * @return int + */ + public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars) + { + if (!isset($currentMap['i']) || !isset($currentMap['p'])) { + $currentMap['p'] = $currentMap['i'] = []; + } - $strlen = \strlen($string); - $charPos = \count($currentMap['p']); - $foundChars = 0; - $invalid = false; - for ($i = 0; $i < $strlen; ++$i) { - $char = $string[$i]; - $size = self::$s_length_map[$char]; - if (0 == $size) { - /* char is invalid, we must wait for a resync */ - $invalid = true; - continue; - } else { - if (true === $invalid) { - /* We mark the chars as invalid and start a new char */ - $currentMap['p'][$charPos + $foundChars] = $startOffset + $i; - $currentMap['i'][$charPos + $foundChars] = true; - ++$foundChars; - $invalid = false; - } - if (($i + $size) > $strlen) { - $ignoredChars = substr($string, $i); - break; - } - for ($j = 1; $j < $size; ++$j) { - $char = $string[$i + $j]; - if ($char > "\x7F" && $char < "\xC0") { - // Valid - continue parsing - } else { - /* char is invalid, we must wait for a resync */ - $invalid = true; - continue 2; - } - } - /* Ok we got a complete char here */ - $currentMap['p'][$charPos + $foundChars] = $startOffset + $i + $size; - $i += $j - 1; - ++$foundChars; - } - } + $strlen = \strlen($string); + $charPos = \count($currentMap['p']); + $foundChars = 0; + $invalid = false; + for ($i = 0; $i < $strlen; ++$i) { + $char = $string[$i]; + $size = self::$s_length_map[$char]; + if (0 == $size) { + /* char is invalid, we must wait for a resync */ + $invalid = true; + continue; + } else { + if (true === $invalid) { + /* We mark the chars as invalid and start a new char */ + $currentMap['p'][$charPos + $foundChars] = $startOffset + $i; + $currentMap['i'][$charPos + $foundChars] = true; + ++$foundChars; + $invalid = false; + } + if (($i + $size) > $strlen) { + $ignoredChars = substr($string, $i); + break; + } + for ($j = 1; $j < $size; ++$j) { + $char = $string[$i + $j]; + if ($char > "\x7F" && $char < "\xC0") { + // Valid - continue parsing + } else { + /* char is invalid, we must wait for a resync */ + $invalid = true; + continue 2; + } + } + /* Ok we got a complete char here */ + $currentMap['p'][$charPos + $foundChars] = $startOffset + $i + $size; + $i += $j - 1; + ++$foundChars; + } + } - return $foundChars; - } + return $foundChars; + } - /** - * Returns mapType. - * - * @return int mapType - */ - public function getMapType() - { - return self::MAP_TYPE_POSITIONS; - } + /** + * Returns mapType. + * + * @return int mapType + */ + public function getMapType() + { + return self::MAP_TYPE_POSITIONS; + } - /** - * Returns an integer which specifies how many more bytes to read. - * - * A positive integer indicates the number of more bytes to fetch before invoking - * this method again. - * A value of zero means this is already a valid character. - * A value of -1 means this cannot possibly be a valid character. - * - * @param string $bytes - * @param int $size - * - * @return int - */ - public function validateByteSequence($bytes, $size) - { - if ($size < 1) { - return -1; - } - $needed = self::$length_map[$bytes[0]] - $size; + /** + * Returns an integer which specifies how many more bytes to read. + * + * A positive integer indicates the number of more bytes to fetch before invoking + * this method again. + * A value of zero means this is already a valid character. + * A value of -1 means this cannot possibly be a valid character. + * + * @param string $bytes + * @param int $size + * + * @return int + */ + public function validateByteSequence($bytes, $size) + { + if ($size < 1) { + return -1; + } + $needed = self::$length_map[$bytes[0]] - $size; - return $needed > -1 ? $needed : -1; - } + return $needed > -1 ? $needed : -1; + } - /** - * Returns the number of bytes which should be read to start each character. - * - * @return int - */ - public function getInitialByteSize() - { - return 1; - } + /** + * Returns the number of bytes which should be read to start each character. + * + * @return int + */ + public function getInitialByteSize() + { + return 1; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReaderFactory/SimpleCharacterReaderFactory.php b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReaderFactory/SimpleCharacterReaderFactory.php index 86900894ab1..97b3b097f3d 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReaderFactory/SimpleCharacterReaderFactory.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReaderFactory/SimpleCharacterReaderFactory.php @@ -15,110 +15,110 @@ */ class Swift_CharacterReaderFactory_SimpleCharacterReaderFactory implements Swift_CharacterReaderFactory { - /** - * A map of charset patterns to their implementation classes. - * - * @var array - */ - private static $map = []; + /** + * A map of charset patterns to their implementation classes. + * + * @var array + */ + private static $map = []; - /** - * Factories which have already been loaded. - * - * @var Swift_CharacterReaderFactory[] - */ - private static $loaded = []; + /** + * Factories which have already been loaded. + * + * @var Swift_CharacterReaderFactory[] + */ + private static $loaded = []; - /** - * Creates a new CharacterReaderFactory. - */ - public function __construct() - { - $this->init(); - } + /** + * Creates a new CharacterReaderFactory. + */ + public function __construct() + { + $this->init(); + } - public function __wakeup() - { - $this->init(); - } + public function __wakeup() + { + $this->init(); + } - public function init() - { - if (\count(self::$map) > 0) { - return; - } + public function init() + { + if (\count(self::$map) > 0) { + return; + } - $prefix = 'Swift_CharacterReader_'; + $prefix = 'Swift_CharacterReader_'; - $singleByte = [ - 'class' => $prefix.'GenericFixedWidthReader', - 'constructor' => [1], - ]; + $singleByte = [ + 'class' => $prefix.'GenericFixedWidthReader', + 'constructor' => [1], + ]; - $doubleByte = [ - 'class' => $prefix.'GenericFixedWidthReader', - 'constructor' => [2], - ]; + $doubleByte = [ + 'class' => $prefix.'GenericFixedWidthReader', + 'constructor' => [2], + ]; - $fourBytes = [ - 'class' => $prefix.'GenericFixedWidthReader', - 'constructor' => [4], - ]; + $fourBytes = [ + 'class' => $prefix.'GenericFixedWidthReader', + 'constructor' => [4], + ]; - // Utf-8 - self::$map['utf-?8'] = [ - 'class' => $prefix.'Utf8Reader', - 'constructor' => [], - ]; + // Utf-8 + self::$map['utf-?8'] = [ + 'class' => $prefix.'Utf8Reader', + 'constructor' => [], + ]; - //7-8 bit charsets - self::$map['(us-)?ascii'] = $singleByte; - self::$map['(iso|iec)-?8859-?[0-9]+'] = $singleByte; - self::$map['windows-?125[0-9]'] = $singleByte; - self::$map['cp-?[0-9]+'] = $singleByte; - self::$map['ansi'] = $singleByte; - self::$map['macintosh'] = $singleByte; - self::$map['koi-?7'] = $singleByte; - self::$map['koi-?8-?.+'] = $singleByte; - self::$map['mik'] = $singleByte; - self::$map['(cork|t1)'] = $singleByte; - self::$map['v?iscii'] = $singleByte; + //7-8 bit charsets + self::$map['(us-)?ascii'] = $singleByte; + self::$map['(iso|iec)-?8859-?[0-9]+'] = $singleByte; + self::$map['windows-?125[0-9]'] = $singleByte; + self::$map['cp-?[0-9]+'] = $singleByte; + self::$map['ansi'] = $singleByte; + self::$map['macintosh'] = $singleByte; + self::$map['koi-?7'] = $singleByte; + self::$map['koi-?8-?.+'] = $singleByte; + self::$map['mik'] = $singleByte; + self::$map['(cork|t1)'] = $singleByte; + self::$map['v?iscii'] = $singleByte; - //16 bits - self::$map['(ucs-?2|utf-?16)'] = $doubleByte; + //16 bits + self::$map['(ucs-?2|utf-?16)'] = $doubleByte; - //32 bits - self::$map['(ucs-?4|utf-?32)'] = $fourBytes; + //32 bits + self::$map['(ucs-?4|utf-?32)'] = $fourBytes; - // Fallback - self::$map['.*'] = $singleByte; - } + // Fallback + self::$map['.*'] = $singleByte; + } - /** - * Returns a CharacterReader suitable for the charset applied. - * - * @param string $charset - * - * @return Swift_CharacterReader - */ - public function getReaderFor($charset) - { - $charset = strtolower(trim($charset ?? '')); - foreach (self::$map as $pattern => $spec) { - $re = '/^'.$pattern.'$/D'; - if (preg_match($re, $charset)) { - if (!\array_key_exists($pattern, self::$loaded)) { - $reflector = new ReflectionClass($spec['class']); - if ($reflector->getConstructor()) { - $reader = $reflector->newInstanceArgs($spec['constructor']); - } else { - $reader = $reflector->newInstance(); - } - self::$loaded[$pattern] = $reader; - } + /** + * Returns a CharacterReader suitable for the charset applied. + * + * @param string $charset + * + * @return Swift_CharacterReader + */ + public function getReaderFor($charset) + { + $charset = strtolower(trim($charset ?? '')); + foreach (self::$map as $pattern => $spec) { + $re = '/^'.$pattern.'$/D'; + if (preg_match($re, $charset)) { + if (!\array_key_exists($pattern, self::$loaded)) { + $reflector = new ReflectionClass($spec['class']); + if ($reflector->getConstructor()) { + $reader = $reflector->newInstanceArgs($spec['constructor']); + } else { + $reader = $reflector->newInstance(); + } + self::$loaded[$pattern] = $reader; + } - return self::$loaded[$pattern]; - } - } - } + return self::$loaded[$pattern]; + } + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterStream.php b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterStream.php index c9d8a078ee0..04e2d433934 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterStream.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterStream.php @@ -19,69 +19,69 @@ */ interface Swift_CharacterStream { - /** - * Set the character set used in this CharacterStream. - * - * @param string $charset - */ - public function setCharacterSet($charset); + /** + * Set the character set used in this CharacterStream. + * + * @param string $charset + */ + public function setCharacterSet($charset); - /** - * Set the CharacterReaderFactory for multi charset support. - */ - public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory); + /** + * Set the CharacterReaderFactory for multi charset support. + */ + public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory); - /** - * Overwrite this character stream using the byte sequence in the byte stream. - * - * @param Swift_OutputByteStream $os output stream to read from - */ - public function importByteStream(Swift_OutputByteStream $os); + /** + * Overwrite this character stream using the byte sequence in the byte stream. + * + * @param Swift_OutputByteStream $os output stream to read from + */ + public function importByteStream(Swift_OutputByteStream $os); - /** - * Import a string a bytes into this CharacterStream, overwriting any existing - * data in the stream. - * - * @param string $string - */ - public function importString($string); + /** + * Import a string a bytes into this CharacterStream, overwriting any existing + * data in the stream. + * + * @param string $string + */ + public function importString($string); - /** - * Read $length characters from the stream and move the internal pointer - * $length further into the stream. - * - * @param int $length - * - * @return string - */ - public function read($length); + /** + * Read $length characters from the stream and move the internal pointer + * $length further into the stream. + * + * @param int $length + * + * @return string + */ + public function read($length); - /** - * Read $length characters from the stream and return a 1-dimensional array - * containing there octet values. - * - * @param int $length - * - * @return int[] - */ - public function readBytes($length); + /** + * Read $length characters from the stream and return a 1-dimensional array + * containing there octet values. + * + * @param int $length + * + * @return int[] + */ + public function readBytes($length); - /** - * Write $chars to the end of the stream. - * - * @param string $chars - */ - public function write($chars); + /** + * Write $chars to the end of the stream. + * + * @param string $chars + */ + public function write($chars); - /** - * Move the internal pointer to $charOffset in the stream. - * - * @param int $charOffset - */ - public function setPointer($charOffset); + /** + * Move the internal pointer to $charOffset in the stream. + * + * @param int $charOffset + */ + public function setPointer($charOffset); - /** - * Empty the stream and reset the internal pointer. - */ - public function flushContents(); + /** + * Empty the stream and reset the internal pointer. + */ + public function flushContents(); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterStream/ArrayCharacterStream.php b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterStream/ArrayCharacterStream.php index 5c2869455b8..6f6a22e393e 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterStream/ArrayCharacterStream.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterStream/ArrayCharacterStream.php @@ -15,277 +15,277 @@ */ class Swift_CharacterStream_ArrayCharacterStream implements Swift_CharacterStream { - /** A map of byte values and their respective characters */ - private static $charMap; + /** A map of byte values and their respective characters */ + private static $charMap; - /** A map of characters and their derivative byte values */ - private static $byteMap; + /** A map of characters and their derivative byte values */ + private static $byteMap; - /** The char reader (lazy-loaded) for the current charset */ - private $charReader; + /** The char reader (lazy-loaded) for the current charset */ + private $charReader; - /** A factory for creating CharacterReader instances */ - private $charReaderFactory; + /** A factory for creating CharacterReader instances */ + private $charReaderFactory; - /** The character set this stream is using */ - private $charset; + /** The character set this stream is using */ + private $charset; - /** Array of characters */ - private $array = []; + /** Array of characters */ + private $array = []; - /** Size of the array of character */ - private $array_size = []; + /** Size of the array of character */ + private $array_size = []; - /** The current character offset in the stream */ - private $offset = 0; + /** The current character offset in the stream */ + private $offset = 0; - /** - * Create a new CharacterStream with the given $chars, if set. - * - * @param Swift_CharacterReaderFactory $factory for loading validators - * @param string $charset used in the stream - */ - public function __construct(Swift_CharacterReaderFactory $factory, $charset) - { - self::initializeMaps(); - $this->setCharacterReaderFactory($factory); - $this->setCharacterSet($charset); - } + /** + * Create a new CharacterStream with the given $chars, if set. + * + * @param Swift_CharacterReaderFactory $factory for loading validators + * @param string $charset used in the stream + */ + public function __construct(Swift_CharacterReaderFactory $factory, $charset) + { + self::initializeMaps(); + $this->setCharacterReaderFactory($factory); + $this->setCharacterSet($charset); + } - /** - * Set the character set used in this CharacterStream. - * - * @param string $charset - */ - public function setCharacterSet($charset) - { - $this->charset = $charset; - $this->charReader = null; - } + /** + * Set the character set used in this CharacterStream. + * + * @param string $charset + */ + public function setCharacterSet($charset) + { + $this->charset = $charset; + $this->charReader = null; + } - /** - * Set the CharacterReaderFactory for multi charset support. - */ - public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory) - { - $this->charReaderFactory = $factory; - } + /** + * Set the CharacterReaderFactory for multi charset support. + */ + public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory) + { + $this->charReaderFactory = $factory; + } - /** - * Overwrite this character stream using the byte sequence in the byte stream. - * - * @param Swift_OutputByteStream $os output stream to read from - */ - public function importByteStream(Swift_OutputByteStream $os) - { - if (!isset($this->charReader)) { - $this->charReader = $this->charReaderFactory - ->getReaderFor($this->charset); - } + /** + * Overwrite this character stream using the byte sequence in the byte stream. + * + * @param Swift_OutputByteStream $os output stream to read from + */ + public function importByteStream(Swift_OutputByteStream $os) + { + if (!isset($this->charReader)) { + $this->charReader = $this->charReaderFactory + ->getReaderFor($this->charset); + } - $startLength = $this->charReader->getInitialByteSize(); - while (false !== $bytes = $os->read($startLength)) { - $c = []; - for ($i = 0, $len = \strlen($bytes); $i < $len; ++$i) { - $c[] = self::$byteMap[$bytes[$i]]; - } - $size = \count($c); - $need = $this->charReader - ->validateByteSequence($c, $size); - if ($need > 0 && - false !== $bytes = $os->read($need)) { - for ($i = 0, $len = \strlen($bytes); $i < $len; ++$i) { - $c[] = self::$byteMap[$bytes[$i]]; - } - } - $this->array[] = $c; - ++$this->array_size; - } - } + $startLength = $this->charReader->getInitialByteSize(); + while (false !== $bytes = $os->read($startLength)) { + $c = []; + for ($i = 0, $len = \strlen($bytes); $i < $len; ++$i) { + $c[] = self::$byteMap[$bytes[$i]]; + } + $size = \count($c); + $need = $this->charReader + ->validateByteSequence($c, $size); + if ($need > 0 && + false !== $bytes = $os->read($need)) { + for ($i = 0, $len = \strlen($bytes); $i < $len; ++$i) { + $c[] = self::$byteMap[$bytes[$i]]; + } + } + $this->array[] = $c; + ++$this->array_size; + } + } - /** - * Import a string a bytes into this CharacterStream, overwriting any existing - * data in the stream. - * - * @param string $string - */ - public function importString($string) - { - $this->flushContents(); - $this->write($string); - } + /** + * Import a string a bytes into this CharacterStream, overwriting any existing + * data in the stream. + * + * @param string $string + */ + public function importString($string) + { + $this->flushContents(); + $this->write($string); + } - /** - * Read $length characters from the stream and move the internal pointer - * $length further into the stream. - * - * @param int $length - * - * @return string - */ - public function read($length) - { - if ($this->offset == $this->array_size) { - return false; - } + /** + * Read $length characters from the stream and move the internal pointer + * $length further into the stream. + * + * @param int $length + * + * @return string + */ + public function read($length) + { + if ($this->offset == $this->array_size) { + return false; + } - // Don't use array slice - $arrays = []; - $end = $length + $this->offset; - for ($i = $this->offset; $i < $end; ++$i) { - if (!isset($this->array[$i])) { - break; - } - $arrays[] = $this->array[$i]; - } - $this->offset += $i - $this->offset; // Limit function calls - $chars = false; - foreach ($arrays as $array) { - $chars .= implode('', array_map('chr', $array)); - } + // Don't use array slice + $arrays = []; + $end = $length + $this->offset; + for ($i = $this->offset; $i < $end; ++$i) { + if (!isset($this->array[$i])) { + break; + } + $arrays[] = $this->array[$i]; + } + $this->offset += $i - $this->offset; // Limit function calls + $chars = false; + foreach ($arrays as $array) { + $chars .= implode('', array_map('chr', $array)); + } - return $chars; - } + return $chars; + } - /** - * Read $length characters from the stream and return a 1-dimensional array - * containing there octet values. - * - * @param int $length - * - * @return int[] - */ - public function readBytes($length) - { - if ($this->offset == $this->array_size) { - return false; - } - $arrays = []; - $end = $length + $this->offset; - for ($i = $this->offset; $i < $end; ++$i) { - if (!isset($this->array[$i])) { - break; - } - $arrays[] = $this->array[$i]; - } - $this->offset += ($i - $this->offset); // Limit function calls + /** + * Read $length characters from the stream and return a 1-dimensional array + * containing there octet values. + * + * @param int $length + * + * @return int[] + */ + public function readBytes($length) + { + if ($this->offset == $this->array_size) { + return false; + } + $arrays = []; + $end = $length + $this->offset; + for ($i = $this->offset; $i < $end; ++$i) { + if (!isset($this->array[$i])) { + break; + } + $arrays[] = $this->array[$i]; + } + $this->offset += ($i - $this->offset); // Limit function calls - return array_merge(...$arrays); - } + return array_merge(...$arrays); + } - /** - * Write $chars to the end of the stream. - * - * @param string $chars - */ - public function write($chars) - { - if (!isset($this->charReader)) { - $this->charReader = $this->charReaderFactory->getReaderFor( - $this->charset); - } + /** + * Write $chars to the end of the stream. + * + * @param string $chars + */ + public function write($chars) + { + if (!isset($this->charReader)) { + $this->charReader = $this->charReaderFactory->getReaderFor( + $this->charset); + } - $startLength = $this->charReader->getInitialByteSize(); + $startLength = $this->charReader->getInitialByteSize(); - $fp = fopen('php://memory', 'w+b'); - fwrite($fp, $chars); - unset($chars); - fseek($fp, 0, SEEK_SET); + $fp = fopen('php://memory', 'w+b'); + fwrite($fp, $chars); + unset($chars); + fseek($fp, 0, SEEK_SET); - $buffer = [0]; - $buf_pos = 1; - $buf_len = 1; - $has_datas = true; - do { - $bytes = []; - // Buffer Filing - if ($buf_len - $buf_pos < $startLength) { - $buf = array_splice($buffer, $buf_pos); - $new = $this->reloadBuffer($fp, 100); - if ($new) { - $buffer = array_merge($buf, $new); - $buf_len = \count($buffer); - $buf_pos = 0; - } else { - $has_datas = false; - } - } - if ($buf_len - $buf_pos > 0) { - $size = 0; - for ($i = 0; $i < $startLength && isset($buffer[$buf_pos]); ++$i) { - ++$size; - $bytes[] = $buffer[$buf_pos++]; - } - $need = $this->charReader->validateByteSequence( - $bytes, $size); - if ($need > 0) { - if ($buf_len - $buf_pos < $need) { - $new = $this->reloadBuffer($fp, $need); + $buffer = [0]; + $buf_pos = 1; + $buf_len = 1; + $has_datas = true; + do { + $bytes = []; + // Buffer Filing + if ($buf_len - $buf_pos < $startLength) { + $buf = array_splice($buffer, $buf_pos); + $new = $this->reloadBuffer($fp, 100); + if ($new) { + $buffer = array_merge($buf, $new); + $buf_len = \count($buffer); + $buf_pos = 0; + } else { + $has_datas = false; + } + } + if ($buf_len - $buf_pos > 0) { + $size = 0; + for ($i = 0; $i < $startLength && isset($buffer[$buf_pos]); ++$i) { + ++$size; + $bytes[] = $buffer[$buf_pos++]; + } + $need = $this->charReader->validateByteSequence( + $bytes, $size); + if ($need > 0) { + if ($buf_len - $buf_pos < $need) { + $new = $this->reloadBuffer($fp, $need); - if ($new) { - $buffer = array_merge($buffer, $new); - $buf_len = \count($buffer); - } - } - for ($i = 0; $i < $need && isset($buffer[$buf_pos]); ++$i) { - $bytes[] = $buffer[$buf_pos++]; - } - } - $this->array[] = $bytes; - ++$this->array_size; - } - } while ($has_datas); + if ($new) { + $buffer = array_merge($buffer, $new); + $buf_len = \count($buffer); + } + } + for ($i = 0; $i < $need && isset($buffer[$buf_pos]); ++$i) { + $bytes[] = $buffer[$buf_pos++]; + } + } + $this->array[] = $bytes; + ++$this->array_size; + } + } while ($has_datas); - fclose($fp); - } + fclose($fp); + } - /** - * Move the internal pointer to $charOffset in the stream. - * - * @param int $charOffset - */ - public function setPointer($charOffset) - { - if ($charOffset > $this->array_size) { - $charOffset = $this->array_size; - } elseif ($charOffset < 0) { - $charOffset = 0; - } - $this->offset = $charOffset; - } + /** + * Move the internal pointer to $charOffset in the stream. + * + * @param int $charOffset + */ + public function setPointer($charOffset) + { + if ($charOffset > $this->array_size) { + $charOffset = $this->array_size; + } elseif ($charOffset < 0) { + $charOffset = 0; + } + $this->offset = $charOffset; + } - /** - * Empty the stream and reset the internal pointer. - */ - public function flushContents() - { - $this->offset = 0; - $this->array = []; - $this->array_size = 0; - } + /** + * Empty the stream and reset the internal pointer. + */ + public function flushContents() + { + $this->offset = 0; + $this->array = []; + $this->array_size = 0; + } - private function reloadBuffer($fp, $len) - { - if (!feof($fp) && false !== ($bytes = fread($fp, $len))) { - $buf = []; - for ($i = 0, $len = \strlen($bytes); $i < $len; ++$i) { - $buf[] = self::$byteMap[$bytes[$i]]; - } + private function reloadBuffer($fp, $len) + { + if (!feof($fp) && false !== ($bytes = fread($fp, $len))) { + $buf = []; + for ($i = 0, $len = \strlen($bytes); $i < $len; ++$i) { + $buf[] = self::$byteMap[$bytes[$i]]; + } - return $buf; - } + return $buf; + } - return false; - } + return false; + } - private static function initializeMaps() - { - if (!isset(self::$charMap)) { - self::$charMap = []; - for ($byte = 0; $byte < 256; ++$byte) { - self::$charMap[$byte] = \chr($byte); - } - self::$byteMap = array_flip(self::$charMap); - } - } + private static function initializeMaps() + { + if (!isset(self::$charMap)) { + self::$charMap = []; + for ($byte = 0; $byte < 256; ++$byte) { + self::$charMap[$byte] = \chr($byte); + } + self::$byteMap = array_flip(self::$charMap); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterStream/NgCharacterStream.php b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterStream/NgCharacterStream.php index 7578dda9cac..d7110ff16ef 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterStream/NgCharacterStream.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterStream/NgCharacterStream.php @@ -15,248 +15,248 @@ */ class Swift_CharacterStream_NgCharacterStream implements Swift_CharacterStream { - /** - * The char reader (lazy-loaded) for the current charset. - * - * @var Swift_CharacterReader - */ - private $charReader; + /** + * The char reader (lazy-loaded) for the current charset. + * + * @var Swift_CharacterReader + */ + private $charReader; - /** - * A factory for creating CharacterReader instances. - * - * @var Swift_CharacterReaderFactory - */ - private $charReaderFactory; + /** + * A factory for creating CharacterReader instances. + * + * @var Swift_CharacterReaderFactory + */ + private $charReaderFactory; - /** - * The character set this stream is using. - * - * @var string - */ - private $charset; + /** + * The character set this stream is using. + * + * @var string + */ + private $charset; - /** - * The data's stored as-is. - * - * @var string - */ - private $datas = ''; + /** + * The data's stored as-is. + * + * @var string + */ + private $datas = ''; - /** - * Number of bytes in the stream. - * - * @var int - */ - private $datasSize = 0; + /** + * Number of bytes in the stream. + * + * @var int + */ + private $datasSize = 0; - /** - * Map. - * - * @var mixed - */ - private $map; + /** + * Map. + * + * @var mixed + */ + private $map; - /** - * Map Type. - * - * @var int - */ - private $mapType = 0; + /** + * Map Type. + * + * @var int + */ + private $mapType = 0; - /** - * Number of characters in the stream. - * - * @var int - */ - private $charCount = 0; + /** + * Number of characters in the stream. + * + * @var int + */ + private $charCount = 0; - /** - * Position in the stream. - * - * @var int - */ - private $currentPos = 0; + /** + * Position in the stream. + * + * @var int + */ + private $currentPos = 0; - /** - * Constructor. - * - * @param string $charset - */ - public function __construct(Swift_CharacterReaderFactory $factory, $charset) - { - $this->setCharacterReaderFactory($factory); - $this->setCharacterSet($charset); - } + /** + * Constructor. + * + * @param string $charset + */ + public function __construct(Swift_CharacterReaderFactory $factory, $charset) + { + $this->setCharacterReaderFactory($factory); + $this->setCharacterSet($charset); + } - /* -- Changing parameters of the stream -- */ + /* -- Changing parameters of the stream -- */ - /** - * Set the character set used in this CharacterStream. - * - * @param string $charset - */ - public function setCharacterSet($charset) - { - $this->charset = $charset; - $this->charReader = null; - $this->mapType = 0; - } + /** + * Set the character set used in this CharacterStream. + * + * @param string $charset + */ + public function setCharacterSet($charset) + { + $this->charset = $charset; + $this->charReader = null; + $this->mapType = 0; + } - /** - * Set the CharacterReaderFactory for multi charset support. - */ - public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory) - { - $this->charReaderFactory = $factory; - } + /** + * Set the CharacterReaderFactory for multi charset support. + */ + public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory) + { + $this->charReaderFactory = $factory; + } - /** - * @see Swift_CharacterStream::flushContents() - */ - public function flushContents() - { - $this->datas = null; - $this->map = null; - $this->charCount = 0; - $this->currentPos = 0; - $this->datasSize = 0; - } + /** + * @see Swift_CharacterStream::flushContents() + */ + public function flushContents() + { + $this->datas = null; + $this->map = null; + $this->charCount = 0; + $this->currentPos = 0; + $this->datasSize = 0; + } - /** - * @see Swift_CharacterStream::importByteStream() - */ - public function importByteStream(Swift_OutputByteStream $os) - { - $this->flushContents(); - $blocks = 512; - $os->setReadPointer(0); - while (false !== ($read = $os->read($blocks))) { - $this->write($read); - } - } + /** + * @see Swift_CharacterStream::importByteStream() + */ + public function importByteStream(Swift_OutputByteStream $os) + { + $this->flushContents(); + $blocks = 512; + $os->setReadPointer(0); + while (false !== ($read = $os->read($blocks))) { + $this->write($read); + } + } - /** - * @see Swift_CharacterStream::importString() - * - * @param string $string - */ - public function importString($string) - { - $this->flushContents(); - $this->write($string); - } + /** + * @see Swift_CharacterStream::importString() + * + * @param string $string + */ + public function importString($string) + { + $this->flushContents(); + $this->write($string); + } - /** - * @see Swift_CharacterStream::read() - * - * @param int $length - * - * @return string - */ - public function read($length) - { - if ($this->currentPos >= $this->charCount) { - return false; - } - $ret = false; - $length = ($this->currentPos + $length > $this->charCount) ? $this->charCount - $this->currentPos : $length; - switch ($this->mapType) { - case Swift_CharacterReader::MAP_TYPE_FIXED_LEN: - $len = $length * $this->map; - $ret = substr($this->datas, - $this->currentPos * $this->map, - $len); - $this->currentPos += $length; - break; + /** + * @see Swift_CharacterStream::read() + * + * @param int $length + * + * @return string + */ + public function read($length) + { + if ($this->currentPos >= $this->charCount) { + return false; + } + $ret = false; + $length = ($this->currentPos + $length > $this->charCount) ? $this->charCount - $this->currentPos : $length; + switch ($this->mapType) { + case Swift_CharacterReader::MAP_TYPE_FIXED_LEN: + $len = $length * $this->map; + $ret = substr($this->datas, + $this->currentPos * $this->map, + $len); + $this->currentPos += $length; + break; - case Swift_CharacterReader::MAP_TYPE_INVALID: - $ret = ''; - for (; $this->currentPos < $length; ++$this->currentPos) { - if (isset($this->map[$this->currentPos])) { - $ret .= '?'; - } else { - $ret .= $this->datas[$this->currentPos]; - } - } - break; + case Swift_CharacterReader::MAP_TYPE_INVALID: + $ret = ''; + for (; $this->currentPos < $length; ++$this->currentPos) { + if (isset($this->map[$this->currentPos])) { + $ret .= '?'; + } else { + $ret .= $this->datas[$this->currentPos]; + } + } + break; - case Swift_CharacterReader::MAP_TYPE_POSITIONS: - $end = $this->currentPos + $length; - $end = $end > $this->charCount ? $this->charCount : $end; - $ret = ''; - $start = 0; - if ($this->currentPos > 0) { - $start = $this->map['p'][$this->currentPos - 1]; - } - $to = $start; - for (; $this->currentPos < $end; ++$this->currentPos) { - if (isset($this->map['i'][$this->currentPos])) { - $ret .= substr($this->datas, $start, $to - $start).'?'; - $start = $this->map['p'][$this->currentPos]; - } else { - $to = $this->map['p'][$this->currentPos]; - } - } - $ret .= substr($this->datas, $start, $to - $start); - break; - } + case Swift_CharacterReader::MAP_TYPE_POSITIONS: + $end = $this->currentPos + $length; + $end = $end > $this->charCount ? $this->charCount : $end; + $ret = ''; + $start = 0; + if ($this->currentPos > 0) { + $start = $this->map['p'][$this->currentPos - 1]; + } + $to = $start; + for (; $this->currentPos < $end; ++$this->currentPos) { + if (isset($this->map['i'][$this->currentPos])) { + $ret .= substr($this->datas, $start, $to - $start).'?'; + $start = $this->map['p'][$this->currentPos]; + } else { + $to = $this->map['p'][$this->currentPos]; + } + } + $ret .= substr($this->datas, $start, $to - $start); + break; + } - return $ret; - } + return $ret; + } - /** - * @see Swift_CharacterStream::readBytes() - * - * @param int $length - * - * @return int[] - */ - public function readBytes($length) - { - $read = $this->read($length); - if (false !== $read) { - $ret = array_map('ord', str_split($read, 1)); + /** + * @see Swift_CharacterStream::readBytes() + * + * @param int $length + * + * @return int[] + */ + public function readBytes($length) + { + $read = $this->read($length); + if (false !== $read) { + $ret = array_map('ord', str_split($read, 1)); - return $ret; - } + return $ret; + } - return false; - } + return false; + } - /** - * @see Swift_CharacterStream::setPointer() - * - * @param int $charOffset - */ - public function setPointer($charOffset) - { - if ($this->charCount < $charOffset) { - $charOffset = $this->charCount; - } - $this->currentPos = $charOffset; - } + /** + * @see Swift_CharacterStream::setPointer() + * + * @param int $charOffset + */ + public function setPointer($charOffset) + { + if ($this->charCount < $charOffset) { + $charOffset = $this->charCount; + } + $this->currentPos = $charOffset; + } - /** - * @see Swift_CharacterStream::write() - * - * @param string $chars - */ - public function write($chars) - { - if (!isset($this->charReader)) { - $this->charReader = $this->charReaderFactory->getReaderFor( - $this->charset); - $this->map = []; - $this->mapType = $this->charReader->getMapType(); - } - $ignored = ''; - $this->datas .= $chars; - $this->charCount += $this->charReader->getCharPositions(substr($this->datas, $this->datasSize), $this->datasSize, $this->map, $ignored); - if (false !== $ignored) { - $this->datasSize = \strlen($this->datas) - \strlen($ignored); - } else { - $this->datasSize = \strlen($this->datas); - } - } + /** + * @see Swift_CharacterStream::write() + * + * @param string $chars + */ + public function write($chars) + { + if (!isset($this->charReader)) { + $this->charReader = $this->charReaderFactory->getReaderFor( + $this->charset); + $this->map = []; + $this->mapType = $this->charReader->getMapType(); + } + $ignored = ''; + $this->datas .= $chars; + $this->charCount += $this->charReader->getCharPositions(substr($this->datas, $this->datasSize), $this->datasSize, $this->map, $ignored); + if (false !== $ignored) { + $this->datasSize = \strlen($this->datas) - \strlen($ignored); + } else { + $this->datasSize = \strlen($this->datas); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/DependencyContainer.php b/htdocs/includes/swiftmailer/lib/classes/Swift/DependencyContainer.php index 3cc885ec03b..c617290d311 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/DependencyContainer.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/DependencyContainer.php @@ -15,373 +15,373 @@ */ class Swift_DependencyContainer { - /** Constant for literal value types */ - const TYPE_VALUE = 0x00001; + /** Constant for literal value types */ + const TYPE_VALUE = 0x00001; - /** Constant for new instance types */ - const TYPE_INSTANCE = 0x00010; + /** Constant for new instance types */ + const TYPE_INSTANCE = 0x00010; - /** Constant for shared instance types */ - const TYPE_SHARED = 0x00100; + /** Constant for shared instance types */ + const TYPE_SHARED = 0x00100; - /** Constant for aliases */ - const TYPE_ALIAS = 0x01000; + /** Constant for aliases */ + const TYPE_ALIAS = 0x01000; - /** Constant for arrays */ - const TYPE_ARRAY = 0x10000; + /** Constant for arrays */ + const TYPE_ARRAY = 0x10000; - /** Singleton instance */ - private static $instance = null; + /** Singleton instance */ + private static $instance = null; - /** The data container */ - private $store = []; + /** The data container */ + private $store = []; - /** The current endpoint in the data container */ - private $endPoint; + /** The current endpoint in the data container */ + private $endPoint; - /** - * Constructor should not be used. - * - * Use {@link getInstance()} instead. - */ - public function __construct() - { - } + /** + * Constructor should not be used. + * + * Use {@link getInstance()} instead. + */ + public function __construct() + { + } - /** - * Returns a singleton of the DependencyContainer. - * - * @return self - */ - public static function getInstance() - { - if (!isset(self::$instance)) { - self::$instance = new self(); - } + /** + * Returns a singleton of the DependencyContainer. + * + * @return self + */ + public static function getInstance() + { + if (!isset(self::$instance)) { + self::$instance = new self(); + } - return self::$instance; - } + return self::$instance; + } - /** - * List the names of all items stored in the Container. - * - * @return array - */ - public function listItems() - { - return array_keys($this->store); - } + /** + * List the names of all items stored in the Container. + * + * @return array + */ + public function listItems() + { + return array_keys($this->store); + } - /** - * Test if an item is registered in this container with the given name. - * - * @see register() - * - * @param string $itemName - * - * @return bool - */ - public function has($itemName) - { - return \array_key_exists($itemName, $this->store) - && isset($this->store[$itemName]['lookupType']); - } + /** + * Test if an item is registered in this container with the given name. + * + * @see register() + * + * @param string $itemName + * + * @return bool + */ + public function has($itemName) + { + return \array_key_exists($itemName, $this->store) + && isset($this->store[$itemName]['lookupType']); + } - /** - * Lookup the item with the given $itemName. - * - * @see register() - * - * @param string $itemName - * - * @return mixed - * - * @throws Swift_DependencyException If the dependency is not found - */ - public function lookup($itemName) - { - if (!$this->has($itemName)) { - throw new Swift_DependencyException('Cannot lookup dependency "'.$itemName.'" since it is not registered.'); - } + /** + * Lookup the item with the given $itemName. + * + * @see register() + * + * @param string $itemName + * + * @return mixed + * + * @throws Swift_DependencyException If the dependency is not found + */ + public function lookup($itemName) + { + if (!$this->has($itemName)) { + throw new Swift_DependencyException('Cannot lookup dependency "'.$itemName.'" since it is not registered.'); + } - switch ($this->store[$itemName]['lookupType']) { - case self::TYPE_ALIAS: - return $this->createAlias($itemName); - case self::TYPE_VALUE: - return $this->getValue($itemName); - case self::TYPE_INSTANCE: - return $this->createNewInstance($itemName); - case self::TYPE_SHARED: - return $this->createSharedInstance($itemName); - case self::TYPE_ARRAY: - return $this->createDependenciesFor($itemName); - } - } + switch ($this->store[$itemName]['lookupType']) { + case self::TYPE_ALIAS: + return $this->createAlias($itemName); + case self::TYPE_VALUE: + return $this->getValue($itemName); + case self::TYPE_INSTANCE: + return $this->createNewInstance($itemName); + case self::TYPE_SHARED: + return $this->createSharedInstance($itemName); + case self::TYPE_ARRAY: + return $this->createDependenciesFor($itemName); + } + } - /** - * Create an array of arguments passed to the constructor of $itemName. - * - * @param string $itemName - * - * @return array - */ - public function createDependenciesFor($itemName) - { - $args = []; - if (isset($this->store[$itemName]['args'])) { - $args = $this->resolveArgs($this->store[$itemName]['args']); - } + /** + * Create an array of arguments passed to the constructor of $itemName. + * + * @param string $itemName + * + * @return array + */ + public function createDependenciesFor($itemName) + { + $args = []; + if (isset($this->store[$itemName]['args'])) { + $args = $this->resolveArgs($this->store[$itemName]['args']); + } - return $args; - } + return $args; + } - /** - * Register a new dependency with $itemName. - * - * This method returns the current DependencyContainer instance because it - * requires the use of the fluid interface to set the specific details for the - * dependency. - * - * @see asNewInstanceOf(), asSharedInstanceOf(), asValue() - * - * @param string $itemName - * - * @return $this - */ - public function register($itemName) - { - $this->store[$itemName] = []; - $this->endPoint = &$this->store[$itemName]; + /** + * Register a new dependency with $itemName. + * + * This method returns the current DependencyContainer instance because it + * requires the use of the fluid interface to set the specific details for the + * dependency. + * + * @see asNewInstanceOf(), asSharedInstanceOf(), asValue() + * + * @param string $itemName + * + * @return $this + */ + public function register($itemName) + { + $this->store[$itemName] = []; + $this->endPoint = &$this->store[$itemName]; - return $this; - } + return $this; + } - /** - * Specify the previously registered item as a literal value. - * - * {@link register()} must be called before this will work. - * - * @param mixed $value - * - * @return $this - */ - public function asValue($value) - { - $endPoint = &$this->getEndPoint(); - $endPoint['lookupType'] = self::TYPE_VALUE; - $endPoint['value'] = $value; + /** + * Specify the previously registered item as a literal value. + * + * {@link register()} must be called before this will work. + * + * @param mixed $value + * + * @return $this + */ + public function asValue($value) + { + $endPoint = &$this->getEndPoint(); + $endPoint['lookupType'] = self::TYPE_VALUE; + $endPoint['value'] = $value; - return $this; - } + return $this; + } - /** - * Specify the previously registered item as an alias of another item. - * - * @param string $lookup - * - * @return $this - */ - public function asAliasOf($lookup) - { - $endPoint = &$this->getEndPoint(); - $endPoint['lookupType'] = self::TYPE_ALIAS; - $endPoint['ref'] = $lookup; + /** + * Specify the previously registered item as an alias of another item. + * + * @param string $lookup + * + * @return $this + */ + public function asAliasOf($lookup) + { + $endPoint = &$this->getEndPoint(); + $endPoint['lookupType'] = self::TYPE_ALIAS; + $endPoint['ref'] = $lookup; - return $this; - } + return $this; + } - /** - * Specify the previously registered item as a new instance of $className. - * - * {@link register()} must be called before this will work. - * Any arguments can be set with {@link withDependencies()}, - * {@link addConstructorValue()} or {@link addConstructorLookup()}. - * - * @see withDependencies(), addConstructorValue(), addConstructorLookup() - * - * @param string $className - * - * @return $this - */ - public function asNewInstanceOf($className) - { - $endPoint = &$this->getEndPoint(); - $endPoint['lookupType'] = self::TYPE_INSTANCE; - $endPoint['className'] = $className; + /** + * Specify the previously registered item as a new instance of $className. + * + * {@link register()} must be called before this will work. + * Any arguments can be set with {@link withDependencies()}, + * {@link addConstructorValue()} or {@link addConstructorLookup()}. + * + * @see withDependencies(), addConstructorValue(), addConstructorLookup() + * + * @param string $className + * + * @return $this + */ + public function asNewInstanceOf($className) + { + $endPoint = &$this->getEndPoint(); + $endPoint['lookupType'] = self::TYPE_INSTANCE; + $endPoint['className'] = $className; - return $this; - } + return $this; + } - /** - * Specify the previously registered item as a shared instance of $className. - * - * {@link register()} must be called before this will work. - * - * @param string $className - * - * @return $this - */ - public function asSharedInstanceOf($className) - { - $endPoint = &$this->getEndPoint(); - $endPoint['lookupType'] = self::TYPE_SHARED; - $endPoint['className'] = $className; + /** + * Specify the previously registered item as a shared instance of $className. + * + * {@link register()} must be called before this will work. + * + * @param string $className + * + * @return $this + */ + public function asSharedInstanceOf($className) + { + $endPoint = &$this->getEndPoint(); + $endPoint['lookupType'] = self::TYPE_SHARED; + $endPoint['className'] = $className; - return $this; - } + return $this; + } - /** - * Specify the previously registered item as array of dependencies. - * - * {@link register()} must be called before this will work. - * - * @return $this - */ - public function asArray() - { - $endPoint = &$this->getEndPoint(); - $endPoint['lookupType'] = self::TYPE_ARRAY; + /** + * Specify the previously registered item as array of dependencies. + * + * {@link register()} must be called before this will work. + * + * @return $this + */ + public function asArray() + { + $endPoint = &$this->getEndPoint(); + $endPoint['lookupType'] = self::TYPE_ARRAY; - return $this; - } + return $this; + } - /** - * Specify a list of injected dependencies for the previously registered item. - * - * This method takes an array of lookup names. - * - * @see addConstructorValue(), addConstructorLookup() - * - * @return $this - */ - public function withDependencies(array $lookups) - { - $endPoint = &$this->getEndPoint(); - $endPoint['args'] = []; - foreach ($lookups as $lookup) { - $this->addConstructorLookup($lookup); - } + /** + * Specify a list of injected dependencies for the previously registered item. + * + * This method takes an array of lookup names. + * + * @see addConstructorValue(), addConstructorLookup() + * + * @return $this + */ + public function withDependencies(array $lookups) + { + $endPoint = &$this->getEndPoint(); + $endPoint['args'] = []; + foreach ($lookups as $lookup) { + $this->addConstructorLookup($lookup); + } - return $this; - } + return $this; + } - /** - * Specify a literal (non looked up) value for the constructor of the - * previously registered item. - * - * @see withDependencies(), addConstructorLookup() - * - * @param mixed $value - * - * @return $this - */ - public function addConstructorValue($value) - { - $endPoint = &$this->getEndPoint(); - if (!isset($endPoint['args'])) { - $endPoint['args'] = []; - } - $endPoint['args'][] = ['type' => 'value', 'item' => $value]; + /** + * Specify a literal (non looked up) value for the constructor of the + * previously registered item. + * + * @see withDependencies(), addConstructorLookup() + * + * @param mixed $value + * + * @return $this + */ + public function addConstructorValue($value) + { + $endPoint = &$this->getEndPoint(); + if (!isset($endPoint['args'])) { + $endPoint['args'] = []; + } + $endPoint['args'][] = ['type' => 'value', 'item' => $value]; - return $this; - } + return $this; + } - /** - * Specify a dependency lookup for the constructor of the previously - * registered item. - * - * @see withDependencies(), addConstructorValue() - * - * @param string $lookup - * - * @return $this - */ - public function addConstructorLookup($lookup) - { - $endPoint = &$this->getEndPoint(); - if (!isset($this->endPoint['args'])) { - $endPoint['args'] = []; - } - $endPoint['args'][] = ['type' => 'lookup', 'item' => $lookup]; + /** + * Specify a dependency lookup for the constructor of the previously + * registered item. + * + * @see withDependencies(), addConstructorValue() + * + * @param string $lookup + * + * @return $this + */ + public function addConstructorLookup($lookup) + { + $endPoint = &$this->getEndPoint(); + if (!isset($this->endPoint['args'])) { + $endPoint['args'] = []; + } + $endPoint['args'][] = ['type' => 'lookup', 'item' => $lookup]; - return $this; - } + return $this; + } - /** Get the literal value with $itemName */ - private function getValue($itemName) - { - return $this->store[$itemName]['value']; - } + /** Get the literal value with $itemName */ + private function getValue($itemName) + { + return $this->store[$itemName]['value']; + } - /** Resolve an alias to another item */ - private function createAlias($itemName) - { - return $this->lookup($this->store[$itemName]['ref']); - } + /** Resolve an alias to another item */ + private function createAlias($itemName) + { + return $this->lookup($this->store[$itemName]['ref']); + } - /** Create a fresh instance of $itemName */ - private function createNewInstance($itemName) - { - $reflector = new ReflectionClass($this->store[$itemName]['className']); - if ($reflector->getConstructor()) { - return $reflector->newInstanceArgs( - $this->createDependenciesFor($itemName) - ); - } + /** Create a fresh instance of $itemName */ + private function createNewInstance($itemName) + { + $reflector = new ReflectionClass($this->store[$itemName]['className']); + if ($reflector->getConstructor()) { + return $reflector->newInstanceArgs( + $this->createDependenciesFor($itemName) + ); + } - return $reflector->newInstance(); - } + return $reflector->newInstance(); + } - /** Create and register a shared instance of $itemName */ - private function createSharedInstance($itemName) - { - if (!isset($this->store[$itemName]['instance'])) { - $this->store[$itemName]['instance'] = $this->createNewInstance($itemName); - } + /** Create and register a shared instance of $itemName */ + private function createSharedInstance($itemName) + { + if (!isset($this->store[$itemName]['instance'])) { + $this->store[$itemName]['instance'] = $this->createNewInstance($itemName); + } - return $this->store[$itemName]['instance']; - } + return $this->store[$itemName]['instance']; + } - /** Get the current endpoint in the store */ - private function &getEndPoint() - { - if (!isset($this->endPoint)) { - throw new BadMethodCallException('Component must first be registered by calling register()'); - } + /** Get the current endpoint in the store */ + private function &getEndPoint() + { + if (!isset($this->endPoint)) { + throw new BadMethodCallException('Component must first be registered by calling register()'); + } - return $this->endPoint; - } + return $this->endPoint; + } - /** Get an argument list with dependencies resolved */ - private function resolveArgs(array $args) - { - $resolved = []; - foreach ($args as $argDefinition) { - switch ($argDefinition['type']) { - case 'lookup': - $resolved[] = $this->lookupRecursive($argDefinition['item']); - break; - case 'value': - $resolved[] = $argDefinition['item']; - break; - } - } + /** Get an argument list with dependencies resolved */ + private function resolveArgs(array $args) + { + $resolved = []; + foreach ($args as $argDefinition) { + switch ($argDefinition['type']) { + case 'lookup': + $resolved[] = $this->lookupRecursive($argDefinition['item']); + break; + case 'value': + $resolved[] = $argDefinition['item']; + break; + } + } - return $resolved; - } + return $resolved; + } - /** Resolve a single dependency with an collections */ - private function lookupRecursive($item) - { - if (\is_array($item)) { - $collection = []; - foreach ($item as $k => $v) { - $collection[$k] = $this->lookupRecursive($v); - } + /** Resolve a single dependency with an collections */ + private function lookupRecursive($item) + { + if (\is_array($item)) { + $collection = []; + foreach ($item as $k => $v) { + $collection[$k] = $this->lookupRecursive($v); + } - return $collection; - } + return $collection; + } - return $this->lookup($item); - } + return $this->lookup($item); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/EmbeddedFile.php b/htdocs/includes/swiftmailer/lib/classes/Swift/EmbeddedFile.php index 30fc68ab03e..0ed8a23d566 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/EmbeddedFile.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/EmbeddedFile.php @@ -15,39 +15,39 @@ */ class Swift_EmbeddedFile extends Swift_Mime_EmbeddedFile { - /** - * Create a new EmbeddedFile. - * - * Details may be optionally provided to the constructor. - * - * @param string|Swift_OutputByteStream $data - * @param string $filename - * @param string $contentType - */ - public function __construct($data = null, $filename = null, $contentType = null) - { - \call_user_func_array( - [$this, 'Swift_Mime_EmbeddedFile::__construct'], - Swift_DependencyContainer::getInstance() - ->createDependenciesFor('mime.embeddedfile') - ); + /** + * Create a new EmbeddedFile. + * + * Details may be optionally provided to the constructor. + * + * @param string|Swift_OutputByteStream $data + * @param string $filename + * @param string $contentType + */ + public function __construct($data = null, $filename = null, $contentType = null) + { + \call_user_func_array( + [$this, 'Swift_Mime_EmbeddedFile::__construct'], + Swift_DependencyContainer::getInstance() + ->createDependenciesFor('mime.embeddedfile') + ); - $this->setBody($data); - $this->setFilename($filename); - if ($contentType) { - $this->setContentType($contentType); - } - } + $this->setBody($data); + $this->setFilename($filename); + if ($contentType) { + $this->setContentType($contentType); + } + } - /** - * Create a new EmbeddedFile from a filesystem path. - * - * @param string $path - * - * @return Swift_Mime_EmbeddedFile - */ - public static function fromPath($path) - { - return (new self())->setFile(new Swift_ByteStream_FileByteStream($path)); - } + /** + * Create a new EmbeddedFile from a filesystem path. + * + * @param string $path + * + * @return Swift_Mime_EmbeddedFile + */ + public static function fromPath($path) + { + return (new self())->setFile(new Swift_ByteStream_FileByteStream($path)); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Encoder/Base64Encoder.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Encoder/Base64Encoder.php index b1eedaa051b..f89e74dc222 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Encoder/Base64Encoder.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Encoder/Base64Encoder.php @@ -15,44 +15,44 @@ */ class Swift_Encoder_Base64Encoder implements Swift_Encoder { - /** - * Takes an unencoded string and produces a Base64 encoded string from it. - * - * Base64 encoded strings have a maximum line length of 76 characters. - * If the first line needs to be shorter, indicate the difference with - * $firstLineOffset. - * - * @param string $string to encode - * @param int $firstLineOffset - * @param int $maxLineLength optional, 0 indicates the default of 76 bytes - * - * @return string - */ - public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) - { - if (0 >= $maxLineLength || 76 < $maxLineLength) { - $maxLineLength = 76; - } + /** + * Takes an unencoded string and produces a Base64 encoded string from it. + * + * Base64 encoded strings have a maximum line length of 76 characters. + * If the first line needs to be shorter, indicate the difference with + * $firstLineOffset. + * + * @param string $string to encode + * @param int $firstLineOffset + * @param int $maxLineLength optional, 0 indicates the default of 76 bytes + * + * @return string + */ + public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) + { + if (0 >= $maxLineLength || 76 < $maxLineLength) { + $maxLineLength = 76; + } - $encodedString = base64_encode($string ?? ''); - $firstLine = ''; + $encodedString = base64_encode($string ?? ''); + $firstLine = ''; - if (0 != $firstLineOffset) { - $firstLine = substr( - $encodedString, 0, $maxLineLength - $firstLineOffset - )."\r\n"; - $encodedString = substr( - $encodedString, $maxLineLength - $firstLineOffset - ); - } + if (0 != $firstLineOffset) { + $firstLine = substr( + $encodedString, 0, $maxLineLength - $firstLineOffset + )."\r\n"; + $encodedString = substr( + $encodedString, $maxLineLength - $firstLineOffset + ); + } - return $firstLine.trim(chunk_split($encodedString, $maxLineLength, "\r\n")); - } + return $firstLine.trim(chunk_split($encodedString, $maxLineLength, "\r\n")); + } - /** - * Does nothing. - */ - public function charsetChanged($charset) - { - } + /** + * Does nothing. + */ + public function charsetChanged($charset) + { + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Encoder/QpEncoder.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Encoder/QpEncoder.php index f078d6d7c38..24ad727f95b 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Encoder/QpEncoder.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Encoder/QpEncoder.php @@ -17,284 +17,284 @@ */ class Swift_Encoder_QpEncoder implements Swift_Encoder { - /** - * The CharacterStream used for reading characters (as opposed to bytes). - * - * @var Swift_CharacterStream - */ - protected $charStream; + /** + * The CharacterStream used for reading characters (as opposed to bytes). + * + * @var Swift_CharacterStream + */ + protected $charStream; - /** - * A filter used if input should be canonicalized. - * - * @var Swift_StreamFilter - */ - protected $filter; + /** + * A filter used if input should be canonicalized. + * + * @var Swift_StreamFilter + */ + protected $filter; - /** - * Pre-computed QP for HUGE optimization. - * - * @var string[] - */ - protected static $qpMap = [ - 0 => '=00', 1 => '=01', 2 => '=02', 3 => '=03', 4 => '=04', - 5 => '=05', 6 => '=06', 7 => '=07', 8 => '=08', 9 => '=09', - 10 => '=0A', 11 => '=0B', 12 => '=0C', 13 => '=0D', 14 => '=0E', - 15 => '=0F', 16 => '=10', 17 => '=11', 18 => '=12', 19 => '=13', - 20 => '=14', 21 => '=15', 22 => '=16', 23 => '=17', 24 => '=18', - 25 => '=19', 26 => '=1A', 27 => '=1B', 28 => '=1C', 29 => '=1D', - 30 => '=1E', 31 => '=1F', 32 => '=20', 33 => '=21', 34 => '=22', - 35 => '=23', 36 => '=24', 37 => '=25', 38 => '=26', 39 => '=27', - 40 => '=28', 41 => '=29', 42 => '=2A', 43 => '=2B', 44 => '=2C', - 45 => '=2D', 46 => '=2E', 47 => '=2F', 48 => '=30', 49 => '=31', - 50 => '=32', 51 => '=33', 52 => '=34', 53 => '=35', 54 => '=36', - 55 => '=37', 56 => '=38', 57 => '=39', 58 => '=3A', 59 => '=3B', - 60 => '=3C', 61 => '=3D', 62 => '=3E', 63 => '=3F', 64 => '=40', - 65 => '=41', 66 => '=42', 67 => '=43', 68 => '=44', 69 => '=45', - 70 => '=46', 71 => '=47', 72 => '=48', 73 => '=49', 74 => '=4A', - 75 => '=4B', 76 => '=4C', 77 => '=4D', 78 => '=4E', 79 => '=4F', - 80 => '=50', 81 => '=51', 82 => '=52', 83 => '=53', 84 => '=54', - 85 => '=55', 86 => '=56', 87 => '=57', 88 => '=58', 89 => '=59', - 90 => '=5A', 91 => '=5B', 92 => '=5C', 93 => '=5D', 94 => '=5E', - 95 => '=5F', 96 => '=60', 97 => '=61', 98 => '=62', 99 => '=63', - 100 => '=64', 101 => '=65', 102 => '=66', 103 => '=67', 104 => '=68', - 105 => '=69', 106 => '=6A', 107 => '=6B', 108 => '=6C', 109 => '=6D', - 110 => '=6E', 111 => '=6F', 112 => '=70', 113 => '=71', 114 => '=72', - 115 => '=73', 116 => '=74', 117 => '=75', 118 => '=76', 119 => '=77', - 120 => '=78', 121 => '=79', 122 => '=7A', 123 => '=7B', 124 => '=7C', - 125 => '=7D', 126 => '=7E', 127 => '=7F', 128 => '=80', 129 => '=81', - 130 => '=82', 131 => '=83', 132 => '=84', 133 => '=85', 134 => '=86', - 135 => '=87', 136 => '=88', 137 => '=89', 138 => '=8A', 139 => '=8B', - 140 => '=8C', 141 => '=8D', 142 => '=8E', 143 => '=8F', 144 => '=90', - 145 => '=91', 146 => '=92', 147 => '=93', 148 => '=94', 149 => '=95', - 150 => '=96', 151 => '=97', 152 => '=98', 153 => '=99', 154 => '=9A', - 155 => '=9B', 156 => '=9C', 157 => '=9D', 158 => '=9E', 159 => '=9F', - 160 => '=A0', 161 => '=A1', 162 => '=A2', 163 => '=A3', 164 => '=A4', - 165 => '=A5', 166 => '=A6', 167 => '=A7', 168 => '=A8', 169 => '=A9', - 170 => '=AA', 171 => '=AB', 172 => '=AC', 173 => '=AD', 174 => '=AE', - 175 => '=AF', 176 => '=B0', 177 => '=B1', 178 => '=B2', 179 => '=B3', - 180 => '=B4', 181 => '=B5', 182 => '=B6', 183 => '=B7', 184 => '=B8', - 185 => '=B9', 186 => '=BA', 187 => '=BB', 188 => '=BC', 189 => '=BD', - 190 => '=BE', 191 => '=BF', 192 => '=C0', 193 => '=C1', 194 => '=C2', - 195 => '=C3', 196 => '=C4', 197 => '=C5', 198 => '=C6', 199 => '=C7', - 200 => '=C8', 201 => '=C9', 202 => '=CA', 203 => '=CB', 204 => '=CC', - 205 => '=CD', 206 => '=CE', 207 => '=CF', 208 => '=D0', 209 => '=D1', - 210 => '=D2', 211 => '=D3', 212 => '=D4', 213 => '=D5', 214 => '=D6', - 215 => '=D7', 216 => '=D8', 217 => '=D9', 218 => '=DA', 219 => '=DB', - 220 => '=DC', 221 => '=DD', 222 => '=DE', 223 => '=DF', 224 => '=E0', - 225 => '=E1', 226 => '=E2', 227 => '=E3', 228 => '=E4', 229 => '=E5', - 230 => '=E6', 231 => '=E7', 232 => '=E8', 233 => '=E9', 234 => '=EA', - 235 => '=EB', 236 => '=EC', 237 => '=ED', 238 => '=EE', 239 => '=EF', - 240 => '=F0', 241 => '=F1', 242 => '=F2', 243 => '=F3', 244 => '=F4', - 245 => '=F5', 246 => '=F6', 247 => '=F7', 248 => '=F8', 249 => '=F9', - 250 => '=FA', 251 => '=FB', 252 => '=FC', 253 => '=FD', 254 => '=FE', - 255 => '=FF', - ]; + /** + * Pre-computed QP for HUGE optimization. + * + * @var string[] + */ + protected static $qpMap = [ + 0 => '=00', 1 => '=01', 2 => '=02', 3 => '=03', 4 => '=04', + 5 => '=05', 6 => '=06', 7 => '=07', 8 => '=08', 9 => '=09', + 10 => '=0A', 11 => '=0B', 12 => '=0C', 13 => '=0D', 14 => '=0E', + 15 => '=0F', 16 => '=10', 17 => '=11', 18 => '=12', 19 => '=13', + 20 => '=14', 21 => '=15', 22 => '=16', 23 => '=17', 24 => '=18', + 25 => '=19', 26 => '=1A', 27 => '=1B', 28 => '=1C', 29 => '=1D', + 30 => '=1E', 31 => '=1F', 32 => '=20', 33 => '=21', 34 => '=22', + 35 => '=23', 36 => '=24', 37 => '=25', 38 => '=26', 39 => '=27', + 40 => '=28', 41 => '=29', 42 => '=2A', 43 => '=2B', 44 => '=2C', + 45 => '=2D', 46 => '=2E', 47 => '=2F', 48 => '=30', 49 => '=31', + 50 => '=32', 51 => '=33', 52 => '=34', 53 => '=35', 54 => '=36', + 55 => '=37', 56 => '=38', 57 => '=39', 58 => '=3A', 59 => '=3B', + 60 => '=3C', 61 => '=3D', 62 => '=3E', 63 => '=3F', 64 => '=40', + 65 => '=41', 66 => '=42', 67 => '=43', 68 => '=44', 69 => '=45', + 70 => '=46', 71 => '=47', 72 => '=48', 73 => '=49', 74 => '=4A', + 75 => '=4B', 76 => '=4C', 77 => '=4D', 78 => '=4E', 79 => '=4F', + 80 => '=50', 81 => '=51', 82 => '=52', 83 => '=53', 84 => '=54', + 85 => '=55', 86 => '=56', 87 => '=57', 88 => '=58', 89 => '=59', + 90 => '=5A', 91 => '=5B', 92 => '=5C', 93 => '=5D', 94 => '=5E', + 95 => '=5F', 96 => '=60', 97 => '=61', 98 => '=62', 99 => '=63', + 100 => '=64', 101 => '=65', 102 => '=66', 103 => '=67', 104 => '=68', + 105 => '=69', 106 => '=6A', 107 => '=6B', 108 => '=6C', 109 => '=6D', + 110 => '=6E', 111 => '=6F', 112 => '=70', 113 => '=71', 114 => '=72', + 115 => '=73', 116 => '=74', 117 => '=75', 118 => '=76', 119 => '=77', + 120 => '=78', 121 => '=79', 122 => '=7A', 123 => '=7B', 124 => '=7C', + 125 => '=7D', 126 => '=7E', 127 => '=7F', 128 => '=80', 129 => '=81', + 130 => '=82', 131 => '=83', 132 => '=84', 133 => '=85', 134 => '=86', + 135 => '=87', 136 => '=88', 137 => '=89', 138 => '=8A', 139 => '=8B', + 140 => '=8C', 141 => '=8D', 142 => '=8E', 143 => '=8F', 144 => '=90', + 145 => '=91', 146 => '=92', 147 => '=93', 148 => '=94', 149 => '=95', + 150 => '=96', 151 => '=97', 152 => '=98', 153 => '=99', 154 => '=9A', + 155 => '=9B', 156 => '=9C', 157 => '=9D', 158 => '=9E', 159 => '=9F', + 160 => '=A0', 161 => '=A1', 162 => '=A2', 163 => '=A3', 164 => '=A4', + 165 => '=A5', 166 => '=A6', 167 => '=A7', 168 => '=A8', 169 => '=A9', + 170 => '=AA', 171 => '=AB', 172 => '=AC', 173 => '=AD', 174 => '=AE', + 175 => '=AF', 176 => '=B0', 177 => '=B1', 178 => '=B2', 179 => '=B3', + 180 => '=B4', 181 => '=B5', 182 => '=B6', 183 => '=B7', 184 => '=B8', + 185 => '=B9', 186 => '=BA', 187 => '=BB', 188 => '=BC', 189 => '=BD', + 190 => '=BE', 191 => '=BF', 192 => '=C0', 193 => '=C1', 194 => '=C2', + 195 => '=C3', 196 => '=C4', 197 => '=C5', 198 => '=C6', 199 => '=C7', + 200 => '=C8', 201 => '=C9', 202 => '=CA', 203 => '=CB', 204 => '=CC', + 205 => '=CD', 206 => '=CE', 207 => '=CF', 208 => '=D0', 209 => '=D1', + 210 => '=D2', 211 => '=D3', 212 => '=D4', 213 => '=D5', 214 => '=D6', + 215 => '=D7', 216 => '=D8', 217 => '=D9', 218 => '=DA', 219 => '=DB', + 220 => '=DC', 221 => '=DD', 222 => '=DE', 223 => '=DF', 224 => '=E0', + 225 => '=E1', 226 => '=E2', 227 => '=E3', 228 => '=E4', 229 => '=E5', + 230 => '=E6', 231 => '=E7', 232 => '=E8', 233 => '=E9', 234 => '=EA', + 235 => '=EB', 236 => '=EC', 237 => '=ED', 238 => '=EE', 239 => '=EF', + 240 => '=F0', 241 => '=F1', 242 => '=F2', 243 => '=F3', 244 => '=F4', + 245 => '=F5', 246 => '=F6', 247 => '=F7', 248 => '=F8', 249 => '=F9', + 250 => '=FA', 251 => '=FB', 252 => '=FC', 253 => '=FD', 254 => '=FE', + 255 => '=FF', + ]; - protected static $safeMapShare = []; + protected static $safeMapShare = []; - /** - * A map of non-encoded ascii characters. - * - * @var string[] - */ - protected $safeMap = []; + /** + * A map of non-encoded ascii characters. + * + * @var string[] + */ + protected $safeMap = []; - /** - * Creates a new QpEncoder for the given CharacterStream. - * - * @param Swift_CharacterStream $charStream to use for reading characters - * @param Swift_StreamFilter $filter if input should be canonicalized - */ - public function __construct(Swift_CharacterStream $charStream, Swift_StreamFilter $filter = null) - { - $this->charStream = $charStream; - if (!isset(self::$safeMapShare[$this->getSafeMapShareId()])) { - $this->initSafeMap(); - self::$safeMapShare[$this->getSafeMapShareId()] = $this->safeMap; - } else { - $this->safeMap = self::$safeMapShare[$this->getSafeMapShareId()]; - } - $this->filter = $filter; - } + /** + * Creates a new QpEncoder for the given CharacterStream. + * + * @param Swift_CharacterStream $charStream to use for reading characters + * @param Swift_StreamFilter $filter if input should be canonicalized + */ + public function __construct(Swift_CharacterStream $charStream, Swift_StreamFilter $filter = null) + { + $this->charStream = $charStream; + if (!isset(self::$safeMapShare[$this->getSafeMapShareId()])) { + $this->initSafeMap(); + self::$safeMapShare[$this->getSafeMapShareId()] = $this->safeMap; + } else { + $this->safeMap = self::$safeMapShare[$this->getSafeMapShareId()]; + } + $this->filter = $filter; + } - public function __sleep() - { - return ['charStream', 'filter']; - } + public function __sleep() + { + return ['charStream', 'filter']; + } - public function __wakeup() - { - if (!isset(self::$safeMapShare[$this->getSafeMapShareId()])) { - $this->initSafeMap(); - self::$safeMapShare[$this->getSafeMapShareId()] = $this->safeMap; - } else { - $this->safeMap = self::$safeMapShare[$this->getSafeMapShareId()]; - } - } + public function __wakeup() + { + if (!isset(self::$safeMapShare[$this->getSafeMapShareId()])) { + $this->initSafeMap(); + self::$safeMapShare[$this->getSafeMapShareId()] = $this->safeMap; + } else { + $this->safeMap = self::$safeMapShare[$this->getSafeMapShareId()]; + } + } - protected function getSafeMapShareId() - { - return static::class; - } + protected function getSafeMapShareId() + { + return static::class; + } - protected function initSafeMap() - { - foreach (array_merge( - [0x09, 0x20], range(0x21, 0x3C), range(0x3E, 0x7E)) as $byte) { - $this->safeMap[$byte] = \chr($byte); - } - } + protected function initSafeMap() + { + foreach (array_merge( + [0x09, 0x20], range(0x21, 0x3C), range(0x3E, 0x7E)) as $byte) { + $this->safeMap[$byte] = \chr($byte); + } + } - /** - * Takes an unencoded string and produces a QP encoded string from it. - * - * QP encoded strings have a maximum line length of 76 characters. - * If the first line needs to be shorter, indicate the difference with - * $firstLineOffset. - * - * @param string $string to encode - * @param int $firstLineOffset optional - * @param int $maxLineLength optional 0 indicates the default of 76 chars - * - * @return string - */ - public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) - { - if ($maxLineLength > 76 || $maxLineLength <= 0) { - $maxLineLength = 76; - } + /** + * Takes an unencoded string and produces a QP encoded string from it. + * + * QP encoded strings have a maximum line length of 76 characters. + * If the first line needs to be shorter, indicate the difference with + * $firstLineOffset. + * + * @param string $string to encode + * @param int $firstLineOffset optional + * @param int $maxLineLength optional 0 indicates the default of 76 chars + * + * @return string + */ + public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) + { + if ($maxLineLength > 76 || $maxLineLength <= 0) { + $maxLineLength = 76; + } - $thisLineLength = $maxLineLength - $firstLineOffset; + $thisLineLength = $maxLineLength - $firstLineOffset; - $lines = []; - $lNo = 0; - $lines[$lNo] = ''; - $currentLine = &$lines[$lNo++]; - $size = $lineLen = 0; + $lines = []; + $lNo = 0; + $lines[$lNo] = ''; + $currentLine = &$lines[$lNo++]; + $size = $lineLen = 0; - $this->charStream->flushContents(); - $this->charStream->importString($string); + $this->charStream->flushContents(); + $this->charStream->importString($string); - // Fetching more than 4 chars at one is slower, as is fetching fewer bytes - // Conveniently 4 chars is the UTF-8 safe number since UTF-8 has up to 6 - // bytes per char and (6 * 4 * 3 = 72 chars per line) * =NN is 3 bytes - while (false !== $bytes = $this->nextSequence()) { - // If we're filtering the input - if (isset($this->filter)) { - // If we can't filter because we need more bytes - while ($this->filter->shouldBuffer($bytes)) { - // Then collect bytes into the buffer - if (false === $moreBytes = $this->nextSequence(1)) { - break; - } + // Fetching more than 4 chars at one is slower, as is fetching fewer bytes + // Conveniently 4 chars is the UTF-8 safe number since UTF-8 has up to 6 + // bytes per char and (6 * 4 * 3 = 72 chars per line) * =NN is 3 bytes + while (false !== $bytes = $this->nextSequence()) { + // If we're filtering the input + if (isset($this->filter)) { + // If we can't filter because we need more bytes + while ($this->filter->shouldBuffer($bytes)) { + // Then collect bytes into the buffer + if (false === $moreBytes = $this->nextSequence(1)) { + break; + } - foreach ($moreBytes as $b) { - $bytes[] = $b; - } - } - // And filter them - $bytes = $this->filter->filter($bytes); - } + foreach ($moreBytes as $b) { + $bytes[] = $b; + } + } + // And filter them + $bytes = $this->filter->filter($bytes); + } - $enc = $this->encodeByteSequence($bytes, $size); + $enc = $this->encodeByteSequence($bytes, $size); - $i = strpos($enc, '=0D=0A'); - $newLineLength = $lineLen + (false === $i ? $size : $i); + $i = strpos($enc, '=0D=0A'); + $newLineLength = $lineLen + (false === $i ? $size : $i); - if ($currentLine && $newLineLength >= $thisLineLength) { - $lines[$lNo] = ''; - $currentLine = &$lines[$lNo++]; - $thisLineLength = $maxLineLength; - $lineLen = 0; - } + if ($currentLine && $newLineLength >= $thisLineLength) { + $lines[$lNo] = ''; + $currentLine = &$lines[$lNo++]; + $thisLineLength = $maxLineLength; + $lineLen = 0; + } - $currentLine .= $enc; + $currentLine .= $enc; - if (false === $i) { - $lineLen += $size; - } else { - // 6 is the length of '=0D=0A'. - $lineLen = $size - strrpos($enc, '=0D=0A') - 6; - } - } + if (false === $i) { + $lineLen += $size; + } else { + // 6 is the length of '=0D=0A'. + $lineLen = $size - strrpos($enc, '=0D=0A') - 6; + } + } - return $this->standardize(implode("=\r\n", $lines)); - } + return $this->standardize(implode("=\r\n", $lines)); + } - /** - * Updates the charset used. - * - * @param string $charset - */ - public function charsetChanged($charset) - { - $this->charStream->setCharacterSet($charset); - } + /** + * Updates the charset used. + * + * @param string $charset + */ + public function charsetChanged($charset) + { + $this->charStream->setCharacterSet($charset); + } - /** - * Encode the given byte array into a verbatim QP form. - * - * @param int[] $bytes - * @param int $size - * - * @return string - */ - protected function encodeByteSequence(array $bytes, &$size) - { - $ret = ''; - $size = 0; - foreach ($bytes as $b) { - if (isset($this->safeMap[$b])) { - $ret .= $this->safeMap[$b]; - ++$size; - } else { - $ret .= self::$qpMap[$b]; - $size += 3; - } - } + /** + * Encode the given byte array into a verbatim QP form. + * + * @param int[] $bytes + * @param int $size + * + * @return string + */ + protected function encodeByteSequence(array $bytes, &$size) + { + $ret = ''; + $size = 0; + foreach ($bytes as $b) { + if (isset($this->safeMap[$b])) { + $ret .= $this->safeMap[$b]; + ++$size; + } else { + $ret .= self::$qpMap[$b]; + $size += 3; + } + } - return $ret; - } + return $ret; + } - /** - * Get the next sequence of bytes to read from the char stream. - * - * @param int $size number of bytes to read - * - * @return int[] - */ - protected function nextSequence($size = 4) - { - return $this->charStream->readBytes($size); - } + /** + * Get the next sequence of bytes to read from the char stream. + * + * @param int $size number of bytes to read + * + * @return int[] + */ + protected function nextSequence($size = 4) + { + return $this->charStream->readBytes($size); + } - /** - * Make sure CRLF is correct and HT/SPACE are in valid places. - * - * @param string $string - * - * @return string - */ - protected function standardize($string) - { - $string = str_replace(["\t=0D=0A", ' =0D=0A', '=0D=0A'], - ["=09\r\n", "=20\r\n", "\r\n"], $string - ); - switch ($end = \ord(substr($string, -1))) { - case 0x09: - case 0x20: - $string = substr_replace($string, self::$qpMap[$end], -1); - } + /** + * Make sure CRLF is correct and HT/SPACE are in valid places. + * + * @param string $string + * + * @return string + */ + protected function standardize($string) + { + $string = str_replace(["\t=0D=0A", ' =0D=0A', '=0D=0A'], + ["=09\r\n", "=20\r\n", "\r\n"], $string + ); + switch ($end = \ord(substr($string, -1))) { + case 0x09: + case 0x20: + $string = substr_replace($string, self::$qpMap[$end], -1); + } - return $string; - } + return $string; + } - /** - * Make a deep copy of object. - */ - public function __clone() - { - $this->charStream = clone $this->charStream; - } + /** + * Make a deep copy of object. + */ + public function __clone() + { + $this->charStream = clone $this->charStream; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Encoder/Rfc2231Encoder.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Encoder/Rfc2231Encoder.php index 7eac36813e0..488fcfd4717 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Encoder/Rfc2231Encoder.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Encoder/Rfc2231Encoder.php @@ -15,76 +15,76 @@ */ class Swift_Encoder_Rfc2231Encoder implements Swift_Encoder { - /** - * A character stream to use when reading a string as characters instead of bytes. - * - * @var Swift_CharacterStream - */ - private $charStream; + /** + * A character stream to use when reading a string as characters instead of bytes. + * + * @var Swift_CharacterStream + */ + private $charStream; - /** - * Creates a new Rfc2231Encoder using the given character stream instance. - */ - public function __construct(Swift_CharacterStream $charStream) - { - $this->charStream = $charStream; - } + /** + * Creates a new Rfc2231Encoder using the given character stream instance. + */ + public function __construct(Swift_CharacterStream $charStream) + { + $this->charStream = $charStream; + } - /** - * Takes an unencoded string and produces a string encoded according to - * RFC 2231 from it. - * - * @param string $string - * @param int $firstLineOffset - * @param int $maxLineLength optional, 0 indicates the default of 75 bytes - * - * @return string - */ - public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) - { - $lines = []; - $lineCount = 0; - $lines[] = ''; - $currentLine = &$lines[$lineCount++]; + /** + * Takes an unencoded string and produces a string encoded according to + * RFC 2231 from it. + * + * @param string $string + * @param int $firstLineOffset + * @param int $maxLineLength optional, 0 indicates the default of 75 bytes + * + * @return string + */ + public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) + { + $lines = []; + $lineCount = 0; + $lines[] = ''; + $currentLine = &$lines[$lineCount++]; - if (0 >= $maxLineLength) { - $maxLineLength = 75; - } + if (0 >= $maxLineLength) { + $maxLineLength = 75; + } - $this->charStream->flushContents(); - $this->charStream->importString($string); + $this->charStream->flushContents(); + $this->charStream->importString($string); - $thisLineLength = $maxLineLength - $firstLineOffset; + $thisLineLength = $maxLineLength - $firstLineOffset; - while (false !== $char = $this->charStream->read(4)) { - $encodedChar = rawurlencode($char); - if (0 != \strlen($currentLine) - && \strlen($currentLine.$encodedChar) > $thisLineLength) { - $lines[] = ''; - $currentLine = &$lines[$lineCount++]; - $thisLineLength = $maxLineLength; - } - $currentLine .= $encodedChar; - } + while (false !== $char = $this->charStream->read(4)) { + $encodedChar = rawurlencode($char); + if (0 != \strlen($currentLine) + && \strlen($currentLine.$encodedChar) > $thisLineLength) { + $lines[] = ''; + $currentLine = &$lines[$lineCount++]; + $thisLineLength = $maxLineLength; + } + $currentLine .= $encodedChar; + } - return implode("\r\n", $lines); - } + return implode("\r\n", $lines); + } - /** - * Updates the charset used. - * - * @param string $charset - */ - public function charsetChanged($charset) - { - $this->charStream->setCharacterSet($charset); - } + /** + * Updates the charset used. + * + * @param string $charset + */ + public function charsetChanged($charset) + { + $this->charStream->setCharacterSet($charset); + } - /** - * Make a deep copy of object. - */ - public function __clone() - { - $this->charStream = clone $this->charStream; - } + /** + * Make a deep copy of object. + */ + public function __clone() + { + $this->charStream = clone $this->charStream; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/CommandEvent.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/CommandEvent.php index 18994c184f3..1524fda752a 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/CommandEvent.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/CommandEvent.php @@ -15,50 +15,50 @@ */ class Swift_Events_CommandEvent extends Swift_Events_EventObject { - /** - * The command sent to the server. - * - * @var string - */ - private $command; + /** + * The command sent to the server. + * + * @var string + */ + private $command; - /** - * An array of codes which a successful response will contain. - * - * @var int[] - */ - private $successCodes = []; + /** + * An array of codes which a successful response will contain. + * + * @var int[] + */ + private $successCodes = []; - /** - * Create a new CommandEvent for $source with $command. - * - * @param string $command - * @param array $successCodes - */ - public function __construct(Swift_Transport $source, $command, $successCodes = []) - { - parent::__construct($source); - $this->command = $command; - $this->successCodes = $successCodes; - } + /** + * Create a new CommandEvent for $source with $command. + * + * @param string $command + * @param array $successCodes + */ + public function __construct(Swift_Transport $source, $command, $successCodes = []) + { + parent::__construct($source); + $this->command = $command; + $this->successCodes = $successCodes; + } - /** - * Get the command which was sent to the server. - * - * @return string - */ - public function getCommand() - { - return $this->command; - } + /** + * Get the command which was sent to the server. + * + * @return string + */ + public function getCommand() + { + return $this->command; + } - /** - * Get the numeric response codes which indicate success for this command. - * - * @return int[] - */ - public function getSuccessCodes() - { - return $this->successCodes; - } + /** + * Get the numeric response codes which indicate success for this command. + * + * @return int[] + */ + public function getSuccessCodes() + { + return $this->successCodes; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/CommandListener.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/CommandListener.php index b158eab462a..7dff32b4ee6 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/CommandListener.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/CommandListener.php @@ -15,8 +15,8 @@ */ interface Swift_Events_CommandListener extends Swift_Events_EventListener { - /** - * Invoked immediately following a command being sent. - */ - public function commandSent(Swift_Events_CommandEvent $evt); + /** + * Invoked immediately following a command being sent. + */ + public function commandSent(Swift_Events_CommandEvent $evt); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/EventDispatcher.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/EventDispatcher.php index df25a124863..1de97381930 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/EventDispatcher.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/EventDispatcher.php @@ -15,56 +15,56 @@ */ interface Swift_Events_EventDispatcher { - /** - * Create a new SendEvent for $source and $message. - * - * @return Swift_Events_SendEvent - */ - public function createSendEvent(Swift_Transport $source, Swift_Mime_SimpleMessage $message); + /** + * Create a new SendEvent for $source and $message. + * + * @return Swift_Events_SendEvent + */ + public function createSendEvent(Swift_Transport $source, Swift_Mime_SimpleMessage $message); - /** - * Create a new CommandEvent for $source and $command. - * - * @param string $command That will be executed - * @param array $successCodes That are needed - * - * @return Swift_Events_CommandEvent - */ - public function createCommandEvent(Swift_Transport $source, $command, $successCodes = []); + /** + * Create a new CommandEvent for $source and $command. + * + * @param string $command That will be executed + * @param array $successCodes That are needed + * + * @return Swift_Events_CommandEvent + */ + public function createCommandEvent(Swift_Transport $source, $command, $successCodes = []); - /** - * Create a new ResponseEvent for $source and $response. - * - * @param string $response - * @param bool $valid If the response is valid - * - * @return Swift_Events_ResponseEvent - */ - public function createResponseEvent(Swift_Transport $source, $response, $valid); + /** + * Create a new ResponseEvent for $source and $response. + * + * @param string $response + * @param bool $valid If the response is valid + * + * @return Swift_Events_ResponseEvent + */ + public function createResponseEvent(Swift_Transport $source, $response, $valid); - /** - * Create a new TransportChangeEvent for $source. - * - * @return Swift_Events_TransportChangeEvent - */ - public function createTransportChangeEvent(Swift_Transport $source); + /** + * Create a new TransportChangeEvent for $source. + * + * @return Swift_Events_TransportChangeEvent + */ + public function createTransportChangeEvent(Swift_Transport $source); - /** - * Create a new TransportExceptionEvent for $source. - * - * @return Swift_Events_TransportExceptionEvent - */ - public function createTransportExceptionEvent(Swift_Transport $source, Swift_TransportException $ex); + /** + * Create a new TransportExceptionEvent for $source. + * + * @return Swift_Events_TransportExceptionEvent + */ + public function createTransportExceptionEvent(Swift_Transport $source, Swift_TransportException $ex); - /** - * Bind an event listener to this dispatcher. - */ - public function bindEventListener(Swift_Events_EventListener $listener); + /** + * Bind an event listener to this dispatcher. + */ + public function bindEventListener(Swift_Events_EventListener $listener); - /** - * Dispatch the given Event to all suitable listeners. - * - * @param string $target method - */ - public function dispatchEvent(Swift_Events_EventObject $evt, $target); + /** + * Dispatch the given Event to all suitable listeners. + * + * @param string $target method + */ + public function dispatchEvent(Swift_Events_EventObject $evt, $target); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/EventObject.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/EventObject.php index 24a11f44e23..8e3f672cdeb 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/EventObject.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/EventObject.php @@ -15,47 +15,47 @@ */ class Swift_Events_EventObject implements Swift_Events_Event { - /** The source of this Event */ - private $source; + /** The source of this Event */ + private $source; - /** The state of this Event (should it bubble up the stack?) */ - private $bubbleCancelled = false; + /** The state of this Event (should it bubble up the stack?) */ + private $bubbleCancelled = false; - /** - * Create a new EventObject originating at $source. - * - * @param object $source - */ - public function __construct($source) - { - $this->source = $source; - } + /** + * Create a new EventObject originating at $source. + * + * @param object $source + */ + public function __construct($source) + { + $this->source = $source; + } - /** - * Get the source object of this event. - * - * @return object - */ - public function getSource() - { - return $this->source; - } + /** + * Get the source object of this event. + * + * @return object + */ + public function getSource() + { + return $this->source; + } - /** - * Prevent this Event from bubbling any further up the stack. - */ - public function cancelBubble($cancel = true) - { - $this->bubbleCancelled = $cancel; - } + /** + * Prevent this Event from bubbling any further up the stack. + */ + public function cancelBubble($cancel = true) + { + $this->bubbleCancelled = $cancel; + } - /** - * Returns true if this Event will not bubble any further up the stack. - * - * @return bool - */ - public function bubbleCancelled() - { - return $this->bubbleCancelled; - } + /** + * Returns true if this Event will not bubble any further up the stack. + * + * @return bool + */ + public function bubbleCancelled() + { + return $this->bubbleCancelled; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/ResponseEvent.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/ResponseEvent.php index ff7c37116ba..ddae7aab9a4 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/ResponseEvent.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/ResponseEvent.php @@ -15,50 +15,50 @@ */ class Swift_Events_ResponseEvent extends Swift_Events_EventObject { - /** - * The overall result. - * - * @var bool - */ - private $valid; + /** + * The overall result. + * + * @var bool + */ + private $valid; - /** - * The response received from the server. - * - * @var string - */ - private $response; + /** + * The response received from the server. + * + * @var string + */ + private $response; - /** - * Create a new ResponseEvent for $source and $response. - * - * @param string $response - * @param bool $valid - */ - public function __construct(Swift_Transport $source, $response, $valid = false) - { - parent::__construct($source); - $this->response = $response; - $this->valid = $valid; - } + /** + * Create a new ResponseEvent for $source and $response. + * + * @param string $response + * @param bool $valid + */ + public function __construct(Swift_Transport $source, $response, $valid = false) + { + parent::__construct($source); + $this->response = $response; + $this->valid = $valid; + } - /** - * Get the response which was received from the server. - * - * @return string - */ - public function getResponse() - { - return $this->response; - } + /** + * Get the response which was received from the server. + * + * @return string + */ + public function getResponse() + { + return $this->response; + } - /** - * Get the success status of this Event. - * - * @return bool - */ - public function isValid() - { - return $this->valid; - } + /** + * Get the success status of this Event. + * + * @return bool + */ + public function isValid() + { + return $this->valid; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/ResponseListener.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/ResponseListener.php index 85115a33811..ba607510426 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/ResponseListener.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/ResponseListener.php @@ -15,8 +15,8 @@ */ interface Swift_Events_ResponseListener extends Swift_Events_EventListener { - /** - * Invoked immediately following a response coming back. - */ - public function responseReceived(Swift_Events_ResponseEvent $evt); + /** + * Invoked immediately following a response coming back. + */ + public function responseReceived(Swift_Events_ResponseEvent $evt); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/SendEvent.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/SendEvent.php index a435691e0b0..c485f29010e 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/SendEvent.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/SendEvent.php @@ -15,112 +15,112 @@ */ class Swift_Events_SendEvent extends Swift_Events_EventObject { - /** Sending has yet to occur */ - const RESULT_PENDING = 0x0001; + /** Sending has yet to occur */ + const RESULT_PENDING = 0x0001; - /** Email is spooled, ready to be sent */ - const RESULT_SPOOLED = 0x0011; + /** Email is spooled, ready to be sent */ + const RESULT_SPOOLED = 0x0011; - /** Sending was successful */ - const RESULT_SUCCESS = 0x0010; + /** Sending was successful */ + const RESULT_SUCCESS = 0x0010; - /** Sending worked, but there were some failures */ - const RESULT_TENTATIVE = 0x0100; + /** Sending worked, but there were some failures */ + const RESULT_TENTATIVE = 0x0100; - /** Sending failed */ - const RESULT_FAILED = 0x1000; + /** Sending failed */ + const RESULT_FAILED = 0x1000; - /** - * The Message being sent. - * - * @var Swift_Mime_SimpleMessage - */ - private $message; + /** + * The Message being sent. + * + * @var Swift_Mime_SimpleMessage + */ + private $message; - /** - * Any recipients which failed after sending. - * - * @var string[] - */ - private $failedRecipients = []; + /** + * Any recipients which failed after sending. + * + * @var string[] + */ + private $failedRecipients = []; - /** - * The overall result as a bitmask from the class constants. - * - * @var int - */ - private $result; + /** + * The overall result as a bitmask from the class constants. + * + * @var int + */ + private $result; - /** - * Create a new SendEvent for $source and $message. - */ - public function __construct(Swift_Transport $source, Swift_Mime_SimpleMessage $message) - { - parent::__construct($source); - $this->message = $message; - $this->result = self::RESULT_PENDING; - } + /** + * Create a new SendEvent for $source and $message. + */ + public function __construct(Swift_Transport $source, Swift_Mime_SimpleMessage $message) + { + parent::__construct($source); + $this->message = $message; + $this->result = self::RESULT_PENDING; + } - /** - * Get the Transport used to send the Message. - * - * @return Swift_Transport - */ - public function getTransport() - { - return $this->getSource(); - } + /** + * Get the Transport used to send the Message. + * + * @return Swift_Transport + */ + public function getTransport() + { + return $this->getSource(); + } - /** - * Get the Message being sent. - * - * @return Swift_Mime_SimpleMessage - */ - public function getMessage() - { - return $this->message; - } + /** + * Get the Message being sent. + * + * @return Swift_Mime_SimpleMessage + */ + public function getMessage() + { + return $this->message; + } - /** - * Set the array of addresses that failed in sending. - * - * @param array $recipients - */ - public function setFailedRecipients($recipients) - { - $this->failedRecipients = $recipients; - } + /** + * Set the array of addresses that failed in sending. + * + * @param array $recipients + */ + public function setFailedRecipients($recipients) + { + $this->failedRecipients = $recipients; + } - /** - * Get an recipient addresses which were not accepted for delivery. - * - * @return string[] - */ - public function getFailedRecipients() - { - return $this->failedRecipients; - } + /** + * Get an recipient addresses which were not accepted for delivery. + * + * @return string[] + */ + public function getFailedRecipients() + { + return $this->failedRecipients; + } - /** - * Set the result of sending. - * - * @param int $result - */ - public function setResult($result) - { - $this->result = $result; - } + /** + * Set the result of sending. + * + * @param int $result + */ + public function setResult($result) + { + $this->result = $result; + } - /** - * Get the result of this Event. - * - * The return value is a bitmask from - * {@see RESULT_PENDING, RESULT_SUCCESS, RESULT_TENTATIVE, RESULT_FAILED} - * - * @return int - */ - public function getResult() - { - return $this->result; - } + /** + * Get the result of this Event. + * + * The return value is a bitmask from + * {@see RESULT_PENDING, RESULT_SUCCESS, RESULT_TENTATIVE, RESULT_FAILED} + * + * @return int + */ + public function getResult() + { + return $this->result; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/SendListener.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/SendListener.php index f7bf55ef56c..33f7f03f870 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/SendListener.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/SendListener.php @@ -15,13 +15,13 @@ */ interface Swift_Events_SendListener extends Swift_Events_EventListener { - /** - * Invoked immediately before the Message is sent. - */ - public function beforeSendPerformed(Swift_Events_SendEvent $evt); + /** + * Invoked immediately before the Message is sent. + */ + public function beforeSendPerformed(Swift_Events_SendEvent $evt); - /** - * Invoked immediately after the Message is sent. - */ - public function sendPerformed(Swift_Events_SendEvent $evt); + /** + * Invoked immediately after the Message is sent. + */ + public function sendPerformed(Swift_Events_SendEvent $evt); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/SimpleEventDispatcher.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/SimpleEventDispatcher.php index 6557103c99a..7531214d824 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/SimpleEventDispatcher.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/SimpleEventDispatcher.php @@ -15,128 +15,128 @@ */ class Swift_Events_SimpleEventDispatcher implements Swift_Events_EventDispatcher { - /** A map of event types to their associated listener types */ - private $eventMap = []; + /** A map of event types to their associated listener types */ + private $eventMap = []; - /** Event listeners bound to this dispatcher */ - private $listeners = []; + /** Event listeners bound to this dispatcher */ + private $listeners = []; - /** - * Create a new EventDispatcher. - */ - public function __construct() - { - $this->eventMap = [ - 'Swift_Events_CommandEvent' => 'Swift_Events_CommandListener', - 'Swift_Events_ResponseEvent' => 'Swift_Events_ResponseListener', - 'Swift_Events_SendEvent' => 'Swift_Events_SendListener', - 'Swift_Events_TransportChangeEvent' => 'Swift_Events_TransportChangeListener', - 'Swift_Events_TransportExceptionEvent' => 'Swift_Events_TransportExceptionListener', - ]; - } + /** + * Create a new EventDispatcher. + */ + public function __construct() + { + $this->eventMap = [ + 'Swift_Events_CommandEvent' => 'Swift_Events_CommandListener', + 'Swift_Events_ResponseEvent' => 'Swift_Events_ResponseListener', + 'Swift_Events_SendEvent' => 'Swift_Events_SendListener', + 'Swift_Events_TransportChangeEvent' => 'Swift_Events_TransportChangeListener', + 'Swift_Events_TransportExceptionEvent' => 'Swift_Events_TransportExceptionListener', + ]; + } - /** - * Create a new SendEvent for $source and $message. - * - * @return Swift_Events_SendEvent - */ - public function createSendEvent(Swift_Transport $source, Swift_Mime_SimpleMessage $message) - { - return new Swift_Events_SendEvent($source, $message); - } + /** + * Create a new SendEvent for $source and $message. + * + * @return Swift_Events_SendEvent + */ + public function createSendEvent(Swift_Transport $source, Swift_Mime_SimpleMessage $message) + { + return new Swift_Events_SendEvent($source, $message); + } - /** - * Create a new CommandEvent for $source and $command. - * - * @param string $command That will be executed - * @param array $successCodes That are needed - * - * @return Swift_Events_CommandEvent - */ - public function createCommandEvent(Swift_Transport $source, $command, $successCodes = []) - { - return new Swift_Events_CommandEvent($source, $command, $successCodes); - } + /** + * Create a new CommandEvent for $source and $command. + * + * @param string $command That will be executed + * @param array $successCodes That are needed + * + * @return Swift_Events_CommandEvent + */ + public function createCommandEvent(Swift_Transport $source, $command, $successCodes = []) + { + return new Swift_Events_CommandEvent($source, $command, $successCodes); + } - /** - * Create a new ResponseEvent for $source and $response. - * - * @param string $response - * @param bool $valid If the response is valid - * - * @return Swift_Events_ResponseEvent - */ - public function createResponseEvent(Swift_Transport $source, $response, $valid) - { - return new Swift_Events_ResponseEvent($source, $response, $valid); - } + /** + * Create a new ResponseEvent for $source and $response. + * + * @param string $response + * @param bool $valid If the response is valid + * + * @return Swift_Events_ResponseEvent + */ + public function createResponseEvent(Swift_Transport $source, $response, $valid) + { + return new Swift_Events_ResponseEvent($source, $response, $valid); + } - /** - * Create a new TransportChangeEvent for $source. - * - * @return Swift_Events_TransportChangeEvent - */ - public function createTransportChangeEvent(Swift_Transport $source) - { - return new Swift_Events_TransportChangeEvent($source); - } + /** + * Create a new TransportChangeEvent for $source. + * + * @return Swift_Events_TransportChangeEvent + */ + public function createTransportChangeEvent(Swift_Transport $source) + { + return new Swift_Events_TransportChangeEvent($source); + } - /** - * Create a new TransportExceptionEvent for $source. - * - * @return Swift_Events_TransportExceptionEvent - */ - public function createTransportExceptionEvent(Swift_Transport $source, Swift_TransportException $ex) - { - return new Swift_Events_TransportExceptionEvent($source, $ex); - } + /** + * Create a new TransportExceptionEvent for $source. + * + * @return Swift_Events_TransportExceptionEvent + */ + public function createTransportExceptionEvent(Swift_Transport $source, Swift_TransportException $ex) + { + return new Swift_Events_TransportExceptionEvent($source, $ex); + } - /** - * Bind an event listener to this dispatcher. - */ - public function bindEventListener(Swift_Events_EventListener $listener) - { - foreach ($this->listeners as $l) { - // Already loaded - if ($l === $listener) { - return; - } - } - $this->listeners[] = $listener; - } + /** + * Bind an event listener to this dispatcher. + */ + public function bindEventListener(Swift_Events_EventListener $listener) + { + foreach ($this->listeners as $l) { + // Already loaded + if ($l === $listener) { + return; + } + } + $this->listeners[] = $listener; + } - /** - * Dispatch the given Event to all suitable listeners. - * - * @param string $target method - */ - public function dispatchEvent(Swift_Events_EventObject $evt, $target) - { - $bubbleQueue = $this->prepareBubbleQueue($evt); - $this->bubble($bubbleQueue, $evt, $target); - } + /** + * Dispatch the given Event to all suitable listeners. + * + * @param string $target method + */ + public function dispatchEvent(Swift_Events_EventObject $evt, $target) + { + $bubbleQueue = $this->prepareBubbleQueue($evt); + $this->bubble($bubbleQueue, $evt, $target); + } - /** Queue listeners on a stack ready for $evt to be bubbled up it */ - private function prepareBubbleQueue(Swift_Events_EventObject $evt) - { - $bubbleQueue = []; - $evtClass = \get_class($evt); - foreach ($this->listeners as $listener) { - if (\array_key_exists($evtClass, $this->eventMap) - && ($listener instanceof $this->eventMap[$evtClass])) { - $bubbleQueue[] = $listener; - } - } + /** Queue listeners on a stack ready for $evt to be bubbled up it */ + private function prepareBubbleQueue(Swift_Events_EventObject $evt) + { + $bubbleQueue = []; + $evtClass = \get_class($evt); + foreach ($this->listeners as $listener) { + if (\array_key_exists($evtClass, $this->eventMap) + && ($listener instanceof $this->eventMap[$evtClass])) { + $bubbleQueue[] = $listener; + } + } - return $bubbleQueue; - } + return $bubbleQueue; + } - /** Bubble $evt up the stack calling $target() on each listener */ - private function bubble(array &$bubbleQueue, Swift_Events_EventObject $evt, $target) - { - if (!$evt->bubbleCancelled() && $listener = array_shift($bubbleQueue)) { - $listener->$target($evt); - $this->bubble($bubbleQueue, $evt, $target); - } - } + /** Bubble $evt up the stack calling $target() on each listener */ + private function bubble(array &$bubbleQueue, Swift_Events_EventObject $evt, $target) + { + if (!$evt->bubbleCancelled() && $listener = array_shift($bubbleQueue)) { + $listener->$target($evt); + $this->bubble($bubbleQueue, $evt, $target); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/TransportChangeListener.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/TransportChangeListener.php index 4a7492bc551..24d6bde50bd 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/TransportChangeListener.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/TransportChangeListener.php @@ -15,23 +15,23 @@ */ interface Swift_Events_TransportChangeListener extends Swift_Events_EventListener { - /** - * Invoked just before a Transport is started. - */ - public function beforeTransportStarted(Swift_Events_TransportChangeEvent $evt); + /** + * Invoked just before a Transport is started. + */ + public function beforeTransportStarted(Swift_Events_TransportChangeEvent $evt); - /** - * Invoked immediately after the Transport is started. - */ - public function transportStarted(Swift_Events_TransportChangeEvent $evt); + /** + * Invoked immediately after the Transport is started. + */ + public function transportStarted(Swift_Events_TransportChangeEvent $evt); - /** - * Invoked just before a Transport is stopped. - */ - public function beforeTransportStopped(Swift_Events_TransportChangeEvent $evt); + /** + * Invoked just before a Transport is stopped. + */ + public function beforeTransportStopped(Swift_Events_TransportChangeEvent $evt); - /** - * Invoked immediately after the Transport is stopped. - */ - public function transportStopped(Swift_Events_TransportChangeEvent $evt); + /** + * Invoked immediately after the Transport is stopped. + */ + public function transportStopped(Swift_Events_TransportChangeEvent $evt); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/TransportExceptionEvent.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/TransportExceptionEvent.php index df442cc70f6..0301c8dfc11 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/TransportExceptionEvent.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/TransportExceptionEvent.php @@ -15,29 +15,29 @@ */ class Swift_Events_TransportExceptionEvent extends Swift_Events_EventObject { - /** - * The Exception thrown. - * - * @var Swift_TransportException - */ - private $exception; + /** + * The Exception thrown. + * + * @var Swift_TransportException + */ + private $exception; - /** - * Create a new TransportExceptionEvent for $transport. - */ - public function __construct(Swift_Transport $transport, Swift_TransportException $ex) - { - parent::__construct($transport); - $this->exception = $ex; - } + /** + * Create a new TransportExceptionEvent for $transport. + */ + public function __construct(Swift_Transport $transport, Swift_TransportException $ex) + { + parent::__construct($transport); + $this->exception = $ex; + } - /** - * Get the TransportException thrown. - * - * @return Swift_TransportException - */ - public function getException() - { - return $this->exception; - } + /** + * Get the TransportException thrown. + * + * @return Swift_TransportException + */ + public function getException() + { + return $this->exception; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/TransportExceptionListener.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/TransportExceptionListener.php index ad80eb01d0f..1de6e6e59a9 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/TransportExceptionListener.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/TransportExceptionListener.php @@ -15,8 +15,8 @@ */ interface Swift_Events_TransportExceptionListener extends Swift_Events_EventListener { - /** - * Invoked as a TransportException is thrown in the Transport system. - */ - public function exceptionThrown(Swift_Events_TransportExceptionEvent $evt); + /** + * Invoked as a TransportException is thrown in the Transport system. + */ + public function exceptionThrown(Swift_Events_TransportExceptionEvent $evt); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/FailoverTransport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/FailoverTransport.php index af0be917903..57d343c9ed3 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/FailoverTransport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/FailoverTransport.php @@ -15,19 +15,19 @@ */ class Swift_FailoverTransport extends Swift_Transport_FailoverTransport { - /** - * Creates a new FailoverTransport with $transports. - * - * @param Swift_Transport[] $transports - */ - public function __construct($transports = []) - { - \call_user_func_array( - [$this, 'Swift_Transport_FailoverTransport::__construct'], - Swift_DependencyContainer::getInstance() - ->createDependenciesFor('transport.failover') - ); + /** + * Creates a new FailoverTransport with $transports. + * + * @param Swift_Transport[] $transports + */ + public function __construct($transports = []) + { + \call_user_func_array( + [$this, 'Swift_Transport_FailoverTransport::__construct'], + Swift_DependencyContainer::getInstance() + ->createDependenciesFor('transport.failover') + ); - $this->setTransports($transports); - } + $this->setTransports($transports); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/FileSpool.php b/htdocs/includes/swiftmailer/lib/classes/Swift/FileSpool.php index 7af8471c9d7..4dd49a65270 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/FileSpool.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/FileSpool.php @@ -16,193 +16,193 @@ */ class Swift_FileSpool extends Swift_ConfigurableSpool { - /** The spool directory */ - private $path; + /** The spool directory */ + private $path; - /** - * File WriteRetry Limit. - * - * @var int - */ - private $retryLimit = 10; + /** + * File WriteRetry Limit. + * + * @var int + */ + private $retryLimit = 10; - /** - * Create a new FileSpool. - * - * @param string $path - * - * @throws Swift_IoException - */ - public function __construct($path) - { - $this->path = $path; + /** + * Create a new FileSpool. + * + * @param string $path + * + * @throws Swift_IoException + */ + public function __construct($path) + { + $this->path = $path; - if (!file_exists($this->path)) { - if (!mkdir($this->path, 0777, true)) { - throw new Swift_IoException(sprintf('Unable to create path "%s".', $this->path)); - } - } - } + if (!file_exists($this->path)) { + if (!mkdir($this->path, 0777, true)) { + throw new Swift_IoException(sprintf('Unable to create path "%s".', $this->path)); + } + } + } - /** - * Tests if this Spool mechanism has started. - * - * @return bool - */ - public function isStarted() - { - return true; - } + /** + * Tests if this Spool mechanism has started. + * + * @return bool + */ + public function isStarted() + { + return true; + } - /** - * Starts this Spool mechanism. - */ - public function start() - { - } + /** + * Starts this Spool mechanism. + */ + public function start() + { + } - /** - * Stops this Spool mechanism. - */ - public function stop() - { - } + /** + * Stops this Spool mechanism. + */ + public function stop() + { + } - /** - * Allow to manage the enqueuing retry limit. - * - * Default, is ten and allows over 64^20 different fileNames - * - * @param int $limit - */ - public function setRetryLimit($limit) - { - $this->retryLimit = $limit; - } + /** + * Allow to manage the enqueuing retry limit. + * + * Default, is ten and allows over 64^20 different fileNames + * + * @param int $limit + */ + public function setRetryLimit($limit) + { + $this->retryLimit = $limit; + } - /** - * Queues a message. - * - * @param Swift_Mime_SimpleMessage $message The message to store - * - * @throws Swift_IoException - * - * @return bool - */ - public function queueMessage(Swift_Mime_SimpleMessage $message) - { - $ser = serialize($message); - $fileName = $this->path.'/'.$this->getRandomString(10); - for ($i = 0; $i < $this->retryLimit; ++$i) { - /* We try an exclusive creation of the file. This is an atomic operation, it avoid locking mechanism */ - $fp = @fopen($fileName.'.message', 'xb'); - if (false !== $fp) { - if (false === fwrite($fp, $ser)) { - return false; - } + /** + * Queues a message. + * + * @param Swift_Mime_SimpleMessage $message The message to store + * + * @throws Swift_IoException + * + * @return bool + */ + public function queueMessage(Swift_Mime_SimpleMessage $message) + { + $ser = serialize($message); + $fileName = $this->path.'/'.$this->getRandomString(10); + for ($i = 0; $i < $this->retryLimit; ++$i) { + /* We try an exclusive creation of the file. This is an atomic operation, it avoid locking mechanism */ + $fp = @fopen($fileName.'.message', 'xb'); + if (false !== $fp) { + if (false === fwrite($fp, $ser)) { + return false; + } - return fclose($fp); - } else { - /* The file already exists, we try a longer fileName */ - $fileName .= $this->getRandomString(1); - } - } + return fclose($fp); + } else { + /* The file already exists, we try a longer fileName */ + $fileName .= $this->getRandomString(1); + } + } - throw new Swift_IoException(sprintf('Unable to create a file for enqueuing Message in "%s".', $this->path)); - } + throw new Swift_IoException(sprintf('Unable to create a file for enqueuing Message in "%s".', $this->path)); + } - /** - * Execute a recovery if for any reason a process is sending for too long. - * - * @param int $timeout in second Defaults is for very slow smtp responses - */ - public function recover($timeout = 900) - { - foreach (new DirectoryIterator($this->path) as $file) { - $file = $file->getRealPath(); + /** + * Execute a recovery if for any reason a process is sending for too long. + * + * @param int $timeout in second Defaults is for very slow smtp responses + */ + public function recover($timeout = 900) + { + foreach (new DirectoryIterator($this->path) as $file) { + $file = $file->getRealPath(); - if ('.message.sending' == substr($file, -16)) { - $lockedtime = filectime($file); - if ((time() - $lockedtime) > $timeout) { - rename($file, substr($file, 0, -8)); - } - } - } - } + if ('.message.sending' == substr($file, -16)) { + $lockedtime = filectime($file); + if ((time() - $lockedtime) > $timeout) { + rename($file, substr($file, 0, -8)); + } + } + } + } - /** - * Sends messages using the given transport instance. - * - * @param Swift_Transport $transport A transport instance - * @param string[] $failedRecipients An array of failures by-reference - * - * @return int The number of sent e-mail's - */ - public function flushQueue(Swift_Transport $transport, &$failedRecipients = null) - { - $directoryIterator = new DirectoryIterator($this->path); + /** + * Sends messages using the given transport instance. + * + * @param Swift_Transport $transport A transport instance + * @param string[] $failedRecipients An array of failures by-reference + * + * @return int The number of sent e-mail's + */ + public function flushQueue(Swift_Transport $transport, &$failedRecipients = null) + { + $directoryIterator = new DirectoryIterator($this->path); - /* Start the transport only if there are queued files to send */ - if (!$transport->isStarted()) { - foreach ($directoryIterator as $file) { - if ('.message' == substr($file->getRealPath(), -8)) { - $transport->start(); - break; - } - } - } + /* Start the transport only if there are queued files to send */ + if (!$transport->isStarted()) { + foreach ($directoryIterator as $file) { + if ('.message' == substr($file->getRealPath(), -8)) { + $transport->start(); + break; + } + } + } - $failedRecipients = (array) $failedRecipients; - $count = 0; - $time = time(); - foreach ($directoryIterator as $file) { - $file = $file->getRealPath(); + $failedRecipients = (array) $failedRecipients; + $count = 0; + $time = time(); + foreach ($directoryIterator as $file) { + $file = $file->getRealPath(); - if ('.message' != substr($file, -8)) { - continue; - } + if ('.message' != substr($file, -8)) { + continue; + } - /* We try a rename, it's an atomic operation, and avoid locking the file */ - if (rename($file, $file.'.sending')) { - $message = unserialize(file_get_contents($file.'.sending')); + /* We try a rename, it's an atomic operation, and avoid locking the file */ + if (rename($file, $file.'.sending')) { + $message = unserialize(file_get_contents($file.'.sending')); - $count += $transport->send($message, $failedRecipients); + $count += $transport->send($message, $failedRecipients); - unlink($file.'.sending'); - } else { - /* This message has just been catched by another process */ - continue; - } + unlink($file.'.sending'); + } else { + /* This message has just been catched by another process */ + continue; + } - if ($this->getMessageLimit() && $count >= $this->getMessageLimit()) { - break; - } + if ($this->getMessageLimit() && $count >= $this->getMessageLimit()) { + break; + } - if ($this->getTimeLimit() && (time() - $time) >= $this->getTimeLimit()) { - break; - } - } + if ($this->getTimeLimit() && (time() - $time) >= $this->getTimeLimit()) { + break; + } + } - return $count; - } + return $count; + } - /** - * Returns a random string needed to generate a fileName for the queue. - * - * @param int $count - * - * @return string - */ - protected function getRandomString($count) - { - // This string MUST stay FS safe, avoid special chars - $base = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-'; - $ret = ''; - $strlen = \strlen($base); - for ($i = 0; $i < $count; ++$i) { - $ret .= $base[random_int(0, $strlen - 1)]; - } + /** + * Returns a random string needed to generate a fileName for the queue. + * + * @param int $count + * + * @return string + */ + protected function getRandomString($count) + { + // This string MUST stay FS safe, avoid special chars + $base = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-'; + $ret = ''; + $strlen = \strlen($base); + for ($i = 0; $i < $count; ++$i) { + $ret .= $base[random_int(0, $strlen - 1)]; + } - return $ret; - } + return $ret; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Filterable.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Filterable.php index efa1b1def5e..9073bf5b663 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Filterable.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Filterable.php @@ -15,17 +15,17 @@ */ interface Swift_Filterable { - /** - * Add a new StreamFilter, referenced by $key. - * - * @param string $key - */ - public function addFilter(Swift_StreamFilter $filter, $key); + /** + * Add a new StreamFilter, referenced by $key. + * + * @param string $key + */ + public function addFilter(Swift_StreamFilter $filter, $key); - /** - * Remove an existing filter using $key. - * - * @param string $key - */ - public function removeFilter($key); + /** + * Remove an existing filter using $key. + * + * @param string $key + */ + public function removeFilter($key); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/InputByteStream.php b/htdocs/includes/swiftmailer/lib/classes/Swift/InputByteStream.php index 379a5a17870..67a12acc6f5 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/InputByteStream.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/InputByteStream.php @@ -18,58 +18,58 @@ */ interface Swift_InputByteStream { - /** - * Writes $bytes to the end of the stream. - * - * Writing may not happen immediately if the stream chooses to buffer. If - * you want to write these bytes with immediate effect, call {@link commit()} - * after calling write(). - * - * This method returns the sequence ID of the write (i.e. 1 for first, 2 for - * second, etc etc). - * - * @param string $bytes - * - * @throws Swift_IoException - * - * @return int - */ - public function write($bytes); + /** + * Writes $bytes to the end of the stream. + * + * Writing may not happen immediately if the stream chooses to buffer. If + * you want to write these bytes with immediate effect, call {@link commit()} + * after calling write(). + * + * This method returns the sequence ID of the write (i.e. 1 for first, 2 for + * second, etc etc). + * + * @param string $bytes + * + * @throws Swift_IoException + * + * @return int + */ + public function write($bytes); - /** - * For any bytes that are currently buffered inside the stream, force them - * off the buffer. - * - * @throws Swift_IoException - */ - public function commit(); + /** + * For any bytes that are currently buffered inside the stream, force them + * off the buffer. + * + * @throws Swift_IoException + */ + public function commit(); - /** - * Attach $is to this stream. - * - * The stream acts as an observer, receiving all data that is written. - * All {@link write()} and {@link flushBuffers()} operations will be mirrored. - * - * @param Swift_InputByteStream $is - */ - public function bind(self $is); + /** + * Attach $is to this stream. + * + * The stream acts as an observer, receiving all data that is written. + * All {@link write()} and {@link flushBuffers()} operations will be mirrored. + * + * @param Swift_InputByteStream $is + */ + public function bind(self $is); - /** - * Remove an already bound stream. - * - * If $is is not bound, no errors will be raised. - * If the stream currently has any buffered data it will be written to $is - * before unbinding occurs. - * - * @param Swift_InputByteStream $is - */ - public function unbind(self $is); + /** + * Remove an already bound stream. + * + * If $is is not bound, no errors will be raised. + * If the stream currently has any buffered data it will be written to $is + * before unbinding occurs. + * + * @param Swift_InputByteStream $is + */ + public function unbind(self $is); - /** - * Flush the contents of the stream (empty it) and set the internal pointer - * to the beginning. - * - * @throws Swift_IoException - */ - public function flushBuffers(); + /** + * Flush the contents of the stream (empty it) and set the internal pointer + * to the beginning. + * + * @throws Swift_IoException + */ + public function flushBuffers(); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/IoException.php b/htdocs/includes/swiftmailer/lib/classes/Swift/IoException.php index 5452bd416a6..8a8b9ff9029 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/IoException.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/IoException.php @@ -15,14 +15,14 @@ */ class Swift_IoException extends Swift_SwiftException { - /** - * Create a new IoException with $message. - * - * @param string $message - * @param int $code - */ - public function __construct($message, $code = 0, Exception $previous = null) - { - parent::__construct($message, $code, $previous); - } + /** + * Create a new IoException with $message. + * + * @param string $message + * @param int $code + */ + public function __construct($message, $code = 0, Exception $previous = null) + { + parent::__construct($message, $code, $previous); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache.php b/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache.php index 87f6a074212..791085d85e7 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache.php @@ -15,90 +15,90 @@ */ interface Swift_KeyCache { - /** Mode for replacing existing cached data */ - const MODE_WRITE = 1; + /** Mode for replacing existing cached data */ + const MODE_WRITE = 1; - /** Mode for appending data to the end of existing cached data */ - const MODE_APPEND = 2; + /** Mode for appending data to the end of existing cached data */ + const MODE_APPEND = 2; - /** - * Set a string into the cache under $itemKey for the namespace $nsKey. - * - * @see MODE_WRITE, MODE_APPEND - * - * @param string $nsKey - * @param string $itemKey - * @param string $string - * @param int $mode - */ - public function setString($nsKey, $itemKey, $string, $mode); + /** + * Set a string into the cache under $itemKey for the namespace $nsKey. + * + * @see MODE_WRITE, MODE_APPEND + * + * @param string $nsKey + * @param string $itemKey + * @param string $string + * @param int $mode + */ + public function setString($nsKey, $itemKey, $string, $mode); - /** - * Set a ByteStream into the cache under $itemKey for the namespace $nsKey. - * - * @see MODE_WRITE, MODE_APPEND - * - * @param string $nsKey - * @param string $itemKey - * @param int $mode - */ - public function importFromByteStream($nsKey, $itemKey, Swift_OutputByteStream $os, $mode); + /** + * Set a ByteStream into the cache under $itemKey for the namespace $nsKey. + * + * @see MODE_WRITE, MODE_APPEND + * + * @param string $nsKey + * @param string $itemKey + * @param int $mode + */ + public function importFromByteStream($nsKey, $itemKey, Swift_OutputByteStream $os, $mode); - /** - * Provides a ByteStream which when written to, writes data to $itemKey. - * - * NOTE: The stream will always write in append mode. - * If the optional third parameter is passed all writes will go through $is. - * - * @param string $nsKey - * @param string $itemKey - * @param Swift_InputByteStream $is optional input stream - * - * @return Swift_InputByteStream - */ - public function getInputByteStream($nsKey, $itemKey, Swift_InputByteStream $is = null); + /** + * Provides a ByteStream which when written to, writes data to $itemKey. + * + * NOTE: The stream will always write in append mode. + * If the optional third parameter is passed all writes will go through $is. + * + * @param string $nsKey + * @param string $itemKey + * @param Swift_InputByteStream $is optional input stream + * + * @return Swift_InputByteStream + */ + public function getInputByteStream($nsKey, $itemKey, Swift_InputByteStream $is = null); - /** - * Get data back out of the cache as a string. - * - * @param string $nsKey - * @param string $itemKey - * - * @return string - */ - public function getString($nsKey, $itemKey); + /** + * Get data back out of the cache as a string. + * + * @param string $nsKey + * @param string $itemKey + * + * @return string + */ + public function getString($nsKey, $itemKey); - /** - * Get data back out of the cache as a ByteStream. - * - * @param string $nsKey - * @param string $itemKey - * @param Swift_InputByteStream $is stream to write the data to - */ - public function exportToByteStream($nsKey, $itemKey, Swift_InputByteStream $is); + /** + * Get data back out of the cache as a ByteStream. + * + * @param string $nsKey + * @param string $itemKey + * @param Swift_InputByteStream $is stream to write the data to + */ + public function exportToByteStream($nsKey, $itemKey, Swift_InputByteStream $is); - /** - * Check if the given $itemKey exists in the namespace $nsKey. - * - * @param string $nsKey - * @param string $itemKey - * - * @return bool - */ - public function hasKey($nsKey, $itemKey); + /** + * Check if the given $itemKey exists in the namespace $nsKey. + * + * @param string $nsKey + * @param string $itemKey + * + * @return bool + */ + public function hasKey($nsKey, $itemKey); - /** - * Clear data for $itemKey in the namespace $nsKey if it exists. - * - * @param string $nsKey - * @param string $itemKey - */ - public function clearKey($nsKey, $itemKey); + /** + * Clear data for $itemKey in the namespace $nsKey if it exists. + * + * @param string $nsKey + * @param string $itemKey + */ + public function clearKey($nsKey, $itemKey); - /** - * Clear all data in the namespace $nsKey if it exists. - * - * @param string $nsKey - */ - public function clearAll($nsKey); + /** + * Clear all data in the namespace $nsKey if it exists. + * + * @param string $nsKey + */ + public function clearAll($nsKey); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/ArrayKeyCache.php b/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/ArrayKeyCache.php index e8fef1c95d4..92a6c2d107e 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/ArrayKeyCache.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/ArrayKeyCache.php @@ -15,183 +15,183 @@ */ class Swift_KeyCache_ArrayKeyCache implements Swift_KeyCache { - /** - * Cache contents. - * - * @var array - */ - private $contents = []; + /** + * Cache contents. + * + * @var array + */ + private $contents = []; - /** - * An InputStream for cloning. - * - * @var Swift_KeyCache_KeyCacheInputStream - */ - private $stream; + /** + * An InputStream for cloning. + * + * @var Swift_KeyCache_KeyCacheInputStream + */ + private $stream; - /** - * Create a new ArrayKeyCache with the given $stream for cloning to make - * InputByteStreams. - */ - public function __construct(Swift_KeyCache_KeyCacheInputStream $stream) - { - $this->stream = $stream; - } + /** + * Create a new ArrayKeyCache with the given $stream for cloning to make + * InputByteStreams. + */ + public function __construct(Swift_KeyCache_KeyCacheInputStream $stream) + { + $this->stream = $stream; + } - /** - * Set a string into the cache under $itemKey for the namespace $nsKey. - * - * @see MODE_WRITE, MODE_APPEND - * - * @param string $nsKey - * @param string $itemKey - * @param string $string - * @param int $mode - */ - public function setString($nsKey, $itemKey, $string, $mode) - { - $this->prepareCache($nsKey); - switch ($mode) { - case self::MODE_WRITE: - $this->contents[$nsKey][$itemKey] = $string; - break; - case self::MODE_APPEND: - if (!$this->hasKey($nsKey, $itemKey)) { - $this->contents[$nsKey][$itemKey] = ''; - } - $this->contents[$nsKey][$itemKey] .= $string; - break; - default: - throw new Swift_SwiftException('Invalid mode ['.$mode.'] used to set nsKey='.$nsKey.', itemKey='.$itemKey); - } - } + /** + * Set a string into the cache under $itemKey for the namespace $nsKey. + * + * @see MODE_WRITE, MODE_APPEND + * + * @param string $nsKey + * @param string $itemKey + * @param string $string + * @param int $mode + */ + public function setString($nsKey, $itemKey, $string, $mode) + { + $this->prepareCache($nsKey); + switch ($mode) { + case self::MODE_WRITE: + $this->contents[$nsKey][$itemKey] = $string; + break; + case self::MODE_APPEND: + if (!$this->hasKey($nsKey, $itemKey)) { + $this->contents[$nsKey][$itemKey] = ''; + } + $this->contents[$nsKey][$itemKey] .= $string; + break; + default: + throw new Swift_SwiftException('Invalid mode ['.$mode.'] used to set nsKey='.$nsKey.', itemKey='.$itemKey); + } + } - /** - * Set a ByteStream into the cache under $itemKey for the namespace $nsKey. - * - * @see MODE_WRITE, MODE_APPEND - * - * @param string $nsKey - * @param string $itemKey - * @param int $mode - */ - public function importFromByteStream($nsKey, $itemKey, Swift_OutputByteStream $os, $mode) - { - $this->prepareCache($nsKey); - switch ($mode) { - case self::MODE_WRITE: - $this->clearKey($nsKey, $itemKey); - // no break - case self::MODE_APPEND: - if (!$this->hasKey($nsKey, $itemKey)) { - $this->contents[$nsKey][$itemKey] = ''; - } - while (false !== $bytes = $os->read(8192)) { - $this->contents[$nsKey][$itemKey] .= $bytes; - } - break; - default: - throw new Swift_SwiftException('Invalid mode ['.$mode.'] used to set nsKey='.$nsKey.', itemKey='.$itemKey); - } - } + /** + * Set a ByteStream into the cache under $itemKey for the namespace $nsKey. + * + * @see MODE_WRITE, MODE_APPEND + * + * @param string $nsKey + * @param string $itemKey + * @param int $mode + */ + public function importFromByteStream($nsKey, $itemKey, Swift_OutputByteStream $os, $mode) + { + $this->prepareCache($nsKey); + switch ($mode) { + case self::MODE_WRITE: + $this->clearKey($nsKey, $itemKey); + // no break + case self::MODE_APPEND: + if (!$this->hasKey($nsKey, $itemKey)) { + $this->contents[$nsKey][$itemKey] = ''; + } + while (false !== $bytes = $os->read(8192)) { + $this->contents[$nsKey][$itemKey] .= $bytes; + } + break; + default: + throw new Swift_SwiftException('Invalid mode ['.$mode.'] used to set nsKey='.$nsKey.', itemKey='.$itemKey); + } + } - /** - * Provides a ByteStream which when written to, writes data to $itemKey. - * - * NOTE: The stream will always write in append mode. - * - * @param string $nsKey - * @param string $itemKey - * - * @return Swift_InputByteStream - */ - public function getInputByteStream($nsKey, $itemKey, Swift_InputByteStream $writeThrough = null) - { - $is = clone $this->stream; - $is->setKeyCache($this); - $is->setNsKey($nsKey); - $is->setItemKey($itemKey); - if (isset($writeThrough)) { - $is->setWriteThroughStream($writeThrough); - } + /** + * Provides a ByteStream which when written to, writes data to $itemKey. + * + * NOTE: The stream will always write in append mode. + * + * @param string $nsKey + * @param string $itemKey + * + * @return Swift_InputByteStream + */ + public function getInputByteStream($nsKey, $itemKey, Swift_InputByteStream $writeThrough = null) + { + $is = clone $this->stream; + $is->setKeyCache($this); + $is->setNsKey($nsKey); + $is->setItemKey($itemKey); + if (isset($writeThrough)) { + $is->setWriteThroughStream($writeThrough); + } - return $is; - } + return $is; + } - /** - * Get data back out of the cache as a string. - * - * @param string $nsKey - * @param string $itemKey - * - * @return string - */ - public function getString($nsKey, $itemKey) - { - $this->prepareCache($nsKey); - if ($this->hasKey($nsKey, $itemKey)) { - return $this->contents[$nsKey][$itemKey]; - } - } + /** + * Get data back out of the cache as a string. + * + * @param string $nsKey + * @param string $itemKey + * + * @return string + */ + public function getString($nsKey, $itemKey) + { + $this->prepareCache($nsKey); + if ($this->hasKey($nsKey, $itemKey)) { + return $this->contents[$nsKey][$itemKey]; + } + } - /** - * Get data back out of the cache as a ByteStream. - * - * @param string $nsKey - * @param string $itemKey - * @param Swift_InputByteStream $is to write the data to - */ - public function exportToByteStream($nsKey, $itemKey, Swift_InputByteStream $is) - { - $this->prepareCache($nsKey); - $is->write($this->getString($nsKey, $itemKey)); - } + /** + * Get data back out of the cache as a ByteStream. + * + * @param string $nsKey + * @param string $itemKey + * @param Swift_InputByteStream $is to write the data to + */ + public function exportToByteStream($nsKey, $itemKey, Swift_InputByteStream $is) + { + $this->prepareCache($nsKey); + $is->write($this->getString($nsKey, $itemKey)); + } - /** - * Check if the given $itemKey exists in the namespace $nsKey. - * - * @param string $nsKey - * @param string $itemKey - * - * @return bool - */ - public function hasKey($nsKey, $itemKey) - { - $this->prepareCache($nsKey); + /** + * Check if the given $itemKey exists in the namespace $nsKey. + * + * @param string $nsKey + * @param string $itemKey + * + * @return bool + */ + public function hasKey($nsKey, $itemKey) + { + $this->prepareCache($nsKey); - return \array_key_exists($itemKey, $this->contents[$nsKey]); - } + return \array_key_exists($itemKey, $this->contents[$nsKey]); + } - /** - * Clear data for $itemKey in the namespace $nsKey if it exists. - * - * @param string $nsKey - * @param string $itemKey - */ - public function clearKey($nsKey, $itemKey) - { - unset($this->contents[$nsKey][$itemKey]); - } + /** + * Clear data for $itemKey in the namespace $nsKey if it exists. + * + * @param string $nsKey + * @param string $itemKey + */ + public function clearKey($nsKey, $itemKey) + { + unset($this->contents[$nsKey][$itemKey]); + } - /** - * Clear all data in the namespace $nsKey if it exists. - * - * @param string $nsKey - */ - public function clearAll($nsKey) - { - unset($this->contents[$nsKey]); - } + /** + * Clear all data in the namespace $nsKey if it exists. + * + * @param string $nsKey + */ + public function clearAll($nsKey) + { + unset($this->contents[$nsKey]); + } - /** - * Initialize the namespace of $nsKey if needed. - * - * @param string $nsKey - */ - private function prepareCache($nsKey) - { - if (!\array_key_exists($nsKey, $this->contents)) { - $this->contents[$nsKey] = []; - } - } + /** + * Initialize the namespace of $nsKey if needed. + * + * @param string $nsKey + */ + private function prepareCache($nsKey) + { + if (!\array_key_exists($nsKey, $this->contents)) { + $this->contents[$nsKey] = []; + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/DiskKeyCache.php b/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/DiskKeyCache.php index 33b6367cb8b..4075b928e13 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/DiskKeyCache.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/DiskKeyCache.php @@ -15,280 +15,280 @@ */ class Swift_KeyCache_DiskKeyCache implements Swift_KeyCache { - /** Signal to place pointer at start of file */ - const POSITION_START = 0; + /** Signal to place pointer at start of file */ + const POSITION_START = 0; - /** Signal to place pointer at end of file */ - const POSITION_END = 1; + /** Signal to place pointer at end of file */ + const POSITION_END = 1; - /** Signal to leave pointer in whatever position it currently is */ - const POSITION_CURRENT = 2; + /** Signal to leave pointer in whatever position it currently is */ + const POSITION_CURRENT = 2; - /** - * An InputStream for cloning. - * - * @var Swift_KeyCache_KeyCacheInputStream - */ - private $stream; + /** + * An InputStream for cloning. + * + * @var Swift_KeyCache_KeyCacheInputStream + */ + private $stream; - /** - * A path to write to. - * - * @var string - */ - private $path; + /** + * A path to write to. + * + * @var string + */ + private $path; - /** - * Stored keys. - * - * @var array - */ - private $keys = []; + /** + * Stored keys. + * + * @var array + */ + private $keys = []; - /** - * Create a new DiskKeyCache with the given $stream for cloning to make - * InputByteStreams, and the given $path to save to. - * - * @param string $path to save to - */ - public function __construct(Swift_KeyCache_KeyCacheInputStream $stream, $path) - { - $this->stream = $stream; - $this->path = $path; - } + /** + * Create a new DiskKeyCache with the given $stream for cloning to make + * InputByteStreams, and the given $path to save to. + * + * @param string $path to save to + */ + public function __construct(Swift_KeyCache_KeyCacheInputStream $stream, $path) + { + $this->stream = $stream; + $this->path = $path; + } - /** - * Set a string into the cache under $itemKey for the namespace $nsKey. - * - * @see MODE_WRITE, MODE_APPEND - * - * @param string $nsKey - * @param string $itemKey - * @param string $string - * @param int $mode - * - * @throws Swift_IoException - */ - public function setString($nsKey, $itemKey, $string, $mode) - { - $this->prepareCache($nsKey); - switch ($mode) { - case self::MODE_WRITE: - $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_START); - break; - case self::MODE_APPEND: - $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_END); - break; - default: - throw new Swift_SwiftException('Invalid mode ['.$mode.'] used to set nsKey='.$nsKey.', itemKey='.$itemKey); - break; - } - fwrite($fp, $string); - $this->freeHandle($nsKey, $itemKey); - } + /** + * Set a string into the cache under $itemKey for the namespace $nsKey. + * + * @see MODE_WRITE, MODE_APPEND + * + * @param string $nsKey + * @param string $itemKey + * @param string $string + * @param int $mode + * + * @throws Swift_IoException + */ + public function setString($nsKey, $itemKey, $string, $mode) + { + $this->prepareCache($nsKey); + switch ($mode) { + case self::MODE_WRITE: + $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_START); + break; + case self::MODE_APPEND: + $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_END); + break; + default: + throw new Swift_SwiftException('Invalid mode ['.$mode.'] used to set nsKey='.$nsKey.', itemKey='.$itemKey); + break; + } + fwrite($fp, $string); + $this->freeHandle($nsKey, $itemKey); + } - /** - * Set a ByteStream into the cache under $itemKey for the namespace $nsKey. - * - * @see MODE_WRITE, MODE_APPEND - * - * @param string $nsKey - * @param string $itemKey - * @param int $mode - * - * @throws Swift_IoException - */ - public function importFromByteStream($nsKey, $itemKey, Swift_OutputByteStream $os, $mode) - { - $this->prepareCache($nsKey); - switch ($mode) { - case self::MODE_WRITE: - $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_START); - break; - case self::MODE_APPEND: - $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_END); - break; - default: - throw new Swift_SwiftException('Invalid mode ['.$mode.'] used to set nsKey='.$nsKey.', itemKey='.$itemKey); - break; - } - while (false !== $bytes = $os->read(8192)) { - fwrite($fp, $bytes); - } - $this->freeHandle($nsKey, $itemKey); - } + /** + * Set a ByteStream into the cache under $itemKey for the namespace $nsKey. + * + * @see MODE_WRITE, MODE_APPEND + * + * @param string $nsKey + * @param string $itemKey + * @param int $mode + * + * @throws Swift_IoException + */ + public function importFromByteStream($nsKey, $itemKey, Swift_OutputByteStream $os, $mode) + { + $this->prepareCache($nsKey); + switch ($mode) { + case self::MODE_WRITE: + $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_START); + break; + case self::MODE_APPEND: + $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_END); + break; + default: + throw new Swift_SwiftException('Invalid mode ['.$mode.'] used to set nsKey='.$nsKey.', itemKey='.$itemKey); + break; + } + while (false !== $bytes = $os->read(8192)) { + fwrite($fp, $bytes); + } + $this->freeHandle($nsKey, $itemKey); + } - /** - * Provides a ByteStream which when written to, writes data to $itemKey. - * - * NOTE: The stream will always write in append mode. - * - * @param string $nsKey - * @param string $itemKey - * - * @return Swift_InputByteStream - */ - public function getInputByteStream($nsKey, $itemKey, Swift_InputByteStream $writeThrough = null) - { - $is = clone $this->stream; - $is->setKeyCache($this); - $is->setNsKey($nsKey); - $is->setItemKey($itemKey); - if (isset($writeThrough)) { - $is->setWriteThroughStream($writeThrough); - } + /** + * Provides a ByteStream which when written to, writes data to $itemKey. + * + * NOTE: The stream will always write in append mode. + * + * @param string $nsKey + * @param string $itemKey + * + * @return Swift_InputByteStream + */ + public function getInputByteStream($nsKey, $itemKey, Swift_InputByteStream $writeThrough = null) + { + $is = clone $this->stream; + $is->setKeyCache($this); + $is->setNsKey($nsKey); + $is->setItemKey($itemKey); + if (isset($writeThrough)) { + $is->setWriteThroughStream($writeThrough); + } - return $is; - } + return $is; + } - /** - * Get data back out of the cache as a string. - * - * @param string $nsKey - * @param string $itemKey - * - * @throws Swift_IoException - * - * @return string - */ - public function getString($nsKey, $itemKey) - { - $this->prepareCache($nsKey); - if ($this->hasKey($nsKey, $itemKey)) { - $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_START); - $str = ''; - while (!feof($fp) && false !== $bytes = fread($fp, 8192)) { - $str .= $bytes; - } - $this->freeHandle($nsKey, $itemKey); + /** + * Get data back out of the cache as a string. + * + * @param string $nsKey + * @param string $itemKey + * + * @throws Swift_IoException + * + * @return string + */ + public function getString($nsKey, $itemKey) + { + $this->prepareCache($nsKey); + if ($this->hasKey($nsKey, $itemKey)) { + $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_START); + $str = ''; + while (!feof($fp) && false !== $bytes = fread($fp, 8192)) { + $str .= $bytes; + } + $this->freeHandle($nsKey, $itemKey); - return $str; - } - } + return $str; + } + } - /** - * Get data back out of the cache as a ByteStream. - * - * @param string $nsKey - * @param string $itemKey - * @param Swift_InputByteStream $is to write the data to - */ - public function exportToByteStream($nsKey, $itemKey, Swift_InputByteStream $is) - { - if ($this->hasKey($nsKey, $itemKey)) { - $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_START); - while (!feof($fp) && false !== $bytes = fread($fp, 8192)) { - $is->write($bytes); - } - $this->freeHandle($nsKey, $itemKey); - } - } + /** + * Get data back out of the cache as a ByteStream. + * + * @param string $nsKey + * @param string $itemKey + * @param Swift_InputByteStream $is to write the data to + */ + public function exportToByteStream($nsKey, $itemKey, Swift_InputByteStream $is) + { + if ($this->hasKey($nsKey, $itemKey)) { + $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_START); + while (!feof($fp) && false !== $bytes = fread($fp, 8192)) { + $is->write($bytes); + } + $this->freeHandle($nsKey, $itemKey); + } + } - /** - * Check if the given $itemKey exists in the namespace $nsKey. - * - * @param string $nsKey - * @param string $itemKey - * - * @return bool - */ - public function hasKey($nsKey, $itemKey) - { - return is_file($this->path.'/'.$nsKey.'/'.$itemKey); - } + /** + * Check if the given $itemKey exists in the namespace $nsKey. + * + * @param string $nsKey + * @param string $itemKey + * + * @return bool + */ + public function hasKey($nsKey, $itemKey) + { + return is_file($this->path.'/'.$nsKey.'/'.$itemKey); + } - /** - * Clear data for $itemKey in the namespace $nsKey if it exists. - * - * @param string $nsKey - * @param string $itemKey - */ - public function clearKey($nsKey, $itemKey) - { - if ($this->hasKey($nsKey, $itemKey)) { - $this->freeHandle($nsKey, $itemKey); - unlink($this->path.'/'.$nsKey.'/'.$itemKey); - } - } + /** + * Clear data for $itemKey in the namespace $nsKey if it exists. + * + * @param string $nsKey + * @param string $itemKey + */ + public function clearKey($nsKey, $itemKey) + { + if ($this->hasKey($nsKey, $itemKey)) { + $this->freeHandle($nsKey, $itemKey); + unlink($this->path.'/'.$nsKey.'/'.$itemKey); + } + } - /** - * Clear all data in the namespace $nsKey if it exists. - * - * @param string $nsKey - */ - public function clearAll($nsKey) - { - if (\array_key_exists($nsKey, $this->keys)) { - foreach ($this->keys[$nsKey] as $itemKey => $null) { - $this->clearKey($nsKey, $itemKey); - } - if (is_dir($this->path.'/'.$nsKey)) { - rmdir($this->path.'/'.$nsKey); - } - unset($this->keys[$nsKey]); - } - } + /** + * Clear all data in the namespace $nsKey if it exists. + * + * @param string $nsKey + */ + public function clearAll($nsKey) + { + if (\array_key_exists($nsKey, $this->keys)) { + foreach ($this->keys[$nsKey] as $itemKey => $null) { + $this->clearKey($nsKey, $itemKey); + } + if (is_dir($this->path.'/'.$nsKey)) { + rmdir($this->path.'/'.$nsKey); + } + unset($this->keys[$nsKey]); + } + } - /** - * Initialize the namespace of $nsKey if needed. - * - * @param string $nsKey - */ - private function prepareCache($nsKey) - { - $cacheDir = $this->path.'/'.$nsKey; - if (!is_dir($cacheDir)) { - if (!mkdir($cacheDir)) { - throw new Swift_IoException('Failed to create cache directory '.$cacheDir); - } - $this->keys[$nsKey] = []; - } - } + /** + * Initialize the namespace of $nsKey if needed. + * + * @param string $nsKey + */ + private function prepareCache($nsKey) + { + $cacheDir = $this->path.'/'.$nsKey; + if (!is_dir($cacheDir)) { + if (!mkdir($cacheDir)) { + throw new Swift_IoException('Failed to create cache directory '.$cacheDir); + } + $this->keys[$nsKey] = []; + } + } - /** - * Get a file handle on the cache item. - * - * @param string $nsKey - * @param string $itemKey - * @param int $position - * - * @return resource - */ - private function getHandle($nsKey, $itemKey, $position) - { - if (!isset($this->keys[$nsKey][$itemKey])) { - $openMode = $this->hasKey($nsKey, $itemKey) ? 'r+b' : 'w+b'; - $fp = fopen($this->path.'/'.$nsKey.'/'.$itemKey, $openMode); - $this->keys[$nsKey][$itemKey] = $fp; - } - if (self::POSITION_START == $position) { - fseek($this->keys[$nsKey][$itemKey], 0, SEEK_SET); - } elseif (self::POSITION_END == $position) { - fseek($this->keys[$nsKey][$itemKey], 0, SEEK_END); - } + /** + * Get a file handle on the cache item. + * + * @param string $nsKey + * @param string $itemKey + * @param int $position + * + * @return resource + */ + private function getHandle($nsKey, $itemKey, $position) + { + if (!isset($this->keys[$nsKey][$itemKey])) { + $openMode = $this->hasKey($nsKey, $itemKey) ? 'r+b' : 'w+b'; + $fp = fopen($this->path.'/'.$nsKey.'/'.$itemKey, $openMode); + $this->keys[$nsKey][$itemKey] = $fp; + } + if (self::POSITION_START == $position) { + fseek($this->keys[$nsKey][$itemKey], 0, SEEK_SET); + } elseif (self::POSITION_END == $position) { + fseek($this->keys[$nsKey][$itemKey], 0, SEEK_END); + } - return $this->keys[$nsKey][$itemKey]; - } + return $this->keys[$nsKey][$itemKey]; + } - private function freeHandle($nsKey, $itemKey) - { - $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_CURRENT); - fclose($fp); - $this->keys[$nsKey][$itemKey] = null; - } + private function freeHandle($nsKey, $itemKey) + { + $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_CURRENT); + fclose($fp); + $this->keys[$nsKey][$itemKey] = null; + } - /** - * Destructor. - */ - public function __destruct() - { - foreach ($this->keys as $nsKey => $null) { - $this->clearAll($nsKey); - } - } + /** + * Destructor. + */ + public function __destruct() + { + foreach ($this->keys as $nsKey => $null) { + $this->clearAll($nsKey); + } + } - public function __wakeup() - { - $this->keys = []; - } + public function __wakeup() + { + $this->keys = []; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/KeyCacheInputStream.php b/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/KeyCacheInputStream.php index be2dbba0c58..159f97643cd 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/KeyCacheInputStream.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/KeyCacheInputStream.php @@ -15,33 +15,33 @@ */ interface Swift_KeyCache_KeyCacheInputStream extends Swift_InputByteStream { - /** - * Set the KeyCache to wrap. - */ - public function setKeyCache(Swift_KeyCache $keyCache); + /** + * Set the KeyCache to wrap. + */ + public function setKeyCache(Swift_KeyCache $keyCache); - /** - * Set the nsKey which will be written to. - * - * @param string $nsKey - */ - public function setNsKey($nsKey); + /** + * Set the nsKey which will be written to. + * + * @param string $nsKey + */ + public function setNsKey($nsKey); - /** - * Set the itemKey which will be written to. - * - * @param string $itemKey - */ - public function setItemKey($itemKey); + /** + * Set the itemKey which will be written to. + * + * @param string $itemKey + */ + public function setItemKey($itemKey); - /** - * Specify a stream to write through for each write(). - */ - public function setWriteThroughStream(Swift_InputByteStream $is); + /** + * Specify a stream to write through for each write(). + */ + public function setWriteThroughStream(Swift_InputByteStream $is); - /** - * Any implementation should be cloneable, allowing the clone to access a - * separate $nsKey and $itemKey. - */ - public function __clone(); + /** + * Any implementation should be cloneable, allowing the clone to access a + * separate $nsKey and $itemKey. + */ + public function __clone(); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/NullKeyCache.php b/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/NullKeyCache.php index 957b1b2a000..2b04d77fe4f 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/NullKeyCache.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/NullKeyCache.php @@ -15,99 +15,99 @@ */ class Swift_KeyCache_NullKeyCache implements Swift_KeyCache { - /** - * Set a string into the cache under $itemKey for the namespace $nsKey. - * - * @see MODE_WRITE, MODE_APPEND - * - * @param string $nsKey - * @param string $itemKey - * @param string $string - * @param int $mode - */ - public function setString($nsKey, $itemKey, $string, $mode) - { - } + /** + * Set a string into the cache under $itemKey for the namespace $nsKey. + * + * @see MODE_WRITE, MODE_APPEND + * + * @param string $nsKey + * @param string $itemKey + * @param string $string + * @param int $mode + */ + public function setString($nsKey, $itemKey, $string, $mode) + { + } - /** - * Set a ByteStream into the cache under $itemKey for the namespace $nsKey. - * - * @see MODE_WRITE, MODE_APPEND - * - * @param string $nsKey - * @param string $itemKey - * @param int $mode - */ - public function importFromByteStream($nsKey, $itemKey, Swift_OutputByteStream $os, $mode) - { - } + /** + * Set a ByteStream into the cache under $itemKey for the namespace $nsKey. + * + * @see MODE_WRITE, MODE_APPEND + * + * @param string $nsKey + * @param string $itemKey + * @param int $mode + */ + public function importFromByteStream($nsKey, $itemKey, Swift_OutputByteStream $os, $mode) + { + } - /** - * Provides a ByteStream which when written to, writes data to $itemKey. - * - * NOTE: The stream will always write in append mode. - * - * @param string $nsKey - * @param string $itemKey - * - * @return Swift_InputByteStream - */ - public function getInputByteStream($nsKey, $itemKey, Swift_InputByteStream $writeThrough = null) - { - } + /** + * Provides a ByteStream which when written to, writes data to $itemKey. + * + * NOTE: The stream will always write in append mode. + * + * @param string $nsKey + * @param string $itemKey + * + * @return Swift_InputByteStream + */ + public function getInputByteStream($nsKey, $itemKey, Swift_InputByteStream $writeThrough = null) + { + } - /** - * Get data back out of the cache as a string. - * - * @param string $nsKey - * @param string $itemKey - * - * @return string - */ - public function getString($nsKey, $itemKey) - { - } + /** + * Get data back out of the cache as a string. + * + * @param string $nsKey + * @param string $itemKey + * + * @return string + */ + public function getString($nsKey, $itemKey) + { + } - /** - * Get data back out of the cache as a ByteStream. - * - * @param string $nsKey - * @param string $itemKey - * @param Swift_InputByteStream $is to write the data to - */ - public function exportToByteStream($nsKey, $itemKey, Swift_InputByteStream $is) - { - } + /** + * Get data back out of the cache as a ByteStream. + * + * @param string $nsKey + * @param string $itemKey + * @param Swift_InputByteStream $is to write the data to + */ + public function exportToByteStream($nsKey, $itemKey, Swift_InputByteStream $is) + { + } - /** - * Check if the given $itemKey exists in the namespace $nsKey. - * - * @param string $nsKey - * @param string $itemKey - * - * @return bool - */ - public function hasKey($nsKey, $itemKey) - { - return false; - } + /** + * Check if the given $itemKey exists in the namespace $nsKey. + * + * @param string $nsKey + * @param string $itemKey + * + * @return bool + */ + public function hasKey($nsKey, $itemKey) + { + return false; + } - /** - * Clear data for $itemKey in the namespace $nsKey if it exists. - * - * @param string $nsKey - * @param string $itemKey - */ - public function clearKey($nsKey, $itemKey) - { - } + /** + * Clear data for $itemKey in the namespace $nsKey if it exists. + * + * @param string $nsKey + * @param string $itemKey + */ + public function clearKey($nsKey, $itemKey) + { + } - /** - * Clear all data in the namespace $nsKey if it exists. - * - * @param string $nsKey - */ - public function clearAll($nsKey) - { - } + /** + * Clear all data in the namespace $nsKey if it exists. + * + * @param string $nsKey + */ + public function clearAll($nsKey) + { + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/SimpleKeyCacheInputStream.php b/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/SimpleKeyCacheInputStream.php index 03bab481ea3..d9d75e078c7 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/SimpleKeyCacheInputStream.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/SimpleKeyCacheInputStream.php @@ -15,109 +15,109 @@ */ class Swift_KeyCache_SimpleKeyCacheInputStream implements Swift_KeyCache_KeyCacheInputStream { - /** The KeyCache being written to */ - private $keyCache; + /** The KeyCache being written to */ + private $keyCache; - /** The nsKey of the KeyCache being written to */ - private $nsKey; + /** The nsKey of the KeyCache being written to */ + private $nsKey; - /** The itemKey of the KeyCache being written to */ - private $itemKey; + /** The itemKey of the KeyCache being written to */ + private $itemKey; - /** A stream to write through on each write() */ - private $writeThrough = null; + /** A stream to write through on each write() */ + private $writeThrough = null; - /** - * Set the KeyCache to wrap. - */ - public function setKeyCache(Swift_KeyCache $keyCache) - { - $this->keyCache = $keyCache; - } + /** + * Set the KeyCache to wrap. + */ + public function setKeyCache(Swift_KeyCache $keyCache) + { + $this->keyCache = $keyCache; + } - /** - * Specify a stream to write through for each write(). - */ - public function setWriteThroughStream(Swift_InputByteStream $is) - { - $this->writeThrough = $is; - } + /** + * Specify a stream to write through for each write(). + */ + public function setWriteThroughStream(Swift_InputByteStream $is) + { + $this->writeThrough = $is; + } - /** - * Writes $bytes to the end of the stream. - * - * @param string $bytes - * @param Swift_InputByteStream $is optional - */ - public function write($bytes, Swift_InputByteStream $is = null) - { - $this->keyCache->setString( - $this->nsKey, $this->itemKey, $bytes, Swift_KeyCache::MODE_APPEND - ); - if (isset($is)) { - $is->write($bytes); - } - if (isset($this->writeThrough)) { - $this->writeThrough->write($bytes); - } - } + /** + * Writes $bytes to the end of the stream. + * + * @param string $bytes + * @param Swift_InputByteStream $is optional + */ + public function write($bytes, Swift_InputByteStream $is = null) + { + $this->keyCache->setString( + $this->nsKey, $this->itemKey, $bytes, Swift_KeyCache::MODE_APPEND + ); + if (isset($is)) { + $is->write($bytes); + } + if (isset($this->writeThrough)) { + $this->writeThrough->write($bytes); + } + } - /** - * Not used. - */ - public function commit() - { - } + /** + * Not used. + */ + public function commit() + { + } - /** - * Not used. - */ - public function bind(Swift_InputByteStream $is) - { - } + /** + * Not used. + */ + public function bind(Swift_InputByteStream $is) + { + } - /** - * Not used. - */ - public function unbind(Swift_InputByteStream $is) - { - } + /** + * Not used. + */ + public function unbind(Swift_InputByteStream $is) + { + } - /** - * Flush the contents of the stream (empty it) and set the internal pointer - * to the beginning. - */ - public function flushBuffers() - { - $this->keyCache->clearKey($this->nsKey, $this->itemKey); - } + /** + * Flush the contents of the stream (empty it) and set the internal pointer + * to the beginning. + */ + public function flushBuffers() + { + $this->keyCache->clearKey($this->nsKey, $this->itemKey); + } - /** - * Set the nsKey which will be written to. - * - * @param string $nsKey - */ - public function setNsKey($nsKey) - { - $this->nsKey = $nsKey; - } + /** + * Set the nsKey which will be written to. + * + * @param string $nsKey + */ + public function setNsKey($nsKey) + { + $this->nsKey = $nsKey; + } - /** - * Set the itemKey which will be written to. - * - * @param string $itemKey - */ - public function setItemKey($itemKey) - { - $this->itemKey = $itemKey; - } + /** + * Set the itemKey which will be written to. + * + * @param string $itemKey + */ + public function setItemKey($itemKey) + { + $this->itemKey = $itemKey; + } - /** - * Any implementation should be cloneable, allowing the clone to access a - * separate $nsKey and $itemKey. - */ - public function __clone() - { - $this->writeThrough = null; - } + /** + * Any implementation should be cloneable, allowing the clone to access a + * separate $nsKey and $itemKey. + */ + public function __clone() + { + $this->writeThrough = null; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/LoadBalancedTransport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/LoadBalancedTransport.php index 244b5f60245..3373f67964e 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/LoadBalancedTransport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/LoadBalancedTransport.php @@ -15,19 +15,19 @@ */ class Swift_LoadBalancedTransport extends Swift_Transport_LoadBalancedTransport { - /** - * Creates a new LoadBalancedTransport with $transports. - * - * @param array $transports - */ - public function __construct($transports = []) - { - \call_user_func_array( - [$this, 'Swift_Transport_LoadBalancedTransport::__construct'], - Swift_DependencyContainer::getInstance() - ->createDependenciesFor('transport.loadbalanced') - ); + /** + * Creates a new LoadBalancedTransport with $transports. + * + * @param array $transports + */ + public function __construct($transports = []) + { + \call_user_func_array( + [$this, 'Swift_Transport_LoadBalancedTransport::__construct'], + Swift_DependencyContainer::getInstance() + ->createDependenciesFor('transport.loadbalanced') + ); - $this->setTransports($transports); - } + $this->setTransports($transports); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mailer.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mailer.php index 57630074cd9..ef9d66365bb 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mailer.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mailer.php @@ -15,84 +15,84 @@ */ class Swift_Mailer { - /** The Transport used to send messages */ - private $transport; + /** The Transport used to send messages */ + private $transport; - /** - * Create a new Mailer using $transport for delivery. - */ - public function __construct(Swift_Transport $transport) - { - $this->transport = $transport; - } + /** + * Create a new Mailer using $transport for delivery. + */ + public function __construct(Swift_Transport $transport) + { + $this->transport = $transport; + } - /** - * Create a new class instance of one of the message services. - * - * For example 'mimepart' would create a 'message.mimepart' instance - * - * @param string $service - * - * @return object - */ - public function createMessage($service = 'message') - { - return Swift_DependencyContainer::getInstance() - ->lookup('message.'.$service); - } + /** + * Create a new class instance of one of the message services. + * + * For example 'mimepart' would create a 'message.mimepart' instance + * + * @param string $service + * + * @return object + */ + public function createMessage($service = 'message') + { + return Swift_DependencyContainer::getInstance() + ->lookup('message.'.$service); + } - /** - * Send the given Message like it would be sent in a mail client. - * - * All recipients (with the exception of Bcc) will be able to see the other - * recipients this message was sent to. - * - * Recipient/sender data will be retrieved from the Message object. - * - * The return value is the number of recipients who were accepted for - * delivery. - * - * @param array $failedRecipients An array of failures by-reference - * - * @return int The number of successful recipients. Can be 0 which indicates failure - */ - public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) - { - $failedRecipients = (array) $failedRecipients; + /** + * Send the given Message like it would be sent in a mail client. + * + * All recipients (with the exception of Bcc) will be able to see the other + * recipients this message was sent to. + * + * Recipient/sender data will be retrieved from the Message object. + * + * The return value is the number of recipients who were accepted for + * delivery. + * + * @param array $failedRecipients An array of failures by-reference + * + * @return int The number of successful recipients. Can be 0 which indicates failure + */ + public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) + { + $failedRecipients = (array) $failedRecipients; - // FIXME: to be removed in 7.0 (as transport must now start itself on send) - if (!$this->transport->isStarted()) { - $this->transport->start(); - } + // FIXME: to be removed in 7.0 (as transport must now start itself on send) + if (!$this->transport->isStarted()) { + $this->transport->start(); + } - $sent = 0; + $sent = 0; - try { - $sent = $this->transport->send($message, $failedRecipients); - } catch (Swift_RfcComplianceException $e) { - foreach ($message->getTo() as $address => $name) { - $failedRecipients[] = $address; - } - } + try { + $sent = $this->transport->send($message, $failedRecipients); + } catch (Swift_RfcComplianceException $e) { + foreach ($message->getTo() as $address => $name) { + $failedRecipients[] = $address; + } + } - return $sent; - } + return $sent; + } - /** - * Register a plugin using a known unique key (e.g. myPlugin). - */ - public function registerPlugin(Swift_Events_EventListener $plugin) - { - $this->transport->registerPlugin($plugin); - } + /** + * Register a plugin using a known unique key (e.g. myPlugin). + */ + public function registerPlugin(Swift_Events_EventListener $plugin) + { + $this->transport->registerPlugin($plugin); + } - /** - * The Transport used to send messages. - * - * @return Swift_Transport - */ - public function getTransport() - { - return $this->transport; - } + /** + * The Transport used to send messages. + * + * @return Swift_Transport + */ + public function getTransport() + { + return $this->transport; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mailer/ArrayRecipientIterator.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mailer/ArrayRecipientIterator.php index 19aa82a9c40..6ee0b1571a4 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mailer/ArrayRecipientIterator.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mailer/ArrayRecipientIterator.php @@ -15,39 +15,39 @@ */ class Swift_Mailer_ArrayRecipientIterator implements Swift_Mailer_RecipientIterator { - /** - * The list of recipients. - * - * @var array - */ - private $recipients = []; + /** + * The list of recipients. + * + * @var array + */ + private $recipients = []; - /** - * Create a new ArrayRecipientIterator from $recipients. - */ - public function __construct(array $recipients) - { - $this->recipients = $recipients; - } + /** + * Create a new ArrayRecipientIterator from $recipients. + */ + public function __construct(array $recipients) + { + $this->recipients = $recipients; + } - /** - * Returns true only if there are more recipients to send to. - * - * @return bool - */ - public function hasNext() - { - return !empty($this->recipients); - } + /** + * Returns true only if there are more recipients to send to. + * + * @return bool + */ + public function hasNext() + { + return !empty($this->recipients); + } - /** - * Returns an array where the keys are the addresses of recipients and the - * values are the names. e.g. ('foo@bar' => 'Foo') or ('foo@bar' => NULL). - * - * @return array - */ - public function nextRecipient() - { - return array_splice($this->recipients, 0, 1); - } + /** + * Returns an array where the keys are the addresses of recipients and the + * values are the names. e.g. ('foo@bar' => 'Foo') or ('foo@bar' => NULL). + * + * @return array + */ + public function nextRecipient() + { + return array_splice($this->recipients, 0, 1); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/MemorySpool.php b/htdocs/includes/swiftmailer/lib/classes/Swift/MemorySpool.php index e3b0894d87a..af430351eba 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/MemorySpool.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/MemorySpool.php @@ -15,96 +15,96 @@ */ class Swift_MemorySpool implements Swift_Spool { - protected $messages = []; - private $flushRetries = 3; + protected $messages = []; + private $flushRetries = 3; - /** - * Tests if this Transport mechanism has started. - * - * @return bool - */ - public function isStarted() - { - return true; - } + /** + * Tests if this Transport mechanism has started. + * + * @return bool + */ + public function isStarted() + { + return true; + } - /** - * Starts this Transport mechanism. - */ - public function start() - { - } + /** + * Starts this Transport mechanism. + */ + public function start() + { + } - /** - * Stops this Transport mechanism. - */ - public function stop() - { - } + /** + * Stops this Transport mechanism. + */ + public function stop() + { + } - /** - * @param int $retries - */ - public function setFlushRetries($retries) - { - $this->flushRetries = $retries; - } + /** + * @param int $retries + */ + public function setFlushRetries($retries) + { + $this->flushRetries = $retries; + } - /** - * Stores a message in the queue. - * - * @param Swift_Mime_SimpleMessage $message The message to store - * - * @return bool Whether the operation has succeeded - */ - public function queueMessage(Swift_Mime_SimpleMessage $message) - { - //clone the message to make sure it is not changed while in the queue - $this->messages[] = clone $message; + /** + * Stores a message in the queue. + * + * @param Swift_Mime_SimpleMessage $message The message to store + * + * @return bool Whether the operation has succeeded + */ + public function queueMessage(Swift_Mime_SimpleMessage $message) + { + //clone the message to make sure it is not changed while in the queue + $this->messages[] = clone $message; - return true; - } + return true; + } - /** - * Sends messages using the given transport instance. - * - * @param Swift_Transport $transport A transport instance - * @param string[] $failedRecipients An array of failures by-reference - * - * @return int The number of sent emails - */ - public function flushQueue(Swift_Transport $transport, &$failedRecipients = null) - { - if (!$this->messages) { - return 0; - } + /** + * Sends messages using the given transport instance. + * + * @param Swift_Transport $transport A transport instance + * @param string[] $failedRecipients An array of failures by-reference + * + * @return int The number of sent emails + */ + public function flushQueue(Swift_Transport $transport, &$failedRecipients = null) + { + if (!$this->messages) { + return 0; + } - if (!$transport->isStarted()) { - $transport->start(); - } + if (!$transport->isStarted()) { + $transport->start(); + } - $count = 0; - $retries = $this->flushRetries; - while ($retries--) { - try { - while ($message = array_pop($this->messages)) { - $count += $transport->send($message, $failedRecipients); - } - } catch (Swift_TransportException $exception) { - if ($retries) { - // re-queue the message at the end of the queue to give a chance - // to the other messages to be sent, in case the failure was due to - // this message and not just the transport failing - array_unshift($this->messages, $message); + $count = 0; + $retries = $this->flushRetries; + while ($retries--) { + try { + while ($message = array_pop($this->messages)) { + $count += $transport->send($message, $failedRecipients); + } + } catch (Swift_TransportException $exception) { + if ($retries) { + // re-queue the message at the end of the queue to give a chance + // to the other messages to be sent, in case the failure was due to + // this message and not just the transport failing + array_unshift($this->messages, $message); - // wait half a second before we try again - usleep(500000); - } else { - throw $exception; - } - } - } + // wait half a second before we try again + usleep(500000); + } else { + throw $exception; + } + } + } - return $count; - } + return $count; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Message.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Message.php index 5c5834e23d8..103563c620c 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Message.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Message.php @@ -15,265 +15,265 @@ */ class Swift_Message extends Swift_Mime_SimpleMessage { - /** - * @var Swift_Signers_HeaderSigner[] - */ - private $headerSigners = []; + /** + * @var Swift_Signers_HeaderSigner[] + */ + private $headerSigners = []; - /** - * @var Swift_Signers_BodySigner[] - */ - private $bodySigners = []; + /** + * @var Swift_Signers_BodySigner[] + */ + private $bodySigners = []; - /** - * @var array - */ - private $savedMessage = []; + /** + * @var array + */ + private $savedMessage = []; - /** - * Create a new Message. - * - * Details may be optionally passed into the constructor. - * - * @param string $subject - * @param string $body - * @param string $contentType - * @param string $charset - */ - public function __construct($subject = null, $body = null, $contentType = null, $charset = null) - { - \call_user_func_array( - [$this, 'Swift_Mime_SimpleMessage::__construct'], - Swift_DependencyContainer::getInstance() - ->createDependenciesFor('mime.message') - ); + /** + * Create a new Message. + * + * Details may be optionally passed into the constructor. + * + * @param string $subject + * @param string $body + * @param string $contentType + * @param string $charset + */ + public function __construct($subject = null, $body = null, $contentType = null, $charset = null) + { + \call_user_func_array( + [$this, 'Swift_Mime_SimpleMessage::__construct'], + Swift_DependencyContainer::getInstance() + ->createDependenciesFor('mime.message') + ); - if (!isset($charset)) { - $charset = Swift_DependencyContainer::getInstance() - ->lookup('properties.charset'); - } - $this->setSubject($subject); - $this->setBody($body); - $this->setCharset($charset); - if ($contentType) { - $this->setContentType($contentType); - } - } + if (!isset($charset)) { + $charset = Swift_DependencyContainer::getInstance() + ->lookup('properties.charset'); + } + $this->setSubject($subject); + $this->setBody($body); + $this->setCharset($charset); + if ($contentType) { + $this->setContentType($contentType); + } + } - /** - * Add a MimePart to this Message. - * - * @param string|Swift_OutputByteStream $body - * @param string $contentType - * @param string $charset - * - * @return $this - */ - public function addPart($body, $contentType = null, $charset = null) - { - return $this->attach((new Swift_MimePart($body, $contentType, $charset))->setEncoder($this->getEncoder())); - } + /** + * Add a MimePart to this Message. + * + * @param string|Swift_OutputByteStream $body + * @param string $contentType + * @param string $charset + * + * @return $this + */ + public function addPart($body, $contentType = null, $charset = null) + { + return $this->attach((new Swift_MimePart($body, $contentType, $charset))->setEncoder($this->getEncoder())); + } - /** - * Attach a new signature handler to the message. - * - * @return $this - */ - public function attachSigner(Swift_Signer $signer) - { - if ($signer instanceof Swift_Signers_HeaderSigner) { - $this->headerSigners[] = $signer; - } elseif ($signer instanceof Swift_Signers_BodySigner) { - $this->bodySigners[] = $signer; - } + /** + * Attach a new signature handler to the message. + * + * @return $this + */ + public function attachSigner(Swift_Signer $signer) + { + if ($signer instanceof Swift_Signers_HeaderSigner) { + $this->headerSigners[] = $signer; + } elseif ($signer instanceof Swift_Signers_BodySigner) { + $this->bodySigners[] = $signer; + } - return $this; - } + return $this; + } - /** - * Detach a signature handler from a message. - * - * @return $this - */ - public function detachSigner(Swift_Signer $signer) - { - if ($signer instanceof Swift_Signers_HeaderSigner) { - foreach ($this->headerSigners as $k => $headerSigner) { - if ($headerSigner === $signer) { - unset($this->headerSigners[$k]); + /** + * Detach a signature handler from a message. + * + * @return $this + */ + public function detachSigner(Swift_Signer $signer) + { + if ($signer instanceof Swift_Signers_HeaderSigner) { + foreach ($this->headerSigners as $k => $headerSigner) { + if ($headerSigner === $signer) { + unset($this->headerSigners[$k]); - return $this; - } - } - } elseif ($signer instanceof Swift_Signers_BodySigner) { - foreach ($this->bodySigners as $k => $bodySigner) { - if ($bodySigner === $signer) { - unset($this->bodySigners[$k]); + return $this; + } + } + } elseif ($signer instanceof Swift_Signers_BodySigner) { + foreach ($this->bodySigners as $k => $bodySigner) { + if ($bodySigner === $signer) { + unset($this->bodySigners[$k]); - return $this; - } - } - } + return $this; + } + } + } - return $this; - } + return $this; + } - /** - * Clear all signature handlers attached to the message. - * - * @return $this - */ - public function clearSigners() - { - $this->headerSigners = []; - $this->bodySigners = []; + /** + * Clear all signature handlers attached to the message. + * + * @return $this + */ + public function clearSigners() + { + $this->headerSigners = []; + $this->bodySigners = []; - return $this; - } + return $this; + } - /** - * Get this message as a complete string. - * - * @return string - */ - public function toString() - { - if (empty($this->headerSigners) && empty($this->bodySigners)) { - return parent::toString(); - } + /** + * Get this message as a complete string. + * + * @return string + */ + public function toString() + { + if (empty($this->headerSigners) && empty($this->bodySigners)) { + return parent::toString(); + } - $this->saveMessage(); + $this->saveMessage(); - $this->doSign(); + $this->doSign(); - $string = parent::toString(); + $string = parent::toString(); - $this->restoreMessage(); + $this->restoreMessage(); - return $string; - } + return $string; + } - /** - * Write this message to a {@link Swift_InputByteStream}. - */ - public function toByteStream(Swift_InputByteStream $is) - { - if (empty($this->headerSigners) && empty($this->bodySigners)) { - parent::toByteStream($is); + /** + * Write this message to a {@link Swift_InputByteStream}. + */ + public function toByteStream(Swift_InputByteStream $is) + { + if (empty($this->headerSigners) && empty($this->bodySigners)) { + parent::toByteStream($is); - return; - } + return; + } - $this->saveMessage(); + $this->saveMessage(); - $this->doSign(); + $this->doSign(); - parent::toByteStream($is); + parent::toByteStream($is); - $this->restoreMessage(); - } + $this->restoreMessage(); + } - public function __wakeup() - { - Swift_DependencyContainer::getInstance()->createDependenciesFor('mime.message'); - } + public function __wakeup() + { + Swift_DependencyContainer::getInstance()->createDependenciesFor('mime.message'); + } - /** - * loops through signers and apply the signatures. - */ - protected function doSign() - { - foreach ($this->bodySigners as $signer) { - $altered = $signer->getAlteredHeaders(); - $this->saveHeaders($altered); - $signer->signMessage($this); - } + /** + * loops through signers and apply the signatures. + */ + protected function doSign() + { + foreach ($this->bodySigners as $signer) { + $altered = $signer->getAlteredHeaders(); + $this->saveHeaders($altered); + $signer->signMessage($this); + } - foreach ($this->headerSigners as $signer) { - $altered = $signer->getAlteredHeaders(); - $this->saveHeaders($altered); - $signer->reset(); + foreach ($this->headerSigners as $signer) { + $altered = $signer->getAlteredHeaders(); + $this->saveHeaders($altered); + $signer->reset(); - $signer->setHeaders($this->getHeaders()); + $signer->setHeaders($this->getHeaders()); - $signer->startBody(); - $this->bodyToByteStream($signer); - $signer->endBody(); + $signer->startBody(); + $this->bodyToByteStream($signer); + $signer->endBody(); - $signer->addSignature($this->getHeaders()); - } - } + $signer->addSignature($this->getHeaders()); + } + } - /** - * save the message before any signature is applied. - */ - protected function saveMessage() - { - $this->savedMessage = ['headers' => []]; - $this->savedMessage['body'] = $this->getBody(); - $this->savedMessage['children'] = $this->getChildren(); - if (\count($this->savedMessage['children']) > 0 && '' != $this->getBody()) { - $this->setChildren(array_merge([$this->becomeMimePart()], $this->savedMessage['children'])); - $this->setBody(''); - } - } + /** + * save the message before any signature is applied. + */ + protected function saveMessage() + { + $this->savedMessage = ['headers' => []]; + $this->savedMessage['body'] = $this->getBody(); + $this->savedMessage['children'] = $this->getChildren(); + if (\count($this->savedMessage['children']) > 0 && '' != $this->getBody()) { + $this->setChildren(array_merge([$this->becomeMimePart()], $this->savedMessage['children'])); + $this->setBody(''); + } + } - /** - * save the original headers. - */ - protected function saveHeaders(array $altered) - { - foreach ($altered as $head) { - $lc = strtolower($head ?? ''); + /** + * save the original headers. + */ + protected function saveHeaders(array $altered) + { + foreach ($altered as $head) { + $lc = strtolower($head ?? ''); - if (!isset($this->savedMessage['headers'][$lc])) { - $this->savedMessage['headers'][$lc] = $this->getHeaders()->getAll($head); - } - } - } + if (!isset($this->savedMessage['headers'][$lc])) { + $this->savedMessage['headers'][$lc] = $this->getHeaders()->getAll($head); + } + } + } - /** - * Remove or restore altered headers. - */ - protected function restoreHeaders() - { - foreach ($this->savedMessage['headers'] as $name => $savedValue) { - $headers = $this->getHeaders()->getAll($name); + /** + * Remove or restore altered headers. + */ + protected function restoreHeaders() + { + foreach ($this->savedMessage['headers'] as $name => $savedValue) { + $headers = $this->getHeaders()->getAll($name); - foreach ($headers as $key => $value) { - if (!isset($savedValue[$key])) { - $this->getHeaders()->remove($name, $key); - } - } - } - } + foreach ($headers as $key => $value) { + if (!isset($savedValue[$key])) { + $this->getHeaders()->remove($name, $key); + } + } + } + } - /** - * Restore message body. - */ - protected function restoreMessage() - { - $this->setBody($this->savedMessage['body']); - $this->setChildren($this->savedMessage['children']); + /** + * Restore message body. + */ + protected function restoreMessage() + { + $this->setBody($this->savedMessage['body']); + $this->setChildren($this->savedMessage['children']); - $this->restoreHeaders(); - $this->savedMessage = []; - } + $this->restoreHeaders(); + $this->savedMessage = []; + } - /** - * Clone Message Signers. - * - * @see Swift_Mime_SimpleMimeEntity::__clone() - */ - public function __clone() - { - parent::__clone(); - foreach ($this->bodySigners as $key => $bodySigner) { - $this->bodySigners[$key] = clone $bodySigner; - } + /** + * Clone Message Signers. + * + * @see Swift_Mime_SimpleMimeEntity::__clone() + */ + public function __clone() + { + parent::__clone(); + foreach ($this->bodySigners as $key => $bodySigner) { + $this->bodySigners[$key] = clone $bodySigner; + } - foreach ($this->headerSigners as $key => $headerSigner) { - $this->headerSigners[$key] = clone $headerSigner; - } - } + foreach ($this->headerSigners as $key => $headerSigner) { + $this->headerSigners[$key] = clone $headerSigner; + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Attachment.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Attachment.php index d994373bd78..ed9b7cbe50c 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Attachment.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Attachment.php @@ -15,130 +15,130 @@ */ class Swift_Mime_Attachment extends Swift_Mime_SimpleMimeEntity { - /** Recognized MIME types */ - private $mimeTypes = []; + /** Recognized MIME types */ + private $mimeTypes = []; - /** - * Create a new Attachment with $headers, $encoder and $cache. - * - * @param array $mimeTypes - */ - public function __construct(Swift_Mime_SimpleHeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_IdGenerator $idGenerator, $mimeTypes = []) - { - parent::__construct($headers, $encoder, $cache, $idGenerator); - $this->setDisposition('attachment'); - $this->setContentType('application/octet-stream'); - $this->mimeTypes = $mimeTypes; - } + /** + * Create a new Attachment with $headers, $encoder and $cache. + * + * @param array $mimeTypes + */ + public function __construct(Swift_Mime_SimpleHeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_IdGenerator $idGenerator, $mimeTypes = []) + { + parent::__construct($headers, $encoder, $cache, $idGenerator); + $this->setDisposition('attachment'); + $this->setContentType('application/octet-stream'); + $this->mimeTypes = $mimeTypes; + } - /** - * Get the nesting level used for this attachment. - * - * Always returns {@link LEVEL_MIXED}. - * - * @return int - */ - public function getNestingLevel() - { - return self::LEVEL_MIXED; - } + /** + * Get the nesting level used for this attachment. + * + * Always returns {@link LEVEL_MIXED}. + * + * @return int + */ + public function getNestingLevel() + { + return self::LEVEL_MIXED; + } - /** - * Get the Content-Disposition of this attachment. - * - * By default attachments have a disposition of "attachment". - * - * @return string - */ - public function getDisposition() - { - return $this->getHeaderFieldModel('Content-Disposition'); - } + /** + * Get the Content-Disposition of this attachment. + * + * By default attachments have a disposition of "attachment". + * + * @return string + */ + public function getDisposition() + { + return $this->getHeaderFieldModel('Content-Disposition'); + } - /** - * Set the Content-Disposition of this attachment. - * - * @param string $disposition - * - * @return $this - */ - public function setDisposition($disposition) - { - if (!$this->setHeaderFieldModel('Content-Disposition', $disposition)) { - $this->getHeaders()->addParameterizedHeader('Content-Disposition', $disposition); - } + /** + * Set the Content-Disposition of this attachment. + * + * @param string $disposition + * + * @return $this + */ + public function setDisposition($disposition) + { + if (!$this->setHeaderFieldModel('Content-Disposition', $disposition)) { + $this->getHeaders()->addParameterizedHeader('Content-Disposition', $disposition); + } - return $this; - } + return $this; + } - /** - * Get the filename of this attachment when downloaded. - * - * @return string - */ - public function getFilename() - { - return $this->getHeaderParameter('Content-Disposition', 'filename'); - } + /** + * Get the filename of this attachment when downloaded. + * + * @return string + */ + public function getFilename() + { + return $this->getHeaderParameter('Content-Disposition', 'filename'); + } - /** - * Set the filename of this attachment. - * - * @param string $filename - * - * @return $this - */ - public function setFilename($filename) - { - $this->setHeaderParameter('Content-Disposition', 'filename', $filename); - $this->setHeaderParameter('Content-Type', 'name', $filename); + /** + * Set the filename of this attachment. + * + * @param string $filename + * + * @return $this + */ + public function setFilename($filename) + { + $this->setHeaderParameter('Content-Disposition', 'filename', $filename); + $this->setHeaderParameter('Content-Type', 'name', $filename); - return $this; - } + return $this; + } - /** - * Get the file size of this attachment. - * - * @return int - */ - public function getSize() - { - return $this->getHeaderParameter('Content-Disposition', 'size'); - } + /** + * Get the file size of this attachment. + * + * @return int + */ + public function getSize() + { + return $this->getHeaderParameter('Content-Disposition', 'size'); + } - /** - * Set the file size of this attachment. - * - * @param int $size - * - * @return $this - */ - public function setSize($size) - { - $this->setHeaderParameter('Content-Disposition', 'size', $size); + /** + * Set the file size of this attachment. + * + * @param int $size + * + * @return $this + */ + public function setSize($size) + { + $this->setHeaderParameter('Content-Disposition', 'size', $size); - return $this; - } + return $this; + } - /** - * Set the file that this attachment is for. - * - * @param string $contentType optional - * - * @return $this - */ - public function setFile(Swift_FileStream $file, $contentType = null) - { - $this->setFilename(basename($file->getPath())); - $this->setBody($file, $contentType); - if (!isset($contentType)) { - $extension = strtolower(substr($file->getPath(), strrpos($file->getPath(), '.') + 1)); + /** + * Set the file that this attachment is for. + * + * @param string $contentType optional + * + * @return $this + */ + public function setFile(Swift_FileStream $file, $contentType = null) + { + $this->setFilename(basename($file->getPath())); + $this->setBody($file, $contentType); + if (!isset($contentType)) { + $extension = strtolower(substr($file->getPath(), strrpos($file->getPath(), '.') + 1)); - if (\array_key_exists($extension, $this->mimeTypes)) { - $this->setContentType($this->mimeTypes[$extension]); - } - } + if (\array_key_exists($extension, $this->mimeTypes)) { + $this->setContentType($this->mimeTypes[$extension]); + } + } - return $this; - } + return $this; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/Base64ContentEncoder.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/Base64ContentEncoder.php index b7e1e028307..d7ae850d61a 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/Base64ContentEncoder.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/Base64ContentEncoder.php @@ -15,87 +15,87 @@ */ class Swift_Mime_ContentEncoder_Base64ContentEncoder extends Swift_Encoder_Base64Encoder implements Swift_Mime_ContentEncoder { - /** - * Encode stream $in to stream $out. - * - * @param int $firstLineOffset - */ - public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) - { - if (0 >= $maxLineLength || 76 < $maxLineLength) { - $maxLineLength = 76; - } + /** + * Encode stream $in to stream $out. + * + * @param int $firstLineOffset + */ + public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) + { + if (0 >= $maxLineLength || 76 < $maxLineLength) { + $maxLineLength = 76; + } - $remainder = 0; - $base64ReadBufferRemainderBytes = ''; + $remainder = 0; + $base64ReadBufferRemainderBytes = ''; - // To reduce memory usage, the output buffer is streamed to the input buffer like so: - // Output Stream => base64encode => wrap line length => Input Stream - // HOWEVER it's important to note that base64_encode() should only be passed whole triplets of data (except for the final chunk of data) - // otherwise it will assume the input data has *ended* and it will incorrectly pad/terminate the base64 data mid-stream. - // We use $base64ReadBufferRemainderBytes to carry over 1-2 "remainder" bytes from the each chunk from OutputStream and pre-pend those onto the - // chunk of bytes read in the next iteration. - // When the OutputStream is empty, we must flush any remainder bytes. - while (true) { - $readBytes = $os->read(8192); - $atEOF = (false === $readBytes); + // To reduce memory usage, the output buffer is streamed to the input buffer like so: + // Output Stream => base64encode => wrap line length => Input Stream + // HOWEVER it's important to note that base64_encode() should only be passed whole triplets of data (except for the final chunk of data) + // otherwise it will assume the input data has *ended* and it will incorrectly pad/terminate the base64 data mid-stream. + // We use $base64ReadBufferRemainderBytes to carry over 1-2 "remainder" bytes from the each chunk from OutputStream and pre-pend those onto the + // chunk of bytes read in the next iteration. + // When the OutputStream is empty, we must flush any remainder bytes. + while (true) { + $readBytes = $os->read(8192); + $atEOF = (false === $readBytes); - if ($atEOF) { - $streamTheseBytes = $base64ReadBufferRemainderBytes; - } else { - $streamTheseBytes = $base64ReadBufferRemainderBytes.$readBytes; - } - $base64ReadBufferRemainderBytes = ''; - $bytesLength = \strlen($streamTheseBytes); + if ($atEOF) { + $streamTheseBytes = $base64ReadBufferRemainderBytes; + } else { + $streamTheseBytes = $base64ReadBufferRemainderBytes.$readBytes; + } + $base64ReadBufferRemainderBytes = ''; + $bytesLength = \strlen($streamTheseBytes); - if (0 === $bytesLength) { // no data left to encode - break; - } + if (0 === $bytesLength) { // no data left to encode + break; + } - // if we're not on the last block of the ouput stream, make sure $streamTheseBytes ends with a complete triplet of data - // and carry over remainder 1-2 bytes to the next loop iteration - if (!$atEOF) { - $excessBytes = $bytesLength % 3; - if (0 !== $excessBytes) { - $base64ReadBufferRemainderBytes = substr($streamTheseBytes, -$excessBytes); - $streamTheseBytes = substr($streamTheseBytes, 0, $bytesLength - $excessBytes); - } - } + // if we're not on the last block of the ouput stream, make sure $streamTheseBytes ends with a complete triplet of data + // and carry over remainder 1-2 bytes to the next loop iteration + if (!$atEOF) { + $excessBytes = $bytesLength % 3; + if (0 !== $excessBytes) { + $base64ReadBufferRemainderBytes = substr($streamTheseBytes, -$excessBytes); + $streamTheseBytes = substr($streamTheseBytes, 0, $bytesLength - $excessBytes); + } + } - $encoded = base64_encode($streamTheseBytes); - $encodedTransformed = ''; - $thisMaxLineLength = $maxLineLength - $remainder - $firstLineOffset; + $encoded = base64_encode($streamTheseBytes); + $encodedTransformed = ''; + $thisMaxLineLength = $maxLineLength - $remainder - $firstLineOffset; - while ($thisMaxLineLength < \strlen($encoded)) { - $encodedTransformed .= substr($encoded, 0, $thisMaxLineLength)."\r\n"; - $firstLineOffset = 0; - $encoded = substr($encoded, $thisMaxLineLength); - $thisMaxLineLength = $maxLineLength; - $remainder = 0; - } + while ($thisMaxLineLength < \strlen($encoded)) { + $encodedTransformed .= substr($encoded, 0, $thisMaxLineLength)."\r\n"; + $firstLineOffset = 0; + $encoded = substr($encoded, $thisMaxLineLength); + $thisMaxLineLength = $maxLineLength; + $remainder = 0; + } - if (0 < $remainingLength = \strlen($encoded)) { - $remainder += $remainingLength; - $encodedTransformed .= $encoded; - $encoded = null; - } + if (0 < $remainingLength = \strlen($encoded)) { + $remainder += $remainingLength; + $encodedTransformed .= $encoded; + $encoded = null; + } - $is->write($encodedTransformed); + $is->write($encodedTransformed); - if ($atEOF) { - break; - } - } - } + if ($atEOF) { + break; + } + } + } - /** - * Get the name of this encoding scheme. - * Returns the string 'base64'. - * - * @return string - */ - public function getName() - { - return 'base64'; - } + /** + * Get the name of this encoding scheme. + * Returns the string 'base64'. + * + * @return string + */ + public function getName() + { + return 'base64'; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/NativeQpContentEncoder.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/NativeQpContentEncoder.php index 8dfea605fde..a678d67edaf 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/NativeQpContentEncoder.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/NativeQpContentEncoder.php @@ -15,107 +15,107 @@ */ class Swift_Mime_ContentEncoder_NativeQpContentEncoder implements Swift_Mime_ContentEncoder { - /** - * @var string|null - */ - private $charset; + /** + * @var string|null + */ + private $charset; - /** - * @param string|null $charset - */ - public function __construct($charset = null) - { - $this->charset = $charset ?: 'utf-8'; - } + /** + * @param string|null $charset + */ + public function __construct($charset = null) + { + $this->charset = $charset ?: 'utf-8'; + } - /** - * Notify this observer that the entity's charset has changed. - * - * @param string $charset - */ - public function charsetChanged($charset) - { - $this->charset = $charset; - } + /** + * Notify this observer that the entity's charset has changed. + * + * @param string $charset + */ + public function charsetChanged($charset) + { + $this->charset = $charset; + } - /** - * Encode $in to $out. - * - * @param Swift_OutputByteStream $os to read from - * @param Swift_InputByteStream $is to write to - * @param int $firstLineOffset - * @param int $maxLineLength 0 indicates the default length for this encoding - * - * @throws RuntimeException - */ - public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) - { - if ('utf-8' !== $this->charset) { - throw new RuntimeException(sprintf('Charset "%s" not supported. NativeQpContentEncoder only supports "utf-8"', $this->charset)); - } + /** + * Encode $in to $out. + * + * @param Swift_OutputByteStream $os to read from + * @param Swift_InputByteStream $is to write to + * @param int $firstLineOffset + * @param int $maxLineLength 0 indicates the default length for this encoding + * + * @throws RuntimeException + */ + public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) + { + if ('utf-8' !== $this->charset) { + throw new RuntimeException(sprintf('Charset "%s" not supported. NativeQpContentEncoder only supports "utf-8"', $this->charset)); + } - $string = ''; + $string = ''; - while (false !== $bytes = $os->read(8192)) { - $string .= $bytes; - } + while (false !== $bytes = $os->read(8192)) { + $string .= $bytes; + } - $is->write($this->encodeString($string)); - } + $is->write($this->encodeString($string)); + } - /** - * Get the MIME name of this content encoding scheme. - * - * @return string - */ - public function getName() - { - return 'quoted-printable'; - } + /** + * Get the MIME name of this content encoding scheme. + * + * @return string + */ + public function getName() + { + return 'quoted-printable'; + } - /** - * Encode a given string to produce an encoded string. - * - * @param string $string - * @param int $firstLineOffset if first line needs to be shorter - * @param int $maxLineLength 0 indicates the default length for this encoding - * - * @throws RuntimeException - * - * @return string - */ - public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) - { - if ('utf-8' !== $this->charset) { - throw new RuntimeException(sprintf('Charset "%s" not supported. NativeQpContentEncoder only supports "utf-8"', $this->charset)); - } + /** + * Encode a given string to produce an encoded string. + * + * @param string $string + * @param int $firstLineOffset if first line needs to be shorter + * @param int $maxLineLength 0 indicates the default length for this encoding + * + * @throws RuntimeException + * + * @return string + */ + public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) + { + if ('utf-8' !== $this->charset) { + throw new RuntimeException(sprintf('Charset "%s" not supported. NativeQpContentEncoder only supports "utf-8"', $this->charset)); + } - return $this->standardize(quoted_printable_encode($string)); - } + return $this->standardize(quoted_printable_encode($string)); + } - /** - * Make sure CRLF is correct and HT/SPACE are in valid places. - * - * @param string $string - * - * @return string - */ - protected function standardize($string) - { - // transform CR or LF to CRLF - $string = preg_replace('~=0D(?!=0A)|(?name = $name; - } + /** + * Creates a new NullContentEncoder with $name (probably 7bit or 8bit). + * + * @param string $name + */ + public function __construct($name) + { + $this->name = $name; + } - /** - * Encode a given string to produce an encoded string. - * - * @param string $string - * @param int $firstLineOffset ignored - * @param int $maxLineLength ignored - * - * @return string - */ - public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) - { - return $string; - } + /** + * Encode a given string to produce an encoded string. + * + * @param string $string + * @param int $firstLineOffset ignored + * @param int $maxLineLength ignored + * + * @return string + */ + public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) + { + return $string; + } - /** - * Encode stream $in to stream $out. - * - * @param int $firstLineOffset ignored - * @param int $maxLineLength ignored - */ - public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) - { - while (false !== ($bytes = $os->read(8192))) { - $is->write($bytes); - } - } + /** + * Encode stream $in to stream $out. + * + * @param int $firstLineOffset ignored + * @param int $maxLineLength ignored + */ + public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) + { + while (false !== ($bytes = $os->read(8192))) { + $is->write($bytes); + } + } - /** - * Get the name of this encoding scheme. - * - * @return string - */ - public function getName() - { - return $this->name; - } + /** + * Get the name of this encoding scheme. + * + * @return string + */ + public function getName() + { + return $this->name; + } - /** - * Not used. - */ - public function charsetChanged($charset) - { - } + /** + * Not used. + */ + public function charsetChanged($charset) + { + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/PlainContentEncoder.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/PlainContentEncoder.php index 72592fc5894..02546e03d95 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/PlainContentEncoder.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/PlainContentEncoder.php @@ -19,146 +19,146 @@ */ class Swift_Mime_ContentEncoder_PlainContentEncoder implements Swift_Mime_ContentEncoder { - /** - * The name of this encoding scheme (probably 7bit or 8bit). - * - * @var string - */ - private $name; + /** + * The name of this encoding scheme (probably 7bit or 8bit). + * + * @var string + */ + private $name; - /** - * True if canonical transformations should be done. - * - * @var bool - */ - private $canonical; + /** + * True if canonical transformations should be done. + * + * @var bool + */ + private $canonical; - /** - * Creates a new PlainContentEncoder with $name (probably 7bit or 8bit). - * - * @param string $name - * @param bool $canonical if canonicalization transformation should be done - */ - public function __construct($name, $canonical = false) - { - $this->name = $name; - $this->canonical = $canonical; - } + /** + * Creates a new PlainContentEncoder with $name (probably 7bit or 8bit). + * + * @param string $name + * @param bool $canonical if canonicalization transformation should be done + */ + public function __construct($name, $canonical = false) + { + $this->name = $name; + $this->canonical = $canonical; + } - /** - * Encode a given string to produce an encoded string. - * - * @param string $string - * @param int $firstLineOffset ignored - * @param int $maxLineLength - 0 means no wrapping will occur - * - * @return string - */ - public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) - { - if ($this->canonical) { - $string = $this->canonicalize($string); - } + /** + * Encode a given string to produce an encoded string. + * + * @param string $string + * @param int $firstLineOffset ignored + * @param int $maxLineLength - 0 means no wrapping will occur + * + * @return string + */ + public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) + { + if ($this->canonical) { + $string = $this->canonicalize($string); + } - return $this->safeWordwrap($string, $maxLineLength, "\r\n"); - } + return $this->safeWordwrap($string, $maxLineLength, "\r\n"); + } - /** - * Encode stream $in to stream $out. - * - * @param int $firstLineOffset ignored - * @param int $maxLineLength optional, 0 means no wrapping will occur - */ - public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) - { - $leftOver = ''; - while (false !== $bytes = $os->read(8192)) { - $toencode = $leftOver.$bytes; - if ($this->canonical) { - $toencode = $this->canonicalize($toencode); - } - $wrapped = $this->safeWordwrap($toencode, $maxLineLength, "\r\n"); - $lastLinePos = strrpos($wrapped, "\r\n"); - $leftOver = substr($wrapped, $lastLinePos); - $wrapped = substr($wrapped, 0, $lastLinePos); + /** + * Encode stream $in to stream $out. + * + * @param int $firstLineOffset ignored + * @param int $maxLineLength optional, 0 means no wrapping will occur + */ + public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) + { + $leftOver = ''; + while (false !== $bytes = $os->read(8192)) { + $toencode = $leftOver.$bytes; + if ($this->canonical) { + $toencode = $this->canonicalize($toencode); + } + $wrapped = $this->safeWordwrap($toencode, $maxLineLength, "\r\n"); + $lastLinePos = strrpos($wrapped, "\r\n"); + $leftOver = substr($wrapped, $lastLinePos); + $wrapped = substr($wrapped, 0, $lastLinePos); - $is->write($wrapped); - } - if (\strlen($leftOver)) { - $is->write($leftOver); - } - } + $is->write($wrapped); + } + if (\strlen($leftOver)) { + $is->write($leftOver); + } + } - /** - * Get the name of this encoding scheme. - * - * @return string - */ - public function getName() - { - return $this->name; - } + /** + * Get the name of this encoding scheme. + * + * @return string + */ + public function getName() + { + return $this->name; + } - /** - * Not used. - */ - public function charsetChanged($charset) - { - } + /** + * Not used. + */ + public function charsetChanged($charset) + { + } - /** - * A safer (but weaker) wordwrap for unicode. - * - * @param string $string - * @param int $length - * @param string $le - * - * @return string - */ - private function safeWordwrap($string, $length = 75, $le = "\r\n") - { - if (0 >= $length) { - return $string; - } + /** + * A safer (but weaker) wordwrap for unicode. + * + * @param string $string + * @param int $length + * @param string $le + * + * @return string + */ + private function safeWordwrap($string, $length = 75, $le = "\r\n") + { + if (0 >= $length) { + return $string; + } - $originalLines = explode($le, $string); + $originalLines = explode($le, $string); - $lines = []; - $lineCount = 0; + $lines = []; + $lineCount = 0; - foreach ($originalLines as $originalLine) { - $lines[] = ''; - $currentLine = &$lines[$lineCount++]; + foreach ($originalLines as $originalLine) { + $lines[] = ''; + $currentLine = &$lines[$lineCount++]; - //$chunks = preg_split('/(?<=[\ \t,\.!\?\-&\+\/])/', $originalLine); - $chunks = preg_split('/(?<=\s)/', $originalLine); + //$chunks = preg_split('/(?<=[\ \t,\.!\?\-&\+\/])/', $originalLine); + $chunks = preg_split('/(?<=\s)/', $originalLine); - foreach ($chunks as $chunk) { - if (0 != \strlen($currentLine) - && \strlen($currentLine.$chunk) > $length) { - $lines[] = ''; - $currentLine = &$lines[$lineCount++]; - } - $currentLine .= $chunk; - } - } + foreach ($chunks as $chunk) { + if (0 != \strlen($currentLine) + && \strlen($currentLine.$chunk) > $length) { + $lines[] = ''; + $currentLine = &$lines[$lineCount++]; + } + $currentLine .= $chunk; + } + } - return implode("\r\n", $lines); - } + return implode("\r\n", $lines); + } - /** - * Canonicalize string input (fix CRLF). - * - * @param string $string - * - * @return string - */ - private function canonicalize($string) - { - return str_replace( - ["\r\n", "\r", "\n"], - ["\n", "\n", "\r\n"], - $string - ); - } + /** + * Canonicalize string input (fix CRLF). + * + * @param string $string + * + * @return string + */ + private function canonicalize($string) + { + return str_replace( + ["\r\n", "\r", "\n"], + ["\n", "\n", "\r\n"], + $string + ); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoder.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoder.php index 465ffd87850..51785234043 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoder.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoder.php @@ -15,120 +15,120 @@ */ class Swift_Mime_ContentEncoder_QpContentEncoder extends Swift_Encoder_QpEncoder implements Swift_Mime_ContentEncoder { - protected $dotEscape; + protected $dotEscape; - /** - * Creates a new QpContentEncoder for the given CharacterStream. - * - * @param Swift_CharacterStream $charStream to use for reading characters - * @param Swift_StreamFilter $filter if canonicalization should occur - * @param bool $dotEscape if dot stuffing workaround must be enabled - */ - public function __construct(Swift_CharacterStream $charStream, Swift_StreamFilter $filter = null, $dotEscape = false) - { - $this->dotEscape = $dotEscape; - parent::__construct($charStream, $filter); - } + /** + * Creates a new QpContentEncoder for the given CharacterStream. + * + * @param Swift_CharacterStream $charStream to use for reading characters + * @param Swift_StreamFilter $filter if canonicalization should occur + * @param bool $dotEscape if dot stuffing workaround must be enabled + */ + public function __construct(Swift_CharacterStream $charStream, Swift_StreamFilter $filter = null, $dotEscape = false) + { + $this->dotEscape = $dotEscape; + parent::__construct($charStream, $filter); + } - public function __sleep() - { - return ['charStream', 'filter', 'dotEscape']; - } + public function __sleep() + { + return ['charStream', 'filter', 'dotEscape']; + } - protected function getSafeMapShareId() - { - return static::class.($this->dotEscape ? '.dotEscape' : ''); - } + protected function getSafeMapShareId() + { + return static::class.($this->dotEscape ? '.dotEscape' : ''); + } - protected function initSafeMap() - { - parent::initSafeMap(); - if ($this->dotEscape) { - /* Encode . as =2e for buggy remote servers */ - unset($this->safeMap[0x2e]); - } - } + protected function initSafeMap() + { + parent::initSafeMap(); + if ($this->dotEscape) { + /* Encode . as =2e for buggy remote servers */ + unset($this->safeMap[0x2e]); + } + } - /** - * Encode stream $in to stream $out. - * - * QP encoded strings have a maximum line length of 76 characters. - * If the first line needs to be shorter, indicate the difference with - * $firstLineOffset. - * - * @param Swift_OutputByteStream $os output stream - * @param Swift_InputByteStream $is input stream - * @param int $firstLineOffset - * @param int $maxLineLength - */ - public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) - { - if ($maxLineLength > 76 || $maxLineLength <= 0) { - $maxLineLength = 76; - } + /** + * Encode stream $in to stream $out. + * + * QP encoded strings have a maximum line length of 76 characters. + * If the first line needs to be shorter, indicate the difference with + * $firstLineOffset. + * + * @param Swift_OutputByteStream $os output stream + * @param Swift_InputByteStream $is input stream + * @param int $firstLineOffset + * @param int $maxLineLength + */ + public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) + { + if ($maxLineLength > 76 || $maxLineLength <= 0) { + $maxLineLength = 76; + } - $thisLineLength = $maxLineLength - $firstLineOffset; + $thisLineLength = $maxLineLength - $firstLineOffset; - $this->charStream->flushContents(); - $this->charStream->importByteStream($os); + $this->charStream->flushContents(); + $this->charStream->importByteStream($os); - $currentLine = ''; - $prepend = ''; - $size = $lineLen = 0; + $currentLine = ''; + $prepend = ''; + $size = $lineLen = 0; - while (false !== $bytes = $this->nextSequence()) { - // If we're filtering the input - if (isset($this->filter)) { - // If we can't filter because we need more bytes - while ($this->filter->shouldBuffer($bytes)) { - // Then collect bytes into the buffer - if (false === $moreBytes = $this->nextSequence(1)) { - break; - } + while (false !== $bytes = $this->nextSequence()) { + // If we're filtering the input + if (isset($this->filter)) { + // If we can't filter because we need more bytes + while ($this->filter->shouldBuffer($bytes)) { + // Then collect bytes into the buffer + if (false === $moreBytes = $this->nextSequence(1)) { + break; + } - foreach ($moreBytes as $b) { - $bytes[] = $b; - } - } - // And filter them - $bytes = $this->filter->filter($bytes); - } + foreach ($moreBytes as $b) { + $bytes[] = $b; + } + } + // And filter them + $bytes = $this->filter->filter($bytes); + } - $enc = $this->encodeByteSequence($bytes, $size); + $enc = $this->encodeByteSequence($bytes, $size); - $i = strpos($enc, '=0D=0A'); - $newLineLength = $lineLen + (false === $i ? $size : $i); + $i = strpos($enc, '=0D=0A'); + $newLineLength = $lineLen + (false === $i ? $size : $i); - if ($currentLine && $newLineLength >= $thisLineLength) { - $is->write($prepend.$this->standardize($currentLine)); - $currentLine = ''; - $prepend = "=\r\n"; - $thisLineLength = $maxLineLength; - $lineLen = 0; - } + if ($currentLine && $newLineLength >= $thisLineLength) { + $is->write($prepend.$this->standardize($currentLine)); + $currentLine = ''; + $prepend = "=\r\n"; + $thisLineLength = $maxLineLength; + $lineLen = 0; + } - $currentLine .= $enc; + $currentLine .= $enc; - if (false === $i) { - $lineLen += $size; - } else { - // 6 is the length of '=0D=0A'. - $lineLen = $size - strrpos($enc, '=0D=0A') - 6; - } - } - if (\strlen($currentLine)) { - $is->write($prepend.$this->standardize($currentLine)); - } - } + if (false === $i) { + $lineLen += $size; + } else { + // 6 is the length of '=0D=0A'. + $lineLen = $size - strrpos($enc, '=0D=0A') - 6; + } + } + if (\strlen($currentLine)) { + $is->write($prepend.$this->standardize($currentLine)); + } + } - /** - * Get the name of this encoding scheme. - * Returns the string 'quoted-printable'. - * - * @return string - */ - public function getName() - { - return 'quoted-printable'; - } + /** + * Get the name of this encoding scheme. + * Returns the string 'quoted-printable'. + * + * @return string + */ + public function getName() + { + return 'quoted-printable'; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoderProxy.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoderProxy.php index f3ece43aecd..7b9fb138c3a 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoderProxy.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoderProxy.php @@ -17,80 +17,80 @@ */ class Swift_Mime_ContentEncoder_QpContentEncoderProxy implements Swift_Mime_ContentEncoder { - /** - * @var Swift_Mime_ContentEncoder_QpContentEncoder - */ - private $safeEncoder; + /** + * @var Swift_Mime_ContentEncoder_QpContentEncoder + */ + private $safeEncoder; - /** - * @var Swift_Mime_ContentEncoder_NativeQpContentEncoder - */ - private $nativeEncoder; + /** + * @var Swift_Mime_ContentEncoder_NativeQpContentEncoder + */ + private $nativeEncoder; - /** - * @var string|null - */ - private $charset; + /** + * @var string|null + */ + private $charset; - /** - * Constructor. - * - * @param string|null $charset - */ - public function __construct(Swift_Mime_ContentEncoder_QpContentEncoder $safeEncoder, Swift_Mime_ContentEncoder_NativeQpContentEncoder $nativeEncoder, $charset) - { - $this->safeEncoder = $safeEncoder; - $this->nativeEncoder = $nativeEncoder; - $this->charset = $charset; - } + /** + * Constructor. + * + * @param string|null $charset + */ + public function __construct(Swift_Mime_ContentEncoder_QpContentEncoder $safeEncoder, Swift_Mime_ContentEncoder_NativeQpContentEncoder $nativeEncoder, $charset) + { + $this->safeEncoder = $safeEncoder; + $this->nativeEncoder = $nativeEncoder; + $this->charset = $charset; + } - /** - * Make a deep copy of object. - */ - public function __clone() - { - $this->safeEncoder = clone $this->safeEncoder; - $this->nativeEncoder = clone $this->nativeEncoder; - } + /** + * Make a deep copy of object. + */ + public function __clone() + { + $this->safeEncoder = clone $this->safeEncoder; + $this->nativeEncoder = clone $this->nativeEncoder; + } - /** - * {@inheritdoc} - */ - public function charsetChanged($charset) - { - $this->charset = $charset; - $this->safeEncoder->charsetChanged($charset); - } + /** + * {@inheritdoc} + */ + public function charsetChanged($charset) + { + $this->charset = $charset; + $this->safeEncoder->charsetChanged($charset); + } - /** - * {@inheritdoc} - */ - public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) - { - $this->getEncoder()->encodeByteStream($os, $is, $firstLineOffset, $maxLineLength); - } + /** + * {@inheritdoc} + */ + public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) + { + $this->getEncoder()->encodeByteStream($os, $is, $firstLineOffset, $maxLineLength); + } - /** - * {@inheritdoc} - */ - public function getName() - { - return 'quoted-printable'; - } + /** + * {@inheritdoc} + */ + public function getName() + { + return 'quoted-printable'; + } - /** - * {@inheritdoc} - */ - public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) - { - return $this->getEncoder()->encodeString($string, $firstLineOffset, $maxLineLength); - } + /** + * {@inheritdoc} + */ + public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) + { + return $this->getEncoder()->encodeString($string, $firstLineOffset, $maxLineLength); + } - /** - * @return Swift_Mime_ContentEncoder - */ - private function getEncoder() - { - return 'utf-8' === $this->charset ? $this->nativeEncoder : $this->safeEncoder; - } + /** + * @return Swift_Mime_ContentEncoder + */ + private function getEncoder() + { + return 'utf-8' === $this->charset ? $this->nativeEncoder : $this->safeEncoder; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/RawContentEncoder.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/RawContentEncoder.php index 870e7f41a93..99d09c56478 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/RawContentEncoder.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/RawContentEncoder.php @@ -19,47 +19,47 @@ */ class Swift_Mime_ContentEncoder_RawContentEncoder implements Swift_Mime_ContentEncoder { - /** - * Encode a given string to produce an encoded string. - * - * @param string $string - * @param int $firstLineOffset ignored - * @param int $maxLineLength ignored - * - * @return string - */ - public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) - { - return $string; - } + /** + * Encode a given string to produce an encoded string. + * + * @param string $string + * @param int $firstLineOffset ignored + * @param int $maxLineLength ignored + * + * @return string + */ + public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) + { + return $string; + } - /** - * Encode stream $in to stream $out. - * - * @param int $firstLineOffset ignored - * @param int $maxLineLength ignored - */ - public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) - { - while (false !== ($bytes = $os->read(8192))) { - $is->write($bytes); - } - } + /** + * Encode stream $in to stream $out. + * + * @param int $firstLineOffset ignored + * @param int $maxLineLength ignored + */ + public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) + { + while (false !== ($bytes = $os->read(8192))) { + $is->write($bytes); + } + } - /** - * Get the name of this encoding scheme. - * - * @return string - */ - public function getName() - { - return 'raw'; - } + /** + * Get the name of this encoding scheme. + * + * @return string + */ + public function getName() + { + return 'raw'; + } - /** - * Not used. - */ - public function charsetChanged($charset) - { - } + /** + * Not used. + */ + public function charsetChanged($charset) + { + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/EmbeddedFile.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/EmbeddedFile.php index 42a51770c76..7b65f781465 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/EmbeddedFile.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/EmbeddedFile.php @@ -15,27 +15,27 @@ */ class Swift_Mime_EmbeddedFile extends Swift_Mime_Attachment { - /** - * Creates a new Attachment with $headers and $encoder. - * - * @param array $mimeTypes optional - */ - public function __construct(Swift_Mime_SimpleHeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_IdGenerator $idGenerator, $mimeTypes = []) - { - parent::__construct($headers, $encoder, $cache, $idGenerator, $mimeTypes); - $this->setDisposition('inline'); - $this->setId($this->getId()); - } + /** + * Creates a new Attachment with $headers and $encoder. + * + * @param array $mimeTypes optional + */ + public function __construct(Swift_Mime_SimpleHeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_IdGenerator $idGenerator, $mimeTypes = []) + { + parent::__construct($headers, $encoder, $cache, $idGenerator, $mimeTypes); + $this->setDisposition('inline'); + $this->setId($this->getId()); + } - /** - * Get the nesting level of this EmbeddedFile. - * - * Returns {@see LEVEL_RELATED}. - * - * @return int - */ - public function getNestingLevel() - { - return self::LEVEL_RELATED; - } + /** + * Get the nesting level of this EmbeddedFile. + * + * Returns {@see LEVEL_RELATED}. + * + * @return int + */ + public function getNestingLevel() + { + return self::LEVEL_RELATED; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/EncodingObserver.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/EncodingObserver.php index 1a952ece12c..51915764259 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/EncodingObserver.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/EncodingObserver.php @@ -15,8 +15,8 @@ */ interface Swift_Mime_EncodingObserver { - /** - * Notify this observer that the observed entity's ContentEncoder has changed. - */ - public function encoderChanged(Swift_Mime_ContentEncoder $encoder); + /** + * Notify this observer that the observed entity's ContentEncoder has changed. + */ + public function encoderChanged(Swift_Mime_ContentEncoder $encoder); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Header.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Header.php index ca712f35aa0..e2559ffba52 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Header.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Header.php @@ -15,79 +15,79 @@ */ interface Swift_Mime_Header { - /** Text headers */ - const TYPE_TEXT = 2; + /** Text headers */ + const TYPE_TEXT = 2; - /** headers (text + params) */ - const TYPE_PARAMETERIZED = 6; + /** headers (text + params) */ + const TYPE_PARAMETERIZED = 6; - /** Mailbox and address headers */ - const TYPE_MAILBOX = 8; + /** Mailbox and address headers */ + const TYPE_MAILBOX = 8; - /** Date and time headers */ - const TYPE_DATE = 16; + /** Date and time headers */ + const TYPE_DATE = 16; - /** Identification headers */ - const TYPE_ID = 32; + /** Identification headers */ + const TYPE_ID = 32; - /** Address path headers */ - const TYPE_PATH = 64; + /** Address path headers */ + const TYPE_PATH = 64; - /** - * Get the type of Header that this instance represents. - * - * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX - * @see TYPE_DATE, TYPE_ID, TYPE_PATH - * - * @return int - */ - public function getFieldType(); + /** + * Get the type of Header that this instance represents. + * + * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX + * @see TYPE_DATE, TYPE_ID, TYPE_PATH + * + * @return int + */ + public function getFieldType(); - /** - * Set the model for the field body. - * - * The actual types needed will vary depending upon the type of Header. - * - * @param mixed $model - */ - public function setFieldBodyModel($model); + /** + * Set the model for the field body. + * + * The actual types needed will vary depending upon the type of Header. + * + * @param mixed $model + */ + public function setFieldBodyModel($model); - /** - * Set the charset used when rendering the Header. - * - * @param string $charset - */ - public function setCharset($charset); + /** + * Set the charset used when rendering the Header. + * + * @param string $charset + */ + public function setCharset($charset); - /** - * Get the model for the field body. - * - * The return type depends on the specifics of the Header. - * - * @return mixed - */ - public function getFieldBodyModel(); + /** + * Get the model for the field body. + * + * The return type depends on the specifics of the Header. + * + * @return mixed + */ + public function getFieldBodyModel(); - /** - * Get the name of this header (e.g. Subject). - * - * The name is an identifier and as such will be immutable. - * - * @return string - */ - public function getFieldName(); + /** + * Get the name of this header (e.g. Subject). + * + * The name is an identifier and as such will be immutable. + * + * @return string + */ + public function getFieldName(); - /** - * Get the field body, prepared for folding into a final header value. - * - * @return string - */ - public function getFieldBody(); + /** + * Get the field body, prepared for folding into a final header value. + * + * @return string + */ + public function getFieldBody(); - /** - * Get this Header rendered as a compliant string, including trailing CRLF. - * - * @return string - */ - public function toString(); + /** + * Get this Header rendered as a compliant string, including trailing CRLF. + * + * @return string + */ + public function toString(); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder/Base64HeaderEncoder.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder/Base64HeaderEncoder.php index 21c8aaabfea..6bcb1e4e8f8 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder/Base64HeaderEncoder.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder/Base64HeaderEncoder.php @@ -15,41 +15,41 @@ */ class Swift_Mime_HeaderEncoder_Base64HeaderEncoder extends Swift_Encoder_Base64Encoder implements Swift_Mime_HeaderEncoder { - /** - * Get the name of this encoding scheme. - * Returns the string 'B'. - * - * @return string - */ - public function getName() - { - return 'B'; - } + /** + * Get the name of this encoding scheme. + * Returns the string 'B'. + * + * @return string + */ + public function getName() + { + return 'B'; + } - /** - * Takes an unencoded string and produces a Base64 encoded string from it. - * - * If the charset is iso-2022-jp, it uses mb_encode_mimeheader instead of - * default encodeString, otherwise pass to the parent method. - * - * @param string $string string to encode - * @param int $firstLineOffset - * @param int $maxLineLength optional, 0 indicates the default of 76 bytes - * @param string $charset - * - * @return string - */ - public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0, $charset = 'utf-8') - { - if ('iso-2022-jp' === strtolower($charset ?? '')) { - $old = mb_internal_encoding(); - mb_internal_encoding('utf-8'); - $newstring = mb_encode_mimeheader($string, $charset, $this->getName(), "\r\n"); - mb_internal_encoding($old); + /** + * Takes an unencoded string and produces a Base64 encoded string from it. + * + * If the charset is iso-2022-jp, it uses mb_encode_mimeheader instead of + * default encodeString, otherwise pass to the parent method. + * + * @param string $string string to encode + * @param int $firstLineOffset + * @param int $maxLineLength optional, 0 indicates the default of 76 bytes + * @param string $charset + * + * @return string + */ + public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0, $charset = 'utf-8') + { + if ('iso-2022-jp' === strtolower($charset ?? '')) { + $old = mb_internal_encoding(); + mb_internal_encoding('utf-8'); + $newstring = mb_encode_mimeheader($string, $charset, $this->getName(), "\r\n"); + mb_internal_encoding($old); - return $newstring; - } + return $newstring; + } - return parent::encodeString($string, $firstLineOffset, $maxLineLength); - } + return parent::encodeString($string, $firstLineOffset, $maxLineLength); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder/QpHeaderEncoder.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder/QpHeaderEncoder.php index 378c4805057..6cfeb3b9285 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder/QpHeaderEncoder.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder/QpHeaderEncoder.php @@ -15,51 +15,51 @@ */ class Swift_Mime_HeaderEncoder_QpHeaderEncoder extends Swift_Encoder_QpEncoder implements Swift_Mime_HeaderEncoder { - /** - * Creates a new QpHeaderEncoder for the given CharacterStream. - * - * @param Swift_CharacterStream $charStream to use for reading characters - */ - public function __construct(Swift_CharacterStream $charStream) - { - parent::__construct($charStream); - } + /** + * Creates a new QpHeaderEncoder for the given CharacterStream. + * + * @param Swift_CharacterStream $charStream to use for reading characters + */ + public function __construct(Swift_CharacterStream $charStream) + { + parent::__construct($charStream); + } - protected function initSafeMap() - { - foreach (array_merge( - range(0x61, 0x7A), range(0x41, 0x5A), - range(0x30, 0x39), [0x20, 0x21, 0x2A, 0x2B, 0x2D, 0x2F] - ) as $byte) { - $this->safeMap[$byte] = \chr($byte); - } - } + protected function initSafeMap() + { + foreach (array_merge( + range(0x61, 0x7A), range(0x41, 0x5A), + range(0x30, 0x39), [0x20, 0x21, 0x2A, 0x2B, 0x2D, 0x2F] + ) as $byte) { + $this->safeMap[$byte] = \chr($byte); + } + } - /** - * Get the name of this encoding scheme. - * - * Returns the string 'Q'. - * - * @return string - */ - public function getName() - { - return 'Q'; - } + /** + * Get the name of this encoding scheme. + * + * Returns the string 'Q'. + * + * @return string + */ + public function getName() + { + return 'Q'; + } - /** - * Takes an unencoded string and produces a QP encoded string from it. - * - * @param string $string string to encode - * @param int $firstLineOffset optional - * @param int $maxLineLength optional, 0 indicates the default of 76 chars - * - * @return string - */ - public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) - { - return str_replace([' ', '=20', "=\r\n"], ['_', '_', "\r\n"], - parent::encodeString($string, $firstLineOffset, $maxLineLength) - ); - } + /** + * Takes an unencoded string and produces a QP encoded string from it. + * + * @param string $string string to encode + * @param int $firstLineOffset optional + * @param int $maxLineLength optional, 0 indicates the default of 76 chars + * + * @return string + */ + public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) + { + return str_replace([' ', '=20', "=\r\n"], ['_', '_', "\r\n"], + parent::encodeString($string, $firstLineOffset, $maxLineLength) + ); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/AbstractHeader.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/AbstractHeader.php index 25740d1155c..344a2b4a7a7 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/AbstractHeader.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/AbstractHeader.php @@ -15,472 +15,472 @@ */ abstract class Swift_Mime_Headers_AbstractHeader implements Swift_Mime_Header { - const PHRASE_PATTERN = '(?:(?:(?:(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?[a-zA-Z0-9!#\$%&\'\*\+\-\/=\?\^_`\{\}\|~]+(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?)|(?:(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?"((?:(?:[ \t]*(?:\r\n))?[ \t])?(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21\x23-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])))*(?:(?:[ \t]*(?:\r\n))?[ \t])?"(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?))+?)'; + const PHRASE_PATTERN = '(?:(?:(?:(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?[a-zA-Z0-9!#\$%&\'\*\+\-\/=\?\^_`\{\}\|~]+(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?)|(?:(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?"((?:(?:[ \t]*(?:\r\n))?[ \t])?(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21\x23-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])))*(?:(?:[ \t]*(?:\r\n))?[ \t])?"(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?))+?)'; - /** - * The name of this Header. - * - * @var string - */ - private $name; + /** + * The name of this Header. + * + * @var string + */ + private $name; - /** - * The Encoder used to encode this Header. - * - * @var Swift_Encoder - */ - private $encoder; + /** + * The Encoder used to encode this Header. + * + * @var Swift_Encoder + */ + private $encoder; - /** - * The maximum length of a line in the header. - * - * @var int - */ - private $lineLength = 78; + /** + * The maximum length of a line in the header. + * + * @var int + */ + private $lineLength = 78; - /** - * The language used in this Header. - * - * @var string - */ - private $lang; + /** + * The language used in this Header. + * + * @var string + */ + private $lang; - /** - * The character set of the text in this Header. - * - * @var string - */ - private $charset = 'utf-8'; + /** + * The character set of the text in this Header. + * + * @var string + */ + private $charset = 'utf-8'; - /** - * The value of this Header, cached. - * - * @var string - */ - private $cachedValue = null; + /** + * The value of this Header, cached. + * + * @var string + */ + private $cachedValue = null; - /** - * Set the character set used in this Header. - * - * @param string $charset - */ - public function setCharset($charset) - { - $this->clearCachedValueIf($charset != $this->charset); - $this->charset = $charset; - if (isset($this->encoder)) { - $this->encoder->charsetChanged($charset); - } - } + /** + * Set the character set used in this Header. + * + * @param string $charset + */ + public function setCharset($charset) + { + $this->clearCachedValueIf($charset != $this->charset); + $this->charset = $charset; + if (isset($this->encoder)) { + $this->encoder->charsetChanged($charset); + } + } - /** - * Get the character set used in this Header. - * - * @return string - */ - public function getCharset() - { - return $this->charset; - } + /** + * Get the character set used in this Header. + * + * @return string + */ + public function getCharset() + { + return $this->charset; + } - /** - * Set the language used in this Header. - * - * For example, for US English, 'en-us'. - * This can be unspecified. - * - * @param string $lang - */ - public function setLanguage($lang) - { - $this->clearCachedValueIf($this->lang != $lang); - $this->lang = $lang; - } + /** + * Set the language used in this Header. + * + * For example, for US English, 'en-us'. + * This can be unspecified. + * + * @param string $lang + */ + public function setLanguage($lang) + { + $this->clearCachedValueIf($this->lang != $lang); + $this->lang = $lang; + } - /** - * Get the language used in this Header. - * - * @return string - */ - public function getLanguage() - { - return $this->lang; - } + /** + * Get the language used in this Header. + * + * @return string + */ + public function getLanguage() + { + return $this->lang; + } - /** - * Set the encoder used for encoding the header. - */ - public function setEncoder(Swift_Mime_HeaderEncoder $encoder) - { - $this->encoder = $encoder; - $this->setCachedValue(null); - } + /** + * Set the encoder used for encoding the header. + */ + public function setEncoder(Swift_Mime_HeaderEncoder $encoder) + { + $this->encoder = $encoder; + $this->setCachedValue(null); + } - /** - * Get the encoder used for encoding this Header. - * - * @return Swift_Mime_HeaderEncoder - */ - public function getEncoder() - { - return $this->encoder; - } + /** + * Get the encoder used for encoding this Header. + * + * @return Swift_Mime_HeaderEncoder + */ + public function getEncoder() + { + return $this->encoder; + } - /** - * Get the name of this header (e.g. charset). - * - * @return string - */ - public function getFieldName() - { - return $this->name; - } + /** + * Get the name of this header (e.g. charset). + * + * @return string + */ + public function getFieldName() + { + return $this->name; + } - /** - * Set the maximum length of lines in the header (excluding EOL). - * - * @param int $lineLength - */ - public function setMaxLineLength($lineLength) - { - $this->clearCachedValueIf($this->lineLength != $lineLength); - $this->lineLength = $lineLength; - } + /** + * Set the maximum length of lines in the header (excluding EOL). + * + * @param int $lineLength + */ + public function setMaxLineLength($lineLength) + { + $this->clearCachedValueIf($this->lineLength != $lineLength); + $this->lineLength = $lineLength; + } - /** - * Get the maximum permitted length of lines in this Header. - * - * @return int - */ - public function getMaxLineLength() - { - return $this->lineLength; - } + /** + * Get the maximum permitted length of lines in this Header. + * + * @return int + */ + public function getMaxLineLength() + { + return $this->lineLength; + } - /** - * Get this Header rendered as a RFC 2822 compliant string. - * - * @return string - * - * @throws Swift_RfcComplianceException - */ - public function toString() - { - return $this->tokensToString($this->toTokens()); - } + /** + * Get this Header rendered as a RFC 2822 compliant string. + * + * @return string + * + * @throws Swift_RfcComplianceException + */ + public function toString() + { + return $this->tokensToString($this->toTokens()); + } - /** - * Returns a string representation of this object. - * - * @return string - * - * @see toString() - */ - public function __toString() - { - return $this->toString(); - } + /** + * Returns a string representation of this object. + * + * @return string + * + * @see toString() + */ + public function __toString() + { + return $this->toString(); + } - /** - * Set the name of this Header field. - * - * @param string $name - */ - protected function setFieldName($name) - { - $this->name = $name; - } + /** + * Set the name of this Header field. + * + * @param string $name + */ + protected function setFieldName($name) + { + $this->name = $name; + } - /** - * Produces a compliant, formatted RFC 2822 'phrase' based on the string given. - * - * @param string $string as displayed - * @param string $charset of the text - * @param bool $shorten the first line to make remove for header name - * - * @return string - */ - protected function createPhrase(Swift_Mime_Header $header, $string, $charset, Swift_Mime_HeaderEncoder $encoder = null, $shorten = false) - { - // Treat token as exactly what was given - $phraseStr = $string; - // If it's not valid + /** + * Produces a compliant, formatted RFC 2822 'phrase' based on the string given. + * + * @param string $string as displayed + * @param string $charset of the text + * @param bool $shorten the first line to make remove for header name + * + * @return string + */ + protected function createPhrase(Swift_Mime_Header $header, $string, $charset, Swift_Mime_HeaderEncoder $encoder = null, $shorten = false) + { + // Treat token as exactly what was given + $phraseStr = $string; + // If it's not valid - if (!preg_match('/^'.self::PHRASE_PATTERN.'$/D', $phraseStr)) { - // .. but it is just ascii text, try escaping some characters - // and make it a quoted-string - if (preg_match('/^[\x00-\x08\x0B\x0C\x0E-\x7F]*$/D', $phraseStr)) { - $phraseStr = $this->escapeSpecials($phraseStr, ['"']); - $phraseStr = '"'.$phraseStr.'"'; - } else { - // ... otherwise it needs encoding - // Determine space remaining on line if first line - if ($shorten) { - $usedLength = \strlen($header->getFieldName().': '); - } else { - $usedLength = 0; - } - $phraseStr = $this->encodeWords($header, $string, $usedLength); - } - } + if (!preg_match('/^'.self::PHRASE_PATTERN.'$/D', $phraseStr)) { + // .. but it is just ascii text, try escaping some characters + // and make it a quoted-string + if (preg_match('/^[\x00-\x08\x0B\x0C\x0E-\x7F]*$/D', $phraseStr)) { + $phraseStr = $this->escapeSpecials($phraseStr, ['"']); + $phraseStr = '"'.$phraseStr.'"'; + } else { + // ... otherwise it needs encoding + // Determine space remaining on line if first line + if ($shorten) { + $usedLength = \strlen($header->getFieldName().': '); + } else { + $usedLength = 0; + } + $phraseStr = $this->encodeWords($header, $string, $usedLength); + } + } - return $phraseStr; - } + return $phraseStr; + } - /** - * Escape special characters in a string (convert to quoted-pairs). - * - * @param string $token - * @param string[] $include additional chars to escape - * - * @return string - */ - private function escapeSpecials($token, $include = []) - { - foreach (array_merge(['\\'], $include) as $char) { - $token = str_replace($char, '\\'.$char, $token); - } + /** + * Escape special characters in a string (convert to quoted-pairs). + * + * @param string $token + * @param string[] $include additional chars to escape + * + * @return string + */ + private function escapeSpecials($token, $include = []) + { + foreach (array_merge(['\\'], $include) as $char) { + $token = str_replace($char, '\\'.$char, $token); + } - return $token; - } + return $token; + } - /** - * Encode needed word tokens within a string of input. - * - * @param string $input - * @param string $usedLength optional - * - * @return string - */ - protected function encodeWords(Swift_Mime_Header $header, $input, $usedLength = -1) - { - $value = ''; + /** + * Encode needed word tokens within a string of input. + * + * @param string $input + * @param string $usedLength optional + * + * @return string + */ + protected function encodeWords(Swift_Mime_Header $header, $input, $usedLength = -1) + { + $value = ''; - $tokens = $this->getEncodableWordTokens($input); + $tokens = $this->getEncodableWordTokens($input); - foreach ($tokens as $token) { - // See RFC 2822, Sect 2.2 (really 2.2 ??) - if ($this->tokenNeedsEncoding($token)) { - // Don't encode starting WSP - $firstChar = substr($token, 0, 1); - switch ($firstChar) { - case ' ': - case "\t": - $value .= $firstChar; - $token = substr($token, 1); - } + foreach ($tokens as $token) { + // See RFC 2822, Sect 2.2 (really 2.2 ??) + if ($this->tokenNeedsEncoding($token)) { + // Don't encode starting WSP + $firstChar = substr($token, 0, 1); + switch ($firstChar) { + case ' ': + case "\t": + $value .= $firstChar; + $token = substr($token, 1); + } - if (-1 == $usedLength) { - $usedLength = \strlen($header->getFieldName().': ') + \strlen($value); - } - $value .= $this->getTokenAsEncodedWord($token, $usedLength); + if (-1 == $usedLength) { + $usedLength = \strlen($header->getFieldName().': ') + \strlen($value); + } + $value .= $this->getTokenAsEncodedWord($token, $usedLength); - $header->setMaxLineLength(76); // Forcefully override - } else { - $value .= $token; - } - } + $header->setMaxLineLength(76); // Forcefully override + } else { + $value .= $token; + } + } - return $value; - } + return $value; + } - /** - * Test if a token needs to be encoded or not. - * - * @param string $token - * - * @return bool - */ - protected function tokenNeedsEncoding($token) - { - return preg_match('~[\x00-\x08\x10-\x19\x7F-\xFF\r\n]~', $token); - } + /** + * Test if a token needs to be encoded or not. + * + * @param string $token + * + * @return bool + */ + protected function tokenNeedsEncoding($token) + { + return preg_match('~[\x00-\x08\x10-\x19\x7F-\xFF\r\n]~', $token); + } - /** - * Splits a string into tokens in blocks of words which can be encoded quickly. - * - * @param string $string - * - * @return string[] - */ - protected function getEncodableWordTokens($string) - { - $tokens = []; + /** + * Splits a string into tokens in blocks of words which can be encoded quickly. + * + * @param string $string + * + * @return string[] + */ + protected function getEncodableWordTokens($string) + { + $tokens = []; - $encodedToken = ''; - // Split at all whitespace boundaries - foreach (preg_split('~(?=[\t ])~', $string ?? '') as $token) { - if ($this->tokenNeedsEncoding($token)) { - $encodedToken .= $token; - } else { - if (\strlen($encodedToken) > 0) { - $tokens[] = $encodedToken; - $encodedToken = ''; - } - $tokens[] = $token; - } - } - if (\strlen($encodedToken)) { - $tokens[] = $encodedToken; - } + $encodedToken = ''; + // Split at all whitespace boundaries + foreach (preg_split('~(?=[\t ])~', $string ?? '') as $token) { + if ($this->tokenNeedsEncoding($token)) { + $encodedToken .= $token; + } else { + if (\strlen($encodedToken) > 0) { + $tokens[] = $encodedToken; + $encodedToken = ''; + } + $tokens[] = $token; + } + } + if (\strlen($encodedToken)) { + $tokens[] = $encodedToken; + } - return $tokens; - } + return $tokens; + } - /** - * Get a token as an encoded word for safe insertion into headers. - * - * @param string $token token to encode - * @param int $firstLineOffset optional - * - * @return string - */ - protected function getTokenAsEncodedWord($token, $firstLineOffset = 0) - { - // Adjust $firstLineOffset to account for space needed for syntax - $charsetDecl = $this->charset; - if (isset($this->lang)) { - $charsetDecl .= '*'.$this->lang; - } - $encodingWrapperLength = \strlen( - '=?'.$charsetDecl.'?'.$this->encoder->getName().'??=' - ); + /** + * Get a token as an encoded word for safe insertion into headers. + * + * @param string $token token to encode + * @param int $firstLineOffset optional + * + * @return string + */ + protected function getTokenAsEncodedWord($token, $firstLineOffset = 0) + { + // Adjust $firstLineOffset to account for space needed for syntax + $charsetDecl = $this->charset; + if (isset($this->lang)) { + $charsetDecl .= '*'.$this->lang; + } + $encodingWrapperLength = \strlen( + '=?'.$charsetDecl.'?'.$this->encoder->getName().'??=' + ); - if ($firstLineOffset >= 75) { - //Does this logic need to be here? - $firstLineOffset = 0; - } + if ($firstLineOffset >= 75) { + //Does this logic need to be here? + $firstLineOffset = 0; + } - $encodedTextLines = explode("\r\n", - $this->encoder->encodeString( - $token, $firstLineOffset, 75 - $encodingWrapperLength, $this->charset - ) ?? '' - ); + $encodedTextLines = explode("\r\n", + $this->encoder->encodeString( + $token, $firstLineOffset, 75 - $encodingWrapperLength, $this->charset + ) ?? '' + ); - if ('iso-2022-jp' !== strtolower($this->charset ?? '')) { - // special encoding for iso-2022-jp using mb_encode_mimeheader - foreach ($encodedTextLines as $lineNum => $line) { - $encodedTextLines[$lineNum] = '=?'.$charsetDecl. - '?'.$this->encoder->getName(). - '?'.$line.'?='; - } - } + if ('iso-2022-jp' !== strtolower($this->charset ?? '')) { + // special encoding for iso-2022-jp using mb_encode_mimeheader + foreach ($encodedTextLines as $lineNum => $line) { + $encodedTextLines[$lineNum] = '=?'.$charsetDecl. + '?'.$this->encoder->getName(). + '?'.$line.'?='; + } + } - return implode("\r\n ", $encodedTextLines); - } + return implode("\r\n ", $encodedTextLines); + } - /** - * Generates tokens from the given string which include CRLF as individual tokens. - * - * @param string $token - * - * @return string[] - */ - protected function generateTokenLines($token) - { - return preg_split('~(\r\n)~', $token ?? '', -1, PREG_SPLIT_DELIM_CAPTURE); - } + /** + * Generates tokens from the given string which include CRLF as individual tokens. + * + * @param string $token + * + * @return string[] + */ + protected function generateTokenLines($token) + { + return preg_split('~(\r\n)~', $token ?? '', -1, PREG_SPLIT_DELIM_CAPTURE); + } - /** - * Set a value into the cache. - * - * @param string $value - */ - protected function setCachedValue($value) - { - $this->cachedValue = $value; - } + /** + * Set a value into the cache. + * + * @param string $value + */ + protected function setCachedValue($value) + { + $this->cachedValue = $value; + } - /** - * Get the value in the cache. - * - * @return string - */ - protected function getCachedValue() - { - return $this->cachedValue; - } + /** + * Get the value in the cache. + * + * @return string + */ + protected function getCachedValue() + { + return $this->cachedValue; + } - /** - * Clear the cached value if $condition is met. - * - * @param bool $condition - */ - protected function clearCachedValueIf($condition) - { - if ($condition) { - $this->setCachedValue(null); - } - } + /** + * Clear the cached value if $condition is met. + * + * @param bool $condition + */ + protected function clearCachedValueIf($condition) + { + if ($condition) { + $this->setCachedValue(null); + } + } - /** - * Generate a list of all tokens in the final header. - * - * @param string $string The string to tokenize - * - * @return array An array of tokens as strings - */ - protected function toTokens($string = null) - { - if (null === $string) { - $string = $this->getFieldBody(); - } + /** + * Generate a list of all tokens in the final header. + * + * @param string $string The string to tokenize + * + * @return array An array of tokens as strings + */ + protected function toTokens($string = null) + { + if (null === $string) { + $string = $this->getFieldBody(); + } - $tokens = []; + $tokens = []; - // Generate atoms; split at all invisible boundaries followed by WSP - foreach (preg_split('~(?=[ \t])~', $string ?? '') as $token) { - $newTokens = $this->generateTokenLines($token); - foreach ($newTokens as $newToken) { - $tokens[] = $newToken; - } - } + // Generate atoms; split at all invisible boundaries followed by WSP + foreach (preg_split('~(?=[ \t])~', $string ?? '') as $token) { + $newTokens = $this->generateTokenLines($token); + foreach ($newTokens as $newToken) { + $tokens[] = $newToken; + } + } - return $tokens; - } + return $tokens; + } - /** - * Takes an array of tokens which appear in the header and turns them into - * an RFC 2822 compliant string, adding FWSP where needed. - * - * @param string[] $tokens - * - * @return string - */ - private function tokensToString(array $tokens) - { - $lineCount = 0; - $headerLines = []; - $headerLines[] = $this->name.': '; - $currentLine = &$headerLines[$lineCount++]; + /** + * Takes an array of tokens which appear in the header and turns them into + * an RFC 2822 compliant string, adding FWSP where needed. + * + * @param string[] $tokens + * + * @return string + */ + private function tokensToString(array $tokens) + { + $lineCount = 0; + $headerLines = []; + $headerLines[] = $this->name.': '; + $currentLine = &$headerLines[$lineCount++]; - // Build all tokens back into compliant header - foreach ($tokens as $i => $token) { - // Line longer than specified maximum or token was just a new line - if (("\r\n" == $token) || - ($i > 0 && \strlen($currentLine.$token) > $this->lineLength) - && 0 < \strlen($currentLine)) { - $headerLines[] = ''; - $currentLine = &$headerLines[$lineCount++]; - } + // Build all tokens back into compliant header + foreach ($tokens as $i => $token) { + // Line longer than specified maximum or token was just a new line + if (("\r\n" == $token) || + ($i > 0 && \strlen($currentLine.$token) > $this->lineLength) + && 0 < \strlen($currentLine)) { + $headerLines[] = ''; + $currentLine = &$headerLines[$lineCount++]; + } - // Append token to the line - if ("\r\n" != $token) { - $currentLine .= $token; - } - } + // Append token to the line + if ("\r\n" != $token) { + $currentLine .= $token; + } + } - // Implode with FWS (RFC 2822, 2.2.3) - return implode("\r\n", $headerLines)."\r\n"; - } + // Implode with FWS (RFC 2822, 2.2.3) + return implode("\r\n", $headerLines)."\r\n"; + } - /** - * Make a deep copy of object. - */ - public function __clone() - { - if ($this->encoder) { - $this->encoder = clone $this->encoder; - } - } + /** + * Make a deep copy of object. + */ + public function __clone() + { + if ($this->encoder) { + $this->encoder = clone $this->encoder; + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/DateHeader.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/DateHeader.php index efe1dad6619..fb83178a8b3 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/DateHeader.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/DateHeader.php @@ -15,99 +15,99 @@ */ class Swift_Mime_Headers_DateHeader extends Swift_Mime_Headers_AbstractHeader { - /** - * Date-time value of this Header. - * - * @var DateTimeImmutable - */ - private $dateTime; + /** + * Date-time value of this Header. + * + * @var DateTimeImmutable + */ + private $dateTime; - /** - * Creates a new DateHeader with $name. - * - * @param string $name of Header - */ - public function __construct($name) - { - $this->setFieldName($name); - } + /** + * Creates a new DateHeader with $name. + * + * @param string $name of Header + */ + public function __construct($name) + { + $this->setFieldName($name); + } - /** - * Get the type of Header that this instance represents. - * - * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX - * @see TYPE_DATE, TYPE_ID, TYPE_PATH - * - * @return int - */ - public function getFieldType() - { - return self::TYPE_DATE; - } + /** + * Get the type of Header that this instance represents. + * + * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX + * @see TYPE_DATE, TYPE_ID, TYPE_PATH + * + * @return int + */ + public function getFieldType() + { + return self::TYPE_DATE; + } - /** - * Set the model for the field body. - * - * @param DateTimeInterface $model - */ - public function setFieldBodyModel($model) - { - $this->setDateTime($model); - } + /** + * Set the model for the field body. + * + * @param DateTimeInterface $model + */ + public function setFieldBodyModel($model) + { + $this->setDateTime($model); + } - /** - * Get the model for the field body. - * - * @return DateTimeImmutable - */ - public function getFieldBodyModel() - { - return $this->getDateTime(); - } + /** + * Get the model for the field body. + * + * @return DateTimeImmutable + */ + public function getFieldBodyModel() + { + return $this->getDateTime(); + } - /** - * Get the date-time representing the Date in this Header. - * - * @return DateTimeImmutable - */ - public function getDateTime() - { - return $this->dateTime; - } + /** + * Get the date-time representing the Date in this Header. + * + * @return DateTimeImmutable + */ + public function getDateTime() + { + return $this->dateTime; + } - /** - * Set the date-time of the Date in this Header. - * - * If a DateTime instance is provided, it is converted to DateTimeImmutable. - */ - public function setDateTime(DateTimeInterface $dateTime) - { - $this->clearCachedValueIf($this->getCachedValue() != $dateTime->format(DateTime::RFC2822)); - if ($dateTime instanceof DateTime) { - $immutable = new DateTimeImmutable('@'.$dateTime->getTimestamp()); - $dateTime = $immutable->setTimezone($dateTime->getTimezone()); - } - $this->dateTime = $dateTime; - } + /** + * Set the date-time of the Date in this Header. + * + * If a DateTime instance is provided, it is converted to DateTimeImmutable. + */ + public function setDateTime(DateTimeInterface $dateTime) + { + $this->clearCachedValueIf($this->getCachedValue() != $dateTime->format(DateTime::RFC2822)); + if ($dateTime instanceof DateTime) { + $immutable = new DateTimeImmutable('@'.$dateTime->getTimestamp()); + $dateTime = $immutable->setTimezone($dateTime->getTimezone()); + } + $this->dateTime = $dateTime; + } - /** - * Get the string value of the body in this Header. - * - * This is not necessarily RFC 2822 compliant since folding white space will - * not be added at this stage (see {@link toString()} for that). - * - * @see toString() - * - * @return string - */ - public function getFieldBody() - { - if (!$this->getCachedValue()) { - if (isset($this->dateTime)) { - $this->setCachedValue($this->dateTime->format(DateTime::RFC2822)); - } - } + /** + * Get the string value of the body in this Header. + * + * This is not necessarily RFC 2822 compliant since folding white space will + * not be added at this stage (see {@link toString()} for that). + * + * @see toString() + * + * @return string + */ + public function getFieldBody() + { + if (!$this->getCachedValue()) { + if (isset($this->dateTime)) { + $this->setCachedValue($this->dateTime->format(DateTime::RFC2822)); + } + } - return $this->getCachedValue(); - } + return $this->getCachedValue(); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/IdentificationHeader.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/IdentificationHeader.php index 4fcdff418a7..cec31c83961 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/IdentificationHeader.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/IdentificationHeader.php @@ -19,171 +19,171 @@ use Egulias\EmailValidator\Validation\RFCValidation; */ class Swift_Mime_Headers_IdentificationHeader extends Swift_Mime_Headers_AbstractHeader { - /** - * The IDs used in the value of this Header. - * - * This may hold multiple IDs or just a single ID. - * - * @var string[] - */ - private $ids = []; + /** + * The IDs used in the value of this Header. + * + * This may hold multiple IDs or just a single ID. + * + * @var string[] + */ + private $ids = []; - /** - * The strict EmailValidator. - * - * @var EmailValidator - */ - private $emailValidator; + /** + * The strict EmailValidator. + * + * @var EmailValidator + */ + private $emailValidator; - private $addressEncoder; + private $addressEncoder; - /** - * Creates a new IdentificationHeader with the given $name and $id. - * - * @param string $name - */ - public function __construct($name, EmailValidator $emailValidator, Swift_AddressEncoder $addressEncoder = null) - { - $this->setFieldName($name); - $this->emailValidator = $emailValidator; - $this->addressEncoder = $addressEncoder ?? new Swift_AddressEncoder_IdnAddressEncoder(); - } + /** + * Creates a new IdentificationHeader with the given $name and $id. + * + * @param string $name + */ + public function __construct($name, EmailValidator $emailValidator, Swift_AddressEncoder $addressEncoder = null) + { + $this->setFieldName($name); + $this->emailValidator = $emailValidator; + $this->addressEncoder = $addressEncoder ?? new Swift_AddressEncoder_IdnAddressEncoder(); + } - /** - * Get the type of Header that this instance represents. - * - * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX - * @see TYPE_DATE, TYPE_ID, TYPE_PATH - * - * @return int - */ - public function getFieldType() - { - return self::TYPE_ID; - } + /** + * Get the type of Header that this instance represents. + * + * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX + * @see TYPE_DATE, TYPE_ID, TYPE_PATH + * + * @return int + */ + public function getFieldType() + { + return self::TYPE_ID; + } - /** - * Set the model for the field body. - * - * This method takes a string ID, or an array of IDs. - * - * @param mixed $model - * - * @throws Swift_RfcComplianceException - */ - public function setFieldBodyModel($model) - { - $this->setId($model); - } + /** + * Set the model for the field body. + * + * This method takes a string ID, or an array of IDs. + * + * @param mixed $model + * + * @throws Swift_RfcComplianceException + */ + public function setFieldBodyModel($model) + { + $this->setId($model); + } - /** - * Get the model for the field body. - * - * This method returns an array of IDs - * - * @return array - */ - public function getFieldBodyModel() - { - return $this->getIds(); - } + /** + * Get the model for the field body. + * + * This method returns an array of IDs + * + * @return array + */ + public function getFieldBodyModel() + { + return $this->getIds(); + } - /** - * Set the ID used in the value of this header. - * - * @param string|array $id - * - * @throws Swift_RfcComplianceException - */ - public function setId($id) - { - $this->setIds(\is_array($id) ? $id : [$id]); - } + /** + * Set the ID used in the value of this header. + * + * @param string|array $id + * + * @throws Swift_RfcComplianceException + */ + public function setId($id) + { + $this->setIds(\is_array($id) ? $id : [$id]); + } - /** - * Get the ID used in the value of this Header. - * - * If multiple IDs are set only the first is returned. - * - * @return string - */ - public function getId() - { - if (\count($this->ids) > 0) { - return $this->ids[0]; - } - } + /** + * Get the ID used in the value of this Header. + * + * If multiple IDs are set only the first is returned. + * + * @return string + */ + public function getId() + { + if (\count($this->ids) > 0) { + return $this->ids[0]; + } + } - /** - * Set a collection of IDs to use in the value of this Header. - * - * @param string[] $ids - * - * @throws Swift_RfcComplianceException - */ - public function setIds(array $ids) - { - $actualIds = []; + /** + * Set a collection of IDs to use in the value of this Header. + * + * @param string[] $ids + * + * @throws Swift_RfcComplianceException + */ + public function setIds(array $ids) + { + $actualIds = []; - foreach ($ids as $id) { - $this->assertValidId($id); - $actualIds[] = $id; - } + foreach ($ids as $id) { + $this->assertValidId($id); + $actualIds[] = $id; + } - $this->clearCachedValueIf($this->ids != $actualIds); - $this->ids = $actualIds; - } + $this->clearCachedValueIf($this->ids != $actualIds); + $this->ids = $actualIds; + } - /** - * Get the list of IDs used in this Header. - * - * @return string[] - */ - public function getIds() - { - return $this->ids; - } + /** + * Get the list of IDs used in this Header. + * + * @return string[] + */ + public function getIds() + { + return $this->ids; + } - /** - * Get the string value of the body in this Header. - * - * This is not necessarily RFC 2822 compliant since folding white space will - * not be added at this stage (see {@see toString()} for that). - * - * @see toString() - * - * @throws Swift_RfcComplianceException - * - * @return string - */ - public function getFieldBody() - { - if (!$this->getCachedValue()) { - $angleAddrs = []; + /** + * Get the string value of the body in this Header. + * + * This is not necessarily RFC 2822 compliant since folding white space will + * not be added at this stage (see {@see toString()} for that). + * + * @see toString() + * + * @throws Swift_RfcComplianceException + * + * @return string + */ + public function getFieldBody() + { + if (!$this->getCachedValue()) { + $angleAddrs = []; - foreach ($this->ids as $id) { - $angleAddrs[] = '<'.$this->addressEncoder->encodeString($id).'>'; - } + foreach ($this->ids as $id) { + $angleAddrs[] = '<'.$this->addressEncoder->encodeString($id).'>'; + } - $this->setCachedValue(implode(' ', $angleAddrs)); - } + $this->setCachedValue(implode(' ', $angleAddrs)); + } - return $this->getCachedValue(); - } + return $this->getCachedValue(); + } - /** - * Throws an Exception if the id passed does not comply with RFC 2822. - * - * @param string $id - * - * @throws Swift_RfcComplianceException - */ - private function assertValidId($id) - { - $emailValidation = class_exists(MessageIDValidation::class) ? new MessageIDValidation() : new RFCValidation(); + /** + * Throws an Exception if the id passed does not comply with RFC 2822. + * + * @param string $id + * + * @throws Swift_RfcComplianceException + */ + private function assertValidId($id) + { + $emailValidation = class_exists(MessageIDValidation::class) ? new MessageIDValidation() : new RFCValidation(); - if (!$this->emailValidator->isValid($id, $emailValidation)) { - throw new Swift_RfcComplianceException('Invalid ID given <'.$id.'>'); - } - } + if (!$this->emailValidator->isValid($id, $emailValidation)) { + throw new Swift_RfcComplianceException('Invalid ID given <'.$id.'>'); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/MailboxHeader.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/MailboxHeader.php index ddd5e8cffb1..febc31332dd 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/MailboxHeader.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/MailboxHeader.php @@ -18,341 +18,341 @@ use Egulias\EmailValidator\Validation\RFCValidation; */ class Swift_Mime_Headers_MailboxHeader extends Swift_Mime_Headers_AbstractHeader { - /** - * The mailboxes used in this Header. - * - * @var string[] - */ - private $mailboxes = []; + /** + * The mailboxes used in this Header. + * + * @var string[] + */ + private $mailboxes = []; - /** - * The strict EmailValidator. - * - * @var EmailValidator - */ - private $emailValidator; + /** + * The strict EmailValidator. + * + * @var EmailValidator + */ + private $emailValidator; - private $addressEncoder; + private $addressEncoder; - /** - * Creates a new MailboxHeader with $name. - * - * @param string $name of Header - */ - public function __construct($name, Swift_Mime_HeaderEncoder $encoder, EmailValidator $emailValidator, Swift_AddressEncoder $addressEncoder = null) - { - $this->setFieldName($name); - $this->setEncoder($encoder); - $this->emailValidator = $emailValidator; - $this->addressEncoder = $addressEncoder ?? new Swift_AddressEncoder_IdnAddressEncoder(); - } + /** + * Creates a new MailboxHeader with $name. + * + * @param string $name of Header + */ + public function __construct($name, Swift_Mime_HeaderEncoder $encoder, EmailValidator $emailValidator, Swift_AddressEncoder $addressEncoder = null) + { + $this->setFieldName($name); + $this->setEncoder($encoder); + $this->emailValidator = $emailValidator; + $this->addressEncoder = $addressEncoder ?? new Swift_AddressEncoder_IdnAddressEncoder(); + } - /** - * Get the type of Header that this instance represents. - * - * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX - * @see TYPE_DATE, TYPE_ID, TYPE_PATH - * - * @return int - */ - public function getFieldType() - { - return self::TYPE_MAILBOX; - } + /** + * Get the type of Header that this instance represents. + * + * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX + * @see TYPE_DATE, TYPE_ID, TYPE_PATH + * + * @return int + */ + public function getFieldType() + { + return self::TYPE_MAILBOX; + } - /** - * Set the model for the field body. - * - * This method takes a string, or an array of addresses. - * - * @param mixed $model - * - * @throws Swift_RfcComplianceException - */ - public function setFieldBodyModel($model) - { - $this->setNameAddresses($model); - } + /** + * Set the model for the field body. + * + * This method takes a string, or an array of addresses. + * + * @param mixed $model + * + * @throws Swift_RfcComplianceException + */ + public function setFieldBodyModel($model) + { + $this->setNameAddresses($model); + } - /** - * Get the model for the field body. - * - * This method returns an associative array like {@link getNameAddresses()} - * - * @throws Swift_RfcComplianceException - * - * @return array - */ - public function getFieldBodyModel() - { - return $this->getNameAddresses(); - } + /** + * Get the model for the field body. + * + * This method returns an associative array like {@link getNameAddresses()} + * + * @throws Swift_RfcComplianceException + * + * @return array + */ + public function getFieldBodyModel() + { + return $this->getNameAddresses(); + } - /** - * Set a list of mailboxes to be shown in this Header. - * - * The mailboxes can be a simple array of addresses, or an array of - * key=>value pairs where (email => personalName). - * Example: - * - * setNameAddresses(array( - * 'chris@swiftmailer.org' => 'Chris Corbyn', - * 'mark@swiftmailer.org' //No associated personal name - * )); - * ?> - * - * - * @see __construct() - * @see setAddresses() - * @see setValue() - * - * @param string|string[] $mailboxes - * - * @throws Swift_RfcComplianceException - */ - public function setNameAddresses($mailboxes) - { - $this->mailboxes = $this->normalizeMailboxes((array) $mailboxes); - $this->setCachedValue(null); //Clear any cached value - } + /** + * Set a list of mailboxes to be shown in this Header. + * + * The mailboxes can be a simple array of addresses, or an array of + * key=>value pairs where (email => personalName). + * Example: + * + * setNameAddresses(array( + * 'chris@swiftmailer.org' => 'Chris Corbyn', + * 'mark@swiftmailer.org' //No associated personal name + * )); + * ?> + * + * + * @see __construct() + * @see setAddresses() + * @see setValue() + * + * @param string|string[] $mailboxes + * + * @throws Swift_RfcComplianceException + */ + public function setNameAddresses($mailboxes) + { + $this->mailboxes = $this->normalizeMailboxes((array) $mailboxes); + $this->setCachedValue(null); //Clear any cached value + } - /** - * Get the full mailbox list of this Header as an array of valid RFC 2822 strings. - * - * Example: - * - * 'Chris Corbyn', - * 'mark@swiftmailer.org' => 'Mark Corbyn') - * ); - * print_r($header->getNameAddressStrings()); - * // array ( - * // 0 => Chris Corbyn , - * // 1 => Mark Corbyn - * // ) - * ?> - * - * - * @see getNameAddresses() - * @see toString() - * - * @throws Swift_RfcComplianceException - * - * @return string[] - */ - public function getNameAddressStrings() - { - return $this->createNameAddressStrings($this->getNameAddresses()); - } + /** + * Get the full mailbox list of this Header as an array of valid RFC 2822 strings. + * + * Example: + * + * 'Chris Corbyn', + * 'mark@swiftmailer.org' => 'Mark Corbyn') + * ); + * print_r($header->getNameAddressStrings()); + * // array ( + * // 0 => Chris Corbyn , + * // 1 => Mark Corbyn + * // ) + * ?> + * + * + * @see getNameAddresses() + * @see toString() + * + * @throws Swift_RfcComplianceException + * + * @return string[] + */ + public function getNameAddressStrings() + { + return $this->createNameAddressStrings($this->getNameAddresses()); + } - /** - * Get all mailboxes in this Header as key=>value pairs. - * - * The key is the address and the value is the name (or null if none set). - * Example: - * - * 'Chris Corbyn', - * 'mark@swiftmailer.org' => 'Mark Corbyn') - * ); - * print_r($header->getNameAddresses()); - * // array ( - * // chris@swiftmailer.org => Chris Corbyn, - * // mark@swiftmailer.org => Mark Corbyn - * // ) - * ?> - * - * - * @see getAddresses() - * @see getNameAddressStrings() - * - * @return string[] - */ - public function getNameAddresses() - { - return $this->mailboxes; - } + /** + * Get all mailboxes in this Header as key=>value pairs. + * + * The key is the address and the value is the name (or null if none set). + * Example: + * + * 'Chris Corbyn', + * 'mark@swiftmailer.org' => 'Mark Corbyn') + * ); + * print_r($header->getNameAddresses()); + * // array ( + * // chris@swiftmailer.org => Chris Corbyn, + * // mark@swiftmailer.org => Mark Corbyn + * // ) + * ?> + * + * + * @see getAddresses() + * @see getNameAddressStrings() + * + * @return string[] + */ + public function getNameAddresses() + { + return $this->mailboxes; + } - /** - * Makes this Header represent a list of plain email addresses with no names. - * - * Example: - * - * setAddresses( - * array('one@domain.tld', 'two@domain.tld', 'three@domain.tld') - * ); - * ?> - * - * - * @see setNameAddresses() - * @see setValue() - * - * @param string[] $addresses - * - * @throws Swift_RfcComplianceException - */ - public function setAddresses($addresses) - { - $this->setNameAddresses(array_values((array) $addresses)); - } + /** + * Makes this Header represent a list of plain email addresses with no names. + * + * Example: + * + * setAddresses( + * array('one@domain.tld', 'two@domain.tld', 'three@domain.tld') + * ); + * ?> + * + * + * @see setNameAddresses() + * @see setValue() + * + * @param string[] $addresses + * + * @throws Swift_RfcComplianceException + */ + public function setAddresses($addresses) + { + $this->setNameAddresses(array_values((array) $addresses)); + } - /** - * Get all email addresses in this Header. - * - * @see getNameAddresses() - * - * @return string[] - */ - public function getAddresses() - { - return array_keys($this->mailboxes); - } + /** + * Get all email addresses in this Header. + * + * @see getNameAddresses() + * + * @return string[] + */ + public function getAddresses() + { + return array_keys($this->mailboxes); + } - /** - * Remove one or more addresses from this Header. - * - * @param string|string[] $addresses - */ - public function removeAddresses($addresses) - { - $this->setCachedValue(null); - foreach ((array) $addresses as $address) { - unset($this->mailboxes[$address]); - } - } + /** + * Remove one or more addresses from this Header. + * + * @param string|string[] $addresses + */ + public function removeAddresses($addresses) + { + $this->setCachedValue(null); + foreach ((array) $addresses as $address) { + unset($this->mailboxes[$address]); + } + } - /** - * Get the string value of the body in this Header. - * - * This is not necessarily RFC 2822 compliant since folding white space will - * not be added at this stage (see {@link toString()} for that). - * - * @see toString() - * - * @throws Swift_RfcComplianceException - * - * @return string - */ - public function getFieldBody() - { - // Compute the string value of the header only if needed - if (null === $this->getCachedValue()) { - $this->setCachedValue($this->createMailboxListString($this->mailboxes)); - } + /** + * Get the string value of the body in this Header. + * + * This is not necessarily RFC 2822 compliant since folding white space will + * not be added at this stage (see {@link toString()} for that). + * + * @see toString() + * + * @throws Swift_RfcComplianceException + * + * @return string + */ + public function getFieldBody() + { + // Compute the string value of the header only if needed + if (null === $this->getCachedValue()) { + $this->setCachedValue($this->createMailboxListString($this->mailboxes)); + } - return $this->getCachedValue(); - } + return $this->getCachedValue(); + } - /** - * Normalizes a user-input list of mailboxes into consistent key=>value pairs. - * - * @param string[] $mailboxes - * - * @return string[] - */ - protected function normalizeMailboxes(array $mailboxes) - { - $actualMailboxes = []; + /** + * Normalizes a user-input list of mailboxes into consistent key=>value pairs. + * + * @param string[] $mailboxes + * + * @return string[] + */ + protected function normalizeMailboxes(array $mailboxes) + { + $actualMailboxes = []; - foreach ($mailboxes as $key => $value) { - if (\is_string($key)) { - //key is email addr - $address = $key; - $name = $value; - } else { - $address = $value; - $name = null; - } - $this->assertValidAddress($address); - $actualMailboxes[$address] = $name; - } + foreach ($mailboxes as $key => $value) { + if (\is_string($key)) { + //key is email addr + $address = $key; + $name = $value; + } else { + $address = $value; + $name = null; + } + $this->assertValidAddress($address); + $actualMailboxes[$address] = $name; + } - return $actualMailboxes; - } + return $actualMailboxes; + } - /** - * Produces a compliant, formatted display-name based on the string given. - * - * @param string $displayName as displayed - * @param bool $shorten the first line to make remove for header name - * - * @return string - */ - protected function createDisplayNameString($displayName, $shorten = false) - { - return $this->createPhrase($this, $displayName, $this->getCharset(), $this->getEncoder(), $shorten); - } + /** + * Produces a compliant, formatted display-name based on the string given. + * + * @param string $displayName as displayed + * @param bool $shorten the first line to make remove for header name + * + * @return string + */ + protected function createDisplayNameString($displayName, $shorten = false) + { + return $this->createPhrase($this, $displayName, $this->getCharset(), $this->getEncoder(), $shorten); + } - /** - * Creates a string form of all the mailboxes in the passed array. - * - * @param string[] $mailboxes - * - * @throws Swift_RfcComplianceException - * - * @return string - */ - protected function createMailboxListString(array $mailboxes) - { - return implode(', ', $this->createNameAddressStrings($mailboxes)); - } + /** + * Creates a string form of all the mailboxes in the passed array. + * + * @param string[] $mailboxes + * + * @throws Swift_RfcComplianceException + * + * @return string + */ + protected function createMailboxListString(array $mailboxes) + { + return implode(', ', $this->createNameAddressStrings($mailboxes)); + } - /** - * Redefine the encoding requirements for mailboxes. - * - * All "specials" must be encoded as the full header value will not be quoted - * - * @see RFC 2822 3.2.1 - * - * @param string $token - * - * @return bool - */ - protected function tokenNeedsEncoding($token) - { - return preg_match('/[()<>\[\]:;@\,."]/', $token) || parent::tokenNeedsEncoding($token); - } + /** + * Redefine the encoding requirements for mailboxes. + * + * All "specials" must be encoded as the full header value will not be quoted + * + * @see RFC 2822 3.2.1 + * + * @param string $token + * + * @return bool + */ + protected function tokenNeedsEncoding($token) + { + return preg_match('/[()<>\[\]:;@\,."]/', $token) || parent::tokenNeedsEncoding($token); + } - /** - * Return an array of strings conforming the the name-addr spec of RFC 2822. - * - * @param string[] $mailboxes - * - * @return string[] - */ - private function createNameAddressStrings(array $mailboxes) - { - $strings = []; + /** + * Return an array of strings conforming the the name-addr spec of RFC 2822. + * + * @param string[] $mailboxes + * + * @return string[] + */ + private function createNameAddressStrings(array $mailboxes) + { + $strings = []; - foreach ($mailboxes as $email => $name) { - $mailboxStr = $this->addressEncoder->encodeString($email); - if (null !== $name) { - $nameStr = $this->createDisplayNameString($name, empty($strings)); - $mailboxStr = $nameStr.' <'.$mailboxStr.'>'; - } - $strings[] = $mailboxStr; - } + foreach ($mailboxes as $email => $name) { + $mailboxStr = $this->addressEncoder->encodeString($email); + if (null !== $name) { + $nameStr = $this->createDisplayNameString($name, empty($strings)); + $mailboxStr = $nameStr.' <'.$mailboxStr.'>'; + } + $strings[] = $mailboxStr; + } - return $strings; - } + return $strings; + } - /** - * Throws an Exception if the address passed does not comply with RFC 2822. - * - * @param string $address - * - * @throws Swift_RfcComplianceException if invalid - */ - private function assertValidAddress($address) - { - if (!$this->emailValidator->isValid($address, new RFCValidation())) { - throw new Swift_RfcComplianceException('Address in mailbox given ['.$address.'] does not comply with RFC 2822, 3.6.2.'); - } - } + /** + * Throws an Exception if the address passed does not comply with RFC 2822. + * + * @param string $address + * + * @throws Swift_RfcComplianceException if invalid + */ + private function assertValidAddress($address) + { + if (!$this->emailValidator->isValid($address, new RFCValidation())) { + throw new Swift_RfcComplianceException('Address in mailbox given ['.$address.'] does not comply with RFC 2822, 3.6.2.'); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/OpenDKIMHeader.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/OpenDKIMHeader.php index fafb5bae21f..d0cb3504a97 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/OpenDKIMHeader.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/OpenDKIMHeader.php @@ -17,119 +17,119 @@ */ class Swift_Mime_Headers_OpenDKIMHeader implements Swift_Mime_Header { - /** - * The value of this Header. - * - * @var string - */ - private $value; + /** + * The value of this Header. + * + * @var string + */ + private $value; - /** - * The name of this Header. - * - * @var string - */ - private $fieldName; + /** + * The name of this Header. + * + * @var string + */ + private $fieldName; - /** - * @param string $name - */ - public function __construct($name) - { - $this->fieldName = $name; - } + /** + * @param string $name + */ + public function __construct($name) + { + $this->fieldName = $name; + } - /** - * Get the type of Header that this instance represents. - * - * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX - * @see TYPE_DATE, TYPE_ID, TYPE_PATH - * - * @return int - */ - public function getFieldType() - { - return self::TYPE_TEXT; - } + /** + * Get the type of Header that this instance represents. + * + * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX + * @see TYPE_DATE, TYPE_ID, TYPE_PATH + * + * @return int + */ + public function getFieldType() + { + return self::TYPE_TEXT; + } - /** - * Set the model for the field body. - * - * This method takes a string for the field value. - * - * @param string $model - */ - public function setFieldBodyModel($model) - { - $this->setValue($model); - } + /** + * Set the model for the field body. + * + * This method takes a string for the field value. + * + * @param string $model + */ + public function setFieldBodyModel($model) + { + $this->setValue($model); + } - /** - * Get the model for the field body. - * - * This method returns a string. - * - * @return string - */ - public function getFieldBodyModel() - { - return $this->getValue(); - } + /** + * Get the model for the field body. + * + * This method returns a string. + * + * @return string + */ + public function getFieldBodyModel() + { + return $this->getValue(); + } - /** - * Get the (unencoded) value of this header. - * - * @return string - */ - public function getValue() - { - return $this->value; - } + /** + * Get the (unencoded) value of this header. + * + * @return string + */ + public function getValue() + { + return $this->value; + } - /** - * Set the (unencoded) value of this header. - * - * @param string $value - */ - public function setValue($value) - { - $this->value = $value; - } + /** + * Set the (unencoded) value of this header. + * + * @param string $value + */ + public function setValue($value) + { + $this->value = $value; + } - /** - * Get the value of this header prepared for rendering. - * - * @return string - */ - public function getFieldBody() - { - return $this->value; - } + /** + * Get the value of this header prepared for rendering. + * + * @return string + */ + public function getFieldBody() + { + return $this->value; + } - /** - * Get this Header rendered as a RFC 2822 compliant string. - * - * @return string - */ - public function toString() - { - return $this->fieldName.': '.$this->value."\r\n"; - } + /** + * Get this Header rendered as a RFC 2822 compliant string. + * + * @return string + */ + public function toString() + { + return $this->fieldName.': '.$this->value."\r\n"; + } - /** - * Set the Header FieldName. - * - * @see Swift_Mime_Header::getFieldName() - */ - public function getFieldName() - { - return $this->fieldName; - } + /** + * Set the Header FieldName. + * + * @see Swift_Mime_Header::getFieldName() + */ + public function getFieldName() + { + return $this->fieldName; + } - /** - * Ignored. - */ - public function setCharset($charset) - { - } + /** + * Ignored. + */ + public function setCharset($charset) + { + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/ParameterizedHeader.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/ParameterizedHeader.php index 47c15e6c05f..6cd26a26465 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/ParameterizedHeader.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/ParameterizedHeader.php @@ -15,241 +15,241 @@ */ class Swift_Mime_Headers_ParameterizedHeader extends Swift_Mime_Headers_UnstructuredHeader { - /** - * RFC 2231's definition of a token. - * - * @var string - */ - const TOKEN_REGEX = '(?:[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E]+)'; + /** + * RFC 2231's definition of a token. + * + * @var string + */ + const TOKEN_REGEX = '(?:[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E]+)'; - /** - * The Encoder used to encode the parameters. - * - * @var Swift_Encoder - */ - private $paramEncoder; + /** + * The Encoder used to encode the parameters. + * + * @var Swift_Encoder + */ + private $paramEncoder; - /** - * The parameters as an associative array. - * - * @var string[] - */ - private $params = []; + /** + * The parameters as an associative array. + * + * @var string[] + */ + private $params = []; - /** - * Creates a new ParameterizedHeader with $name. - * - * @param string $name - */ - public function __construct($name, Swift_Mime_HeaderEncoder $encoder, Swift_Encoder $paramEncoder = null) - { - parent::__construct($name, $encoder); - $this->paramEncoder = $paramEncoder; - } + /** + * Creates a new ParameterizedHeader with $name. + * + * @param string $name + */ + public function __construct($name, Swift_Mime_HeaderEncoder $encoder, Swift_Encoder $paramEncoder = null) + { + parent::__construct($name, $encoder); + $this->paramEncoder = $paramEncoder; + } - /** - * Get the type of Header that this instance represents. - * - * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX - * @see TYPE_DATE, TYPE_ID, TYPE_PATH - * - * @return int - */ - public function getFieldType() - { - return self::TYPE_PARAMETERIZED; - } + /** + * Get the type of Header that this instance represents. + * + * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX + * @see TYPE_DATE, TYPE_ID, TYPE_PATH + * + * @return int + */ + public function getFieldType() + { + return self::TYPE_PARAMETERIZED; + } - /** - * Set the character set used in this Header. - * - * @param string $charset - */ - public function setCharset($charset) - { - parent::setCharset($charset); - if (isset($this->paramEncoder)) { - $this->paramEncoder->charsetChanged($charset); - } - } + /** + * Set the character set used in this Header. + * + * @param string $charset + */ + public function setCharset($charset) + { + parent::setCharset($charset); + if (isset($this->paramEncoder)) { + $this->paramEncoder->charsetChanged($charset); + } + } - /** - * Set the value of $parameter. - * - * @param string $parameter - * @param string $value - */ - public function setParameter($parameter, $value) - { - $this->setParameters(array_merge($this->getParameters(), [$parameter => $value])); - } + /** + * Set the value of $parameter. + * + * @param string $parameter + * @param string $value + */ + public function setParameter($parameter, $value) + { + $this->setParameters(array_merge($this->getParameters(), [$parameter => $value])); + } - /** - * Get the value of $parameter. - * - * @param string $parameter - * - * @return string - */ - public function getParameter($parameter) - { - $params = $this->getParameters(); + /** + * Get the value of $parameter. + * + * @param string $parameter + * + * @return string + */ + public function getParameter($parameter) + { + $params = $this->getParameters(); - return $params[$parameter] ?? null; - } + return $params[$parameter] ?? null; + } - /** - * Set an associative array of parameter names mapped to values. - * - * @param string[] $parameters - */ - public function setParameters(array $parameters) - { - $this->clearCachedValueIf($this->params != $parameters); - $this->params = $parameters; - } + /** + * Set an associative array of parameter names mapped to values. + * + * @param string[] $parameters + */ + public function setParameters(array $parameters) + { + $this->clearCachedValueIf($this->params != $parameters); + $this->params = $parameters; + } - /** - * Returns an associative array of parameter names mapped to values. - * - * @return string[] - */ - public function getParameters() - { - return $this->params; - } + /** + * Returns an associative array of parameter names mapped to values. + * + * @return string[] + */ + public function getParameters() + { + return $this->params; + } - /** - * Get the value of this header prepared for rendering. - * - * @return string - */ - public function getFieldBody() //TODO: Check caching here - { - $body = parent::getFieldBody(); - foreach ($this->params as $name => $value) { - if (null !== $value) { - // Add the parameter - $body .= '; '.$this->createParameter($name, $value); - } - } + /** + * Get the value of this header prepared for rendering. + * + * @return string + */ + public function getFieldBody() //TODO: Check caching here + { + $body = parent::getFieldBody(); + foreach ($this->params as $name => $value) { + if (null !== $value) { + // Add the parameter + $body .= '; '.$this->createParameter($name, $value); + } + } - return $body; - } + return $body; + } - /** - * Generate a list of all tokens in the final header. - * - * This doesn't need to be overridden in theory, but it is for implementation - * reasons to prevent potential breakage of attributes. - * - * @param string $string The string to tokenize - * - * @return array An array of tokens as strings - */ - protected function toTokens($string = null) - { - $tokens = parent::toTokens(parent::getFieldBody()); + /** + * Generate a list of all tokens in the final header. + * + * This doesn't need to be overridden in theory, but it is for implementation + * reasons to prevent potential breakage of attributes. + * + * @param string $string The string to tokenize + * + * @return array An array of tokens as strings + */ + protected function toTokens($string = null) + { + $tokens = parent::toTokens(parent::getFieldBody()); - // Try creating any parameters - foreach ($this->params as $name => $value) { - if (null !== $value) { - // Add the semi-colon separator - $tokens[\count($tokens) - 1] .= ';'; - $tokens = array_merge($tokens, $this->generateTokenLines( - ' '.$this->createParameter($name, $value) - )); - } - } + // Try creating any parameters + foreach ($this->params as $name => $value) { + if (null !== $value) { + // Add the semi-colon separator + $tokens[\count($tokens) - 1] .= ';'; + $tokens = array_merge($tokens, $this->generateTokenLines( + ' '.$this->createParameter($name, $value) + )); + } + } - return $tokens; - } + return $tokens; + } - /** - * Render a RFC 2047 compliant header parameter from the $name and $value. - * - * @param string $name - * @param string $value - * - * @return string - */ - private function createParameter($name, $value) - { - $origValue = $value; + /** + * Render a RFC 2047 compliant header parameter from the $name and $value. + * + * @param string $name + * @param string $value + * + * @return string + */ + private function createParameter($name, $value) + { + $origValue = $value; - $encoded = false; - // Allow room for parameter name, indices, "=" and DQUOTEs - $maxValueLength = $this->getMaxLineLength() - \strlen($name.'=*N"";') - 1; - $firstLineOffset = 0; + $encoded = false; + // Allow room for parameter name, indices, "=" and DQUOTEs + $maxValueLength = $this->getMaxLineLength() - \strlen($name.'=*N"";') - 1; + $firstLineOffset = 0; - // If it's not already a valid parameter value... - if (!preg_match('/^'.self::TOKEN_REGEX.'$/D', $value)) { - // TODO: text, or something else?? - // ... and it's not ascii - if (!preg_match('/^[\x00-\x08\x0B\x0C\x0E-\x7F]*$/D', $value)) { - $encoded = true; - // Allow space for the indices, charset and language - $maxValueLength = $this->getMaxLineLength() - \strlen($name.'*N*="";') - 1; - $firstLineOffset = \strlen( - $this->getCharset()."'".$this->getLanguage()."'" - ); - } - } + // If it's not already a valid parameter value... + if (!preg_match('/^'.self::TOKEN_REGEX.'$/D', $value)) { + // TODO: text, or something else?? + // ... and it's not ascii + if (!preg_match('/^[\x00-\x08\x0B\x0C\x0E-\x7F]*$/D', $value)) { + $encoded = true; + // Allow space for the indices, charset and language + $maxValueLength = $this->getMaxLineLength() - \strlen($name.'*N*="";') - 1; + $firstLineOffset = \strlen( + $this->getCharset()."'".$this->getLanguage()."'" + ); + } + } - // Encode if we need to - if ($encoded || \strlen($value) > $maxValueLength) { - if (isset($this->paramEncoder)) { - $value = $this->paramEncoder->encodeString( - $origValue, $firstLineOffset, $maxValueLength, $this->getCharset() - ); - } else { - // We have to go against RFC 2183/2231 in some areas for interoperability - $value = $this->getTokenAsEncodedWord($origValue); - $encoded = false; - } - } + // Encode if we need to + if ($encoded || \strlen($value) > $maxValueLength) { + if (isset($this->paramEncoder)) { + $value = $this->paramEncoder->encodeString( + $origValue, $firstLineOffset, $maxValueLength, $this->getCharset() + ); + } else { + // We have to go against RFC 2183/2231 in some areas for interoperability + $value = $this->getTokenAsEncodedWord($origValue); + $encoded = false; + } + } - $valueLines = isset($this->paramEncoder) ? explode("\r\n", $value) : [$value]; + $valueLines = isset($this->paramEncoder) ? explode("\r\n", $value) : [$value]; - // Need to add indices - if (\count($valueLines) > 1) { - $paramLines = []; - foreach ($valueLines as $i => $line) { - $paramLines[] = $name.'*'.$i. - $this->getEndOfParameterValue($line, true, 0 == $i); - } + // Need to add indices + if (\count($valueLines) > 1) { + $paramLines = []; + foreach ($valueLines as $i => $line) { + $paramLines[] = $name.'*'.$i. + $this->getEndOfParameterValue($line, true, 0 == $i); + } - return implode(";\r\n ", $paramLines); - } else { - return $name.$this->getEndOfParameterValue( - $valueLines[0], $encoded, true - ); - } - } + return implode(";\r\n ", $paramLines); + } else { + return $name.$this->getEndOfParameterValue( + $valueLines[0], $encoded, true + ); + } + } - /** - * Returns the parameter value from the "=" and beyond. - * - * @param string $value to append - * @param bool $encoded - * @param bool $firstLine - * - * @return string - */ - private function getEndOfParameterValue($value, $encoded = false, $firstLine = false) - { - if (!preg_match('/^'.self::TOKEN_REGEX.'$/D', $value)) { - $value = '"'.$value.'"'; - } - $prepend = '='; - if ($encoded) { - $prepend = '*='; - if ($firstLine) { - $prepend = '*='.$this->getCharset()."'".$this->getLanguage(). - "'"; - } - } + /** + * Returns the parameter value from the "=" and beyond. + * + * @param string $value to append + * @param bool $encoded + * @param bool $firstLine + * + * @return string + */ + private function getEndOfParameterValue($value, $encoded = false, $firstLine = false) + { + if (!preg_match('/^'.self::TOKEN_REGEX.'$/D', $value)) { + $value = '"'.$value.'"'; + } + $prepend = '='; + if ($encoded) { + $prepend = '*='; + if ($firstLine) { + $prepend = '*='.$this->getCharset()."'".$this->getLanguage(). + "'"; + } + } - return $prepend.$value; - } + return $prepend.$value; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/PathHeader.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/PathHeader.php index 81b421ee7a8..86ab1deaf50 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/PathHeader.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/PathHeader.php @@ -18,136 +18,136 @@ use Egulias\EmailValidator\Validation\RFCValidation; */ class Swift_Mime_Headers_PathHeader extends Swift_Mime_Headers_AbstractHeader { - /** - * The address in this Header (if specified). - * - * @var string - */ - private $address; + /** + * The address in this Header (if specified). + * + * @var string + */ + private $address; - /** - * The strict EmailValidator. - * - * @var EmailValidator - */ - private $emailValidator; + /** + * The strict EmailValidator. + * + * @var EmailValidator + */ + private $emailValidator; - private $addressEncoder; + private $addressEncoder; - /** - * Creates a new PathHeader with the given $name. - * - * @param string $name - */ - public function __construct($name, EmailValidator $emailValidator, Swift_AddressEncoder $addressEncoder = null) - { - $this->setFieldName($name); - $this->emailValidator = $emailValidator; - $this->addressEncoder = $addressEncoder ?? new Swift_AddressEncoder_IdnAddressEncoder(); - } + /** + * Creates a new PathHeader with the given $name. + * + * @param string $name + */ + public function __construct($name, EmailValidator $emailValidator, Swift_AddressEncoder $addressEncoder = null) + { + $this->setFieldName($name); + $this->emailValidator = $emailValidator; + $this->addressEncoder = $addressEncoder ?? new Swift_AddressEncoder_IdnAddressEncoder(); + } - /** - * Get the type of Header that this instance represents. - * - * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX - * @see TYPE_DATE, TYPE_ID, TYPE_PATH - * - * @return int - */ - public function getFieldType() - { - return self::TYPE_PATH; - } + /** + * Get the type of Header that this instance represents. + * + * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX + * @see TYPE_DATE, TYPE_ID, TYPE_PATH + * + * @return int + */ + public function getFieldType() + { + return self::TYPE_PATH; + } - /** - * Set the model for the field body. - * This method takes a string for an address. - * - * @param string $model - * - * @throws Swift_RfcComplianceException - */ - public function setFieldBodyModel($model) - { - $this->setAddress($model); - } + /** + * Set the model for the field body. + * This method takes a string for an address. + * + * @param string $model + * + * @throws Swift_RfcComplianceException + */ + public function setFieldBodyModel($model) + { + $this->setAddress($model); + } - /** - * Get the model for the field body. - * This method returns a string email address. - * - * @return mixed - */ - public function getFieldBodyModel() - { - return $this->getAddress(); - } + /** + * Get the model for the field body. + * This method returns a string email address. + * + * @return mixed + */ + public function getFieldBodyModel() + { + return $this->getAddress(); + } - /** - * Set the Address which should appear in this Header. - * - * @param string $address - * - * @throws Swift_RfcComplianceException - */ - public function setAddress($address) - { - if (null === $address) { - $this->address = null; - } elseif ('' == $address) { - $this->address = ''; - } else { - $this->assertValidAddress($address); - $this->address = $address; - } - $this->setCachedValue(null); - } + /** + * Set the Address which should appear in this Header. + * + * @param string $address + * + * @throws Swift_RfcComplianceException + */ + public function setAddress($address) + { + if (null === $address) { + $this->address = null; + } elseif ('' == $address) { + $this->address = ''; + } else { + $this->assertValidAddress($address); + $this->address = $address; + } + $this->setCachedValue(null); + } - /** - * Get the address which is used in this Header (if any). - * - * Null is returned if no address is set. - * - * @return string - */ - public function getAddress() - { - return $this->address; - } + /** + * Get the address which is used in this Header (if any). + * + * Null is returned if no address is set. + * + * @return string + */ + public function getAddress() + { + return $this->address; + } - /** - * Get the string value of the body in this Header. - * - * This is not necessarily RFC 2822 compliant since folding white space will - * not be added at this stage (see {@link toString()} for that). - * - * @see toString() - * - * @return string - */ - public function getFieldBody() - { - if (!$this->getCachedValue()) { - if (isset($this->address)) { - $address = $this->addressEncoder->encodeString($this->address); - $this->setCachedValue('<'.$address.'>'); - } - } + /** + * Get the string value of the body in this Header. + * + * This is not necessarily RFC 2822 compliant since folding white space will + * not be added at this stage (see {@link toString()} for that). + * + * @see toString() + * + * @return string + */ + public function getFieldBody() + { + if (!$this->getCachedValue()) { + if (isset($this->address)) { + $address = $this->addressEncoder->encodeString($this->address); + $this->setCachedValue('<'.$address.'>'); + } + } - return $this->getCachedValue(); - } + return $this->getCachedValue(); + } - /** - * Throws an Exception if the address passed does not comply with RFC 2822. - * - * @param string $address - * - * @throws Swift_RfcComplianceException If address is invalid - */ - private function assertValidAddress($address) - { - if (!$this->emailValidator->isValid($address, new RFCValidation())) { - throw new Swift_RfcComplianceException('Address set in PathHeader does not comply with addr-spec of RFC 2822.'); - } - } + /** + * Throws an Exception if the address passed does not comply with RFC 2822. + * + * @param string $address + * + * @throws Swift_RfcComplianceException If address is invalid + */ + private function assertValidAddress($address) + { + if (!$this->emailValidator->isValid($address, new RFCValidation())) { + throw new Swift_RfcComplianceException('Address set in PathHeader does not comply with addr-spec of RFC 2822.'); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/UnstructuredHeader.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/UnstructuredHeader.php index 64f160dec7c..7d51945aabb 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/UnstructuredHeader.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/UnstructuredHeader.php @@ -15,95 +15,95 @@ */ class Swift_Mime_Headers_UnstructuredHeader extends Swift_Mime_Headers_AbstractHeader { - /** - * The value of this Header. - * - * @var string - */ - private $value; + /** + * The value of this Header. + * + * @var string + */ + private $value; - /** - * Creates a new SimpleHeader with $name. - * - * @param string $name - */ - public function __construct($name, Swift_Mime_HeaderEncoder $encoder) - { - $this->setFieldName($name); - $this->setEncoder($encoder); - } + /** + * Creates a new SimpleHeader with $name. + * + * @param string $name + */ + public function __construct($name, Swift_Mime_HeaderEncoder $encoder) + { + $this->setFieldName($name); + $this->setEncoder($encoder); + } - /** - * Get the type of Header that this instance represents. - * - * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX - * @see TYPE_DATE, TYPE_ID, TYPE_PATH - * - * @return int - */ - public function getFieldType() - { - return self::TYPE_TEXT; - } + /** + * Get the type of Header that this instance represents. + * + * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX + * @see TYPE_DATE, TYPE_ID, TYPE_PATH + * + * @return int + */ + public function getFieldType() + { + return self::TYPE_TEXT; + } - /** - * Set the model for the field body. - * - * This method takes a string for the field value. - * - * @param string $model - */ - public function setFieldBodyModel($model) - { - $this->setValue($model); - } + /** + * Set the model for the field body. + * + * This method takes a string for the field value. + * + * @param string $model + */ + public function setFieldBodyModel($model) + { + $this->setValue($model); + } - /** - * Get the model for the field body. - * - * This method returns a string. - * - * @return string - */ - public function getFieldBodyModel() - { - return $this->getValue(); - } + /** + * Get the model for the field body. + * + * This method returns a string. + * + * @return string + */ + public function getFieldBodyModel() + { + return $this->getValue(); + } - /** - * Get the (unencoded) value of this header. - * - * @return string - */ - public function getValue() - { - return $this->value; - } + /** + * Get the (unencoded) value of this header. + * + * @return string + */ + public function getValue() + { + return $this->value; + } - /** - * Set the (unencoded) value of this header. - * - * @param string $value - */ - public function setValue($value) - { - $this->clearCachedValueIf($this->value != $value); - $this->value = $value; - } + /** + * Set the (unencoded) value of this header. + * + * @param string $value + */ + public function setValue($value) + { + $this->clearCachedValueIf($this->value != $value); + $this->value = $value; + } - /** - * Get the value of this header prepared for rendering. - * - * @return string - */ - public function getFieldBody() - { - if (!$this->getCachedValue()) { - $this->setCachedValue( - $this->encodeWords($this, $this->value) - ); - } + /** + * Get the value of this header prepared for rendering. + * + * @return string + */ + public function getFieldBody() + { + if (!$this->getCachedValue()) { + $this->setCachedValue( + $this->encodeWords($this, $this->value) + ); + } - return $this->getCachedValue(); - } + return $this->getCachedValue(); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/IdGenerator.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/IdGenerator.php index 3ce35f27c03..a8fd141a26a 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/IdGenerator.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/IdGenerator.php @@ -13,42 +13,42 @@ */ class Swift_Mime_IdGenerator implements Swift_IdGenerator { - private $idRight; + private $idRight; - /** - * @param string $idRight - */ - public function __construct($idRight) - { - $this->idRight = $idRight; - } + /** + * @param string $idRight + */ + public function __construct($idRight) + { + $this->idRight = $idRight; + } - /** - * Returns the right-hand side of the "@" used in all generated IDs. - * - * @return string - */ - public function getIdRight() - { - return $this->idRight; - } + /** + * Returns the right-hand side of the "@" used in all generated IDs. + * + * @return string + */ + public function getIdRight() + { + return $this->idRight; + } - /** - * Sets the right-hand side of the "@" to use in all generated IDs. - * - * @param string $idRight - */ - public function setIdRight($idRight) - { - $this->idRight = $idRight; - } + /** + * Sets the right-hand side of the "@" to use in all generated IDs. + * + * @param string $idRight + */ + public function setIdRight($idRight) + { + $this->idRight = $idRight; + } - /** - * @return string - */ - public function generateId() - { - // 32 hex values for the left part - return bin2hex(random_bytes(16)).'@'.$this->idRight; - } + /** + * @return string + */ + public function generateId() + { + // 32 hex values for the left part + return bin2hex(random_bytes(16)).'@'.$this->idRight; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/MimePart.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/MimePart.php index d0b2e6586b4..560f5ba64a5 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/MimePart.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/MimePart.php @@ -15,185 +15,185 @@ */ class Swift_Mime_MimePart extends Swift_Mime_SimpleMimeEntity { - /** The format parameter last specified by the user */ - protected $userFormat; + /** The format parameter last specified by the user */ + protected $userFormat; - /** The charset last specified by the user */ - protected $userCharset; + /** The charset last specified by the user */ + protected $userCharset; - /** The delsp parameter last specified by the user */ - protected $userDelSp; + /** The delsp parameter last specified by the user */ + protected $userDelSp; - /** The nesting level of this MimePart */ - private $nestingLevel = self::LEVEL_ALTERNATIVE; + /** The nesting level of this MimePart */ + private $nestingLevel = self::LEVEL_ALTERNATIVE; - /** - * Create a new MimePart with $headers, $encoder and $cache. - * - * @param string $charset - */ - public function __construct(Swift_Mime_SimpleHeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_IdGenerator $idGenerator, $charset = null) - { - parent::__construct($headers, $encoder, $cache, $idGenerator); - $this->setContentType('text/plain'); - if (null !== $charset) { - $this->setCharset($charset); - } - } + /** + * Create a new MimePart with $headers, $encoder and $cache. + * + * @param string $charset + */ + public function __construct(Swift_Mime_SimpleHeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_IdGenerator $idGenerator, $charset = null) + { + parent::__construct($headers, $encoder, $cache, $idGenerator); + $this->setContentType('text/plain'); + if (null !== $charset) { + $this->setCharset($charset); + } + } - /** - * Set the body of this entity, either as a string, or as an instance of - * {@link Swift_OutputByteStream}. - * - * @param mixed $body - * @param string $contentType optional - * @param string $charset optional - * - * @return $this - */ - public function setBody($body, $contentType = null, $charset = null) - { - if (isset($charset)) { - $this->setCharset($charset); - } - $body = $this->convertString($body); + /** + * Set the body of this entity, either as a string, or as an instance of + * {@link Swift_OutputByteStream}. + * + * @param mixed $body + * @param string $contentType optional + * @param string $charset optional + * + * @return $this + */ + public function setBody($body, $contentType = null, $charset = null) + { + if (isset($charset)) { + $this->setCharset($charset); + } + $body = $this->convertString($body); - parent::setBody($body, $contentType); + parent::setBody($body, $contentType); - return $this; - } + return $this; + } - /** - * Get the character set of this entity. - * - * @return string - */ - public function getCharset() - { - return $this->getHeaderParameter('Content-Type', 'charset'); - } + /** + * Get the character set of this entity. + * + * @return string + */ + public function getCharset() + { + return $this->getHeaderParameter('Content-Type', 'charset'); + } - /** - * Set the character set of this entity. - * - * @param string $charset - * - * @return $this - */ - public function setCharset($charset) - { - $this->setHeaderParameter('Content-Type', 'charset', $charset); - if ($charset !== $this->userCharset) { - $this->clearCache(); - } - $this->userCharset = $charset; - parent::charsetChanged($charset); + /** + * Set the character set of this entity. + * + * @param string $charset + * + * @return $this + */ + public function setCharset($charset) + { + $this->setHeaderParameter('Content-Type', 'charset', $charset); + if ($charset !== $this->userCharset) { + $this->clearCache(); + } + $this->userCharset = $charset; + parent::charsetChanged($charset); - return $this; - } + return $this; + } - /** - * Get the format of this entity (i.e. flowed or fixed). - * - * @return string - */ - public function getFormat() - { - return $this->getHeaderParameter('Content-Type', 'format'); - } + /** + * Get the format of this entity (i.e. flowed or fixed). + * + * @return string + */ + public function getFormat() + { + return $this->getHeaderParameter('Content-Type', 'format'); + } - /** - * Set the format of this entity (flowed or fixed). - * - * @param string $format - * - * @return $this - */ - public function setFormat($format) - { - $this->setHeaderParameter('Content-Type', 'format', $format); - $this->userFormat = $format; + /** + * Set the format of this entity (flowed or fixed). + * + * @param string $format + * + * @return $this + */ + public function setFormat($format) + { + $this->setHeaderParameter('Content-Type', 'format', $format); + $this->userFormat = $format; - return $this; - } + return $this; + } - /** - * Test if delsp is being used for this entity. - * - * @return bool - */ - public function getDelSp() - { - return 'yes' === $this->getHeaderParameter('Content-Type', 'delsp'); - } + /** + * Test if delsp is being used for this entity. + * + * @return bool + */ + public function getDelSp() + { + return 'yes' === $this->getHeaderParameter('Content-Type', 'delsp'); + } - /** - * Turn delsp on or off for this entity. - * - * @param bool $delsp - * - * @return $this - */ - public function setDelSp($delsp = true) - { - $this->setHeaderParameter('Content-Type', 'delsp', $delsp ? 'yes' : null); - $this->userDelSp = $delsp; + /** + * Turn delsp on or off for this entity. + * + * @param bool $delsp + * + * @return $this + */ + public function setDelSp($delsp = true) + { + $this->setHeaderParameter('Content-Type', 'delsp', $delsp ? 'yes' : null); + $this->userDelSp = $delsp; - return $this; - } + return $this; + } - /** - * Get the nesting level of this entity. - * - * @see LEVEL_TOP, LEVEL_ALTERNATIVE, LEVEL_MIXED, LEVEL_RELATED - * - * @return int - */ - public function getNestingLevel() - { - return $this->nestingLevel; - } + /** + * Get the nesting level of this entity. + * + * @see LEVEL_TOP, LEVEL_ALTERNATIVE, LEVEL_MIXED, LEVEL_RELATED + * + * @return int + */ + public function getNestingLevel() + { + return $this->nestingLevel; + } - /** - * Receive notification that the charset has changed on this document, or a - * parent document. - * - * @param string $charset - */ - public function charsetChanged($charset) - { - $this->setCharset($charset); - } + /** + * Receive notification that the charset has changed on this document, or a + * parent document. + * + * @param string $charset + */ + public function charsetChanged($charset) + { + $this->setCharset($charset); + } - /** Fix the content-type and encoding of this entity */ - protected function fixHeaders() - { - parent::fixHeaders(); - if (\count($this->getChildren())) { - $this->setHeaderParameter('Content-Type', 'charset', null); - $this->setHeaderParameter('Content-Type', 'format', null); - $this->setHeaderParameter('Content-Type', 'delsp', null); - } else { - $this->setCharset($this->userCharset); - $this->setFormat($this->userFormat); - $this->setDelSp($this->userDelSp); - } - } + /** Fix the content-type and encoding of this entity */ + protected function fixHeaders() + { + parent::fixHeaders(); + if (\count($this->getChildren())) { + $this->setHeaderParameter('Content-Type', 'charset', null); + $this->setHeaderParameter('Content-Type', 'format', null); + $this->setHeaderParameter('Content-Type', 'delsp', null); + } else { + $this->setCharset($this->userCharset); + $this->setFormat($this->userFormat); + $this->setDelSp($this->userDelSp); + } + } - /** Set the nesting level of this entity */ - protected function setNestingLevel($level) - { - $this->nestingLevel = $level; - } + /** Set the nesting level of this entity */ + protected function setNestingLevel($level) + { + $this->nestingLevel = $level; + } - /** Encode charset when charset is not utf-8 */ - protected function convertString($string) - { - $charset = strtolower($this->getCharset() ?? ''); - if (!\in_array($charset, ['utf-8', 'iso-8859-1', 'iso-8859-15', ''])) { - return mb_convert_encoding($string, $charset, 'utf-8'); - } + /** Encode charset when charset is not utf-8 */ + protected function convertString($string) + { + $charset = strtolower($this->getCharset() ?? ''); + if (!\in_array($charset, ['utf-8', 'iso-8859-1', 'iso-8859-15', ''])) { + return mb_convert_encoding($string, $charset, 'utf-8'); + } - return $string; - } + return $string; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleHeaderFactory.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleHeaderFactory.php index ab3ce6b1914..347fa74cf66 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleHeaderFactory.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleHeaderFactory.php @@ -17,179 +17,179 @@ use Egulias\EmailValidator\EmailValidator; */ class Swift_Mime_SimpleHeaderFactory implements Swift_Mime_CharsetObserver { - /** The HeaderEncoder used by these headers */ - private $encoder; + /** The HeaderEncoder used by these headers */ + private $encoder; - /** The Encoder used by parameters */ - private $paramEncoder; + /** The Encoder used by parameters */ + private $paramEncoder; - /** Strict EmailValidator */ - private $emailValidator; + /** Strict EmailValidator */ + private $emailValidator; - /** The charset of created Headers */ - private $charset; + /** The charset of created Headers */ + private $charset; - /** Swift_AddressEncoder */ - private $addressEncoder; + /** Swift_AddressEncoder */ + private $addressEncoder; - /** - * Creates a new SimpleHeaderFactory using $encoder and $paramEncoder. - * - * @param string|null $charset - */ - public function __construct(Swift_Mime_HeaderEncoder $encoder, Swift_Encoder $paramEncoder, EmailValidator $emailValidator, $charset = null, Swift_AddressEncoder $addressEncoder = null) - { - $this->encoder = $encoder; - $this->paramEncoder = $paramEncoder; - $this->emailValidator = $emailValidator; - $this->charset = $charset; - $this->addressEncoder = $addressEncoder ?? new Swift_AddressEncoder_IdnAddressEncoder(); - } + /** + * Creates a new SimpleHeaderFactory using $encoder and $paramEncoder. + * + * @param string|null $charset + */ + public function __construct(Swift_Mime_HeaderEncoder $encoder, Swift_Encoder $paramEncoder, EmailValidator $emailValidator, $charset = null, Swift_AddressEncoder $addressEncoder = null) + { + $this->encoder = $encoder; + $this->paramEncoder = $paramEncoder; + $this->emailValidator = $emailValidator; + $this->charset = $charset; + $this->addressEncoder = $addressEncoder ?? new Swift_AddressEncoder_IdnAddressEncoder(); + } - /** - * Create a new Mailbox Header with a list of $addresses. - * - * @param string $name - * @param array|string|null $addresses - * - * @return Swift_Mime_Header - */ - public function createMailboxHeader($name, $addresses = null) - { - $header = new Swift_Mime_Headers_MailboxHeader($name, $this->encoder, $this->emailValidator, $this->addressEncoder); - if (isset($addresses)) { - $header->setFieldBodyModel($addresses); - } - $this->setHeaderCharset($header); + /** + * Create a new Mailbox Header with a list of $addresses. + * + * @param string $name + * @param array|string|null $addresses + * + * @return Swift_Mime_Header + */ + public function createMailboxHeader($name, $addresses = null) + { + $header = new Swift_Mime_Headers_MailboxHeader($name, $this->encoder, $this->emailValidator, $this->addressEncoder); + if (isset($addresses)) { + $header->setFieldBodyModel($addresses); + } + $this->setHeaderCharset($header); - return $header; - } + return $header; + } - /** - * Create a new Date header using $dateTime. - * - * @param string $name - * - * @return Swift_Mime_Header - */ - public function createDateHeader($name, DateTimeInterface $dateTime = null) - { - $header = new Swift_Mime_Headers_DateHeader($name); - if (isset($dateTime)) { - $header->setFieldBodyModel($dateTime); - } - $this->setHeaderCharset($header); + /** + * Create a new Date header using $dateTime. + * + * @param string $name + * + * @return Swift_Mime_Header + */ + public function createDateHeader($name, DateTimeInterface $dateTime = null) + { + $header = new Swift_Mime_Headers_DateHeader($name); + if (isset($dateTime)) { + $header->setFieldBodyModel($dateTime); + } + $this->setHeaderCharset($header); - return $header; - } + return $header; + } - /** - * Create a new basic text header with $name and $value. - * - * @param string $name - * @param string $value - * - * @return Swift_Mime_Header - */ - public function createTextHeader($name, $value = null) - { - $header = new Swift_Mime_Headers_UnstructuredHeader($name, $this->encoder); - if (isset($value)) { - $header->setFieldBodyModel($value); - } - $this->setHeaderCharset($header); + /** + * Create a new basic text header with $name and $value. + * + * @param string $name + * @param string $value + * + * @return Swift_Mime_Header + */ + public function createTextHeader($name, $value = null) + { + $header = new Swift_Mime_Headers_UnstructuredHeader($name, $this->encoder); + if (isset($value)) { + $header->setFieldBodyModel($value); + } + $this->setHeaderCharset($header); - return $header; - } + return $header; + } - /** - * Create a new ParameterizedHeader with $name, $value and $params. - * - * @param string $name - * @param string $value - * @param array $params - * - * @return Swift_Mime_Headers_ParameterizedHeader - */ - public function createParameterizedHeader($name, $value = null, $params = []) - { - $header = new Swift_Mime_Headers_ParameterizedHeader($name, $this->encoder, ('content-disposition' == strtolower($name ?? '')) ? $this->paramEncoder : null); - if (isset($value)) { - $header->setFieldBodyModel($value); - } - foreach ($params as $k => $v) { - $header->setParameter($k, $v); - } - $this->setHeaderCharset($header); + /** + * Create a new ParameterizedHeader with $name, $value and $params. + * + * @param string $name + * @param string $value + * @param array $params + * + * @return Swift_Mime_Headers_ParameterizedHeader + */ + public function createParameterizedHeader($name, $value = null, $params = []) + { + $header = new Swift_Mime_Headers_ParameterizedHeader($name, $this->encoder, ('content-disposition' == strtolower($name ?? '')) ? $this->paramEncoder : null); + if (isset($value)) { + $header->setFieldBodyModel($value); + } + foreach ($params as $k => $v) { + $header->setParameter($k, $v); + } + $this->setHeaderCharset($header); - return $header; - } + return $header; + } - /** - * Create a new ID header for Message-ID or Content-ID. - * - * @param string $name - * @param string|array $ids - * - * @return Swift_Mime_Header - */ - public function createIdHeader($name, $ids = null) - { - $header = new Swift_Mime_Headers_IdentificationHeader($name, $this->emailValidator); - if (isset($ids)) { - $header->setFieldBodyModel($ids); - } - $this->setHeaderCharset($header); + /** + * Create a new ID header for Message-ID or Content-ID. + * + * @param string $name + * @param string|array $ids + * + * @return Swift_Mime_Header + */ + public function createIdHeader($name, $ids = null) + { + $header = new Swift_Mime_Headers_IdentificationHeader($name, $this->emailValidator); + if (isset($ids)) { + $header->setFieldBodyModel($ids); + } + $this->setHeaderCharset($header); - return $header; - } + return $header; + } - /** - * Create a new Path header with an address (path) in it. - * - * @param string $name - * @param string $path - * - * @return Swift_Mime_Header - */ - public function createPathHeader($name, $path = null) - { - $header = new Swift_Mime_Headers_PathHeader($name, $this->emailValidator); - if (isset($path)) { - $header->setFieldBodyModel($path); - } - $this->setHeaderCharset($header); + /** + * Create a new Path header with an address (path) in it. + * + * @param string $name + * @param string $path + * + * @return Swift_Mime_Header + */ + public function createPathHeader($name, $path = null) + { + $header = new Swift_Mime_Headers_PathHeader($name, $this->emailValidator); + if (isset($path)) { + $header->setFieldBodyModel($path); + } + $this->setHeaderCharset($header); - return $header; - } + return $header; + } - /** - * Notify this observer that the entity's charset has changed. - * - * @param string $charset - */ - public function charsetChanged($charset) - { - $this->charset = $charset; - $this->encoder->charsetChanged($charset); - $this->paramEncoder->charsetChanged($charset); - } + /** + * Notify this observer that the entity's charset has changed. + * + * @param string $charset + */ + public function charsetChanged($charset) + { + $this->charset = $charset; + $this->encoder->charsetChanged($charset); + $this->paramEncoder->charsetChanged($charset); + } - /** - * Make a deep copy of object. - */ - public function __clone() - { - $this->encoder = clone $this->encoder; - $this->paramEncoder = clone $this->paramEncoder; - $this->addressEncoder = clone $this->addressEncoder; - } + /** + * Make a deep copy of object. + */ + public function __clone() + { + $this->encoder = clone $this->encoder; + $this->paramEncoder = clone $this->paramEncoder; + $this->addressEncoder = clone $this->addressEncoder; + } - /** Apply the charset to the Header */ - private function setHeaderCharset(Swift_Mime_Header $header) - { - if (isset($this->charset)) { - $header->setCharset($this->charset); - } - } + /** Apply the charset to the Header */ + private function setHeaderCharset(Swift_Mime_Header $header) + { + if (isset($this->charset)) { + $header->setCharset($this->charset); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleHeaderSet.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleHeaderSet.php index 5195bcf48ae..219c46f32ff 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleHeaderSet.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleHeaderSet.php @@ -15,385 +15,385 @@ */ class Swift_Mime_SimpleHeaderSet implements Swift_Mime_CharsetObserver { - /** HeaderFactory */ - private $factory; + /** HeaderFactory */ + private $factory; - /** Collection of set Headers */ - private $headers = []; + /** Collection of set Headers */ + private $headers = []; - /** Field ordering details */ - private $order = []; + /** Field ordering details */ + private $order = []; - /** List of fields which are required to be displayed */ - private $required = []; + /** List of fields which are required to be displayed */ + private $required = []; - /** The charset used by Headers */ - private $charset; + /** The charset used by Headers */ + private $charset; - /** - * Create a new SimpleHeaderSet with the given $factory. - * - * @param string $charset - */ - public function __construct(Swift_Mime_SimpleHeaderFactory $factory, $charset = null) - { - $this->factory = $factory; - if (isset($charset)) { - $this->setCharset($charset); - } - } + /** + * Create a new SimpleHeaderSet with the given $factory. + * + * @param string $charset + */ + public function __construct(Swift_Mime_SimpleHeaderFactory $factory, $charset = null) + { + $this->factory = $factory; + if (isset($charset)) { + $this->setCharset($charset); + } + } - public function newInstance() - { - return new self($this->factory); - } + public function newInstance() + { + return new self($this->factory); + } - /** - * Set the charset used by these headers. - * - * @param string $charset - */ - public function setCharset($charset) - { - $this->charset = $charset; - $this->factory->charsetChanged($charset); - $this->notifyHeadersOfCharset($charset); - } + /** + * Set the charset used by these headers. + * + * @param string $charset + */ + public function setCharset($charset) + { + $this->charset = $charset; + $this->factory->charsetChanged($charset); + $this->notifyHeadersOfCharset($charset); + } - /** - * Add a new Mailbox Header with a list of $addresses. - * - * @param string $name - * @param array|string $addresses - */ - public function addMailboxHeader($name, $addresses = null) - { - $this->storeHeader($name, $this->factory->createMailboxHeader($name, $addresses)); - } + /** + * Add a new Mailbox Header with a list of $addresses. + * + * @param string $name + * @param array|string $addresses + */ + public function addMailboxHeader($name, $addresses = null) + { + $this->storeHeader($name, $this->factory->createMailboxHeader($name, $addresses)); + } - /** - * Add a new Date header using $dateTime. - * - * @param string $name - */ - public function addDateHeader($name, DateTimeInterface $dateTime = null) - { - $this->storeHeader($name, $this->factory->createDateHeader($name, $dateTime)); - } + /** + * Add a new Date header using $dateTime. + * + * @param string $name + */ + public function addDateHeader($name, DateTimeInterface $dateTime = null) + { + $this->storeHeader($name, $this->factory->createDateHeader($name, $dateTime)); + } - /** - * Add a new basic text header with $name and $value. - * - * @param string $name - * @param string $value - */ - public function addTextHeader($name, $value = null) - { - $this->storeHeader($name, $this->factory->createTextHeader($name, $value)); - } + /** + * Add a new basic text header with $name and $value. + * + * @param string $name + * @param string $value + */ + public function addTextHeader($name, $value = null) + { + $this->storeHeader($name, $this->factory->createTextHeader($name, $value)); + } - /** - * Add a new ParameterizedHeader with $name, $value and $params. - * - * @param string $name - * @param string $value - * @param array $params - */ - public function addParameterizedHeader($name, $value = null, $params = []) - { - $this->storeHeader($name, $this->factory->createParameterizedHeader($name, $value, $params)); - } + /** + * Add a new ParameterizedHeader with $name, $value and $params. + * + * @param string $name + * @param string $value + * @param array $params + */ + public function addParameterizedHeader($name, $value = null, $params = []) + { + $this->storeHeader($name, $this->factory->createParameterizedHeader($name, $value, $params)); + } - /** - * Add a new ID header for Message-ID or Content-ID. - * - * @param string $name - * @param string|array $ids - */ - public function addIdHeader($name, $ids = null) - { - $this->storeHeader($name, $this->factory->createIdHeader($name, $ids)); - } + /** + * Add a new ID header for Message-ID or Content-ID. + * + * @param string $name + * @param string|array $ids + */ + public function addIdHeader($name, $ids = null) + { + $this->storeHeader($name, $this->factory->createIdHeader($name, $ids)); + } - /** - * Add a new Path header with an address (path) in it. - * - * @param string $name - * @param string $path - */ - public function addPathHeader($name, $path = null) - { - $this->storeHeader($name, $this->factory->createPathHeader($name, $path)); - } + /** + * Add a new Path header with an address (path) in it. + * + * @param string $name + * @param string $path + */ + public function addPathHeader($name, $path = null) + { + $this->storeHeader($name, $this->factory->createPathHeader($name, $path)); + } - /** - * Returns true if at least one header with the given $name exists. - * - * If multiple headers match, the actual one may be specified by $index. - * - * @param string $name - * @param int $index - * - * @return bool - */ - public function has($name, $index = 0) - { - $lowerName = strtolower($name ?? ''); + /** + * Returns true if at least one header with the given $name exists. + * + * If multiple headers match, the actual one may be specified by $index. + * + * @param string $name + * @param int $index + * + * @return bool + */ + public function has($name, $index = 0) + { + $lowerName = strtolower($name ?? ''); - if (!\array_key_exists($lowerName, $this->headers)) { - return false; - } + if (!\array_key_exists($lowerName, $this->headers)) { + return false; + } - if (\func_num_args() < 2) { - // index was not specified, so we only need to check that there is at least one header value set - return (bool) \count($this->headers[$lowerName]); - } + if (\func_num_args() < 2) { + // index was not specified, so we only need to check that there is at least one header value set + return (bool) \count($this->headers[$lowerName]); + } - return \array_key_exists($index, $this->headers[$lowerName]); - } + return \array_key_exists($index, $this->headers[$lowerName]); + } - /** - * Set a header in the HeaderSet. - * - * The header may be a previously fetched header via {@link get()} or it may - * be one that has been created separately. - * - * If $index is specified, the header will be inserted into the set at this - * offset. - * - * @param int $index - */ - public function set(Swift_Mime_Header $header, $index = 0) - { - $this->storeHeader($header->getFieldName(), $header, $index); - } + /** + * Set a header in the HeaderSet. + * + * The header may be a previously fetched header via {@link get()} or it may + * be one that has been created separately. + * + * If $index is specified, the header will be inserted into the set at this + * offset. + * + * @param int $index + */ + public function set(Swift_Mime_Header $header, $index = 0) + { + $this->storeHeader($header->getFieldName(), $header, $index); + } - /** - * Get the header with the given $name. - * - * If multiple headers match, the actual one may be specified by $index. - * Returns NULL if none present. - * - * @param string $name - * @param int $index - * - * @return Swift_Mime_Header|null - */ - public function get($name, $index = 0) - { - $name = strtolower($name ?? ''); + /** + * Get the header with the given $name. + * + * If multiple headers match, the actual one may be specified by $index. + * Returns NULL if none present. + * + * @param string $name + * @param int $index + * + * @return Swift_Mime_Header|null + */ + public function get($name, $index = 0) + { + $name = strtolower($name ?? ''); - if (\func_num_args() < 2) { - if ($this->has($name)) { - $values = array_values($this->headers[$name]); + if (\func_num_args() < 2) { + if ($this->has($name)) { + $values = array_values($this->headers[$name]); - return array_shift($values); - } - } else { - if ($this->has($name, $index)) { - return $this->headers[$name][$index]; - } - } - } + return array_shift($values); + } + } else { + if ($this->has($name, $index)) { + return $this->headers[$name][$index]; + } + } + } - /** - * Get all headers with the given $name. - * - * @param string $name - * - * @return array - */ - public function getAll($name = null) - { - if (!isset($name)) { - $headers = []; - foreach ($this->headers as $collection) { - $headers = array_merge($headers, $collection); - } + /** + * Get all headers with the given $name. + * + * @param string $name + * + * @return array + */ + public function getAll($name = null) + { + if (!isset($name)) { + $headers = []; + foreach ($this->headers as $collection) { + $headers = array_merge($headers, $collection); + } - return $headers; - } + return $headers; + } - $lowerName = strtolower($name ?? ''); - if (!\array_key_exists($lowerName, $this->headers)) { - return []; - } + $lowerName = strtolower($name ?? ''); + if (!\array_key_exists($lowerName, $this->headers)) { + return []; + } - return $this->headers[$lowerName]; - } + return $this->headers[$lowerName]; + } - /** - * Return the name of all Headers. - * - * @return array - */ - public function listAll() - { - $headers = $this->headers; - if ($this->canSort()) { - uksort($headers, [$this, 'sortHeaders']); - } + /** + * Return the name of all Headers. + * + * @return array + */ + public function listAll() + { + $headers = $this->headers; + if ($this->canSort()) { + uksort($headers, [$this, 'sortHeaders']); + } - return array_keys($headers); - } + return array_keys($headers); + } - /** - * Remove the header with the given $name if it's set. - * - * If multiple headers match, the actual one may be specified by $index. - * - * @param string $name - * @param int $index - */ - public function remove($name, $index = 0) - { - $lowerName = strtolower($name ?? ''); - unset($this->headers[$lowerName][$index]); - } + /** + * Remove the header with the given $name if it's set. + * + * If multiple headers match, the actual one may be specified by $index. + * + * @param string $name + * @param int $index + */ + public function remove($name, $index = 0) + { + $lowerName = strtolower($name ?? ''); + unset($this->headers[$lowerName][$index]); + } - /** - * Remove all headers with the given $name. - * - * @param string $name - */ - public function removeAll($name) - { - $lowerName = strtolower($name ?? ''); - unset($this->headers[$lowerName]); - } + /** + * Remove all headers with the given $name. + * + * @param string $name + */ + public function removeAll($name) + { + $lowerName = strtolower($name ?? ''); + unset($this->headers[$lowerName]); + } - /** - * Define a list of Header names as an array in the correct order. - * - * These Headers will be output in the given order where present. - */ - public function defineOrdering(array $sequence) - { - $this->order = array_flip(array_map('strtolower', $sequence)); - } + /** + * Define a list of Header names as an array in the correct order. + * + * These Headers will be output in the given order where present. + */ + public function defineOrdering(array $sequence) + { + $this->order = array_flip(array_map('strtolower', $sequence)); + } - /** - * Set a list of header names which must always be displayed when set. - * - * Usually headers without a field value won't be output unless set here. - */ - public function setAlwaysDisplayed(array $names) - { - $this->required = array_flip(array_map('strtolower', $names)); - } + /** + * Set a list of header names which must always be displayed when set. + * + * Usually headers without a field value won't be output unless set here. + */ + public function setAlwaysDisplayed(array $names) + { + $this->required = array_flip(array_map('strtolower', $names)); + } - /** - * Notify this observer that the entity's charset has changed. - * - * @param string $charset - */ - public function charsetChanged($charset) - { - $this->setCharset($charset); - } + /** + * Notify this observer that the entity's charset has changed. + * + * @param string $charset + */ + public function charsetChanged($charset) + { + $this->setCharset($charset); + } - /** - * Returns a string with a representation of all headers. - * - * @return string - */ - public function toString() - { - $string = ''; - $headers = $this->headers; - if ($this->canSort()) { - uksort($headers, [$this, 'sortHeaders']); - } - foreach ($headers as $collection) { - foreach ($collection as $header) { - if ($this->isDisplayed($header) || '' != $header->getFieldBody()) { - $string .= $header->toString(); - } - } - } + /** + * Returns a string with a representation of all headers. + * + * @return string + */ + public function toString() + { + $string = ''; + $headers = $this->headers; + if ($this->canSort()) { + uksort($headers, [$this, 'sortHeaders']); + } + foreach ($headers as $collection) { + foreach ($collection as $header) { + if ($this->isDisplayed($header) || '' != $header->getFieldBody()) { + $string .= $header->toString(); + } + } + } - return $string; - } + return $string; + } - /** - * Returns a string representation of this object. - * - * @return string - * - * @see toString() - */ - public function __toString() - { - return $this->toString(); - } + /** + * Returns a string representation of this object. + * + * @return string + * + * @see toString() + */ + public function __toString() + { + return $this->toString(); + } - /** Save a Header to the internal collection */ - private function storeHeader($name, Swift_Mime_Header $header, $offset = null) - { - if (!isset($this->headers[strtolower($name ?? '')])) { - $this->headers[strtolower($name ?? '')] = []; - } - if (!isset($offset)) { - $this->headers[strtolower($name ?? '')][] = $header; - } else { - $this->headers[strtolower($name ?? '')][$offset] = $header; - } - } + /** Save a Header to the internal collection */ + private function storeHeader($name, Swift_Mime_Header $header, $offset = null) + { + if (!isset($this->headers[strtolower($name ?? '')])) { + $this->headers[strtolower($name ?? '')] = []; + } + if (!isset($offset)) { + $this->headers[strtolower($name ?? '')][] = $header; + } else { + $this->headers[strtolower($name ?? '')][$offset] = $header; + } + } - /** Test if the headers can be sorted */ - private function canSort() - { - return \count($this->order) > 0; - } + /** Test if the headers can be sorted */ + private function canSort() + { + return \count($this->order) > 0; + } - /** uksort() algorithm for Header ordering */ - private function sortHeaders($a, $b) - { - $lowerA = strtolower($a ?? ''); - $lowerB = strtolower($b ?? ''); - $aPos = \array_key_exists($lowerA, $this->order) ? $this->order[$lowerA] : -1; - $bPos = \array_key_exists($lowerB, $this->order) ? $this->order[$lowerB] : -1; + /** uksort() algorithm for Header ordering */ + private function sortHeaders($a, $b) + { + $lowerA = strtolower($a ?? ''); + $lowerB = strtolower($b ?? ''); + $aPos = \array_key_exists($lowerA, $this->order) ? $this->order[$lowerA] : -1; + $bPos = \array_key_exists($lowerB, $this->order) ? $this->order[$lowerB] : -1; - if (-1 === $aPos && -1 === $bPos) { - // just be sure to be determinist here - return $a > $b ? -1 : 1; - } + if (-1 === $aPos && -1 === $bPos) { + // just be sure to be determinist here + return $a > $b ? -1 : 1; + } - if (-1 == $aPos) { - return 1; - } elseif (-1 == $bPos) { - return -1; - } + if (-1 == $aPos) { + return 1; + } elseif (-1 == $bPos) { + return -1; + } - return $aPos < $bPos ? -1 : 1; - } + return $aPos < $bPos ? -1 : 1; + } - /** Test if the given Header is always displayed */ - private function isDisplayed(Swift_Mime_Header $header) - { - return \array_key_exists(strtolower($header->getFieldName() ?? ''), $this->required); - } + /** Test if the given Header is always displayed */ + private function isDisplayed(Swift_Mime_Header $header) + { + return \array_key_exists(strtolower($header->getFieldName() ?? ''), $this->required); + } - /** Notify all Headers of the new charset */ - private function notifyHeadersOfCharset($charset) - { - foreach ($this->headers as $headerGroup) { - foreach ($headerGroup as $header) { - $header->setCharset($charset); - } - } - } + /** Notify all Headers of the new charset */ + private function notifyHeadersOfCharset($charset) + { + foreach ($this->headers as $headerGroup) { + foreach ($headerGroup as $header) { + $header->setCharset($charset); + } + } + } - /** - * Make a deep copy of object. - */ - public function __clone() - { - $this->factory = clone $this->factory; - foreach ($this->headers as $groupKey => $headerGroup) { - foreach ($headerGroup as $key => $header) { - $this->headers[$groupKey][$key] = clone $header; - } - } - } + /** + * Make a deep copy of object. + */ + public function __clone() + { + $this->factory = clone $this->factory; + foreach ($this->headers as $groupKey => $headerGroup) { + foreach ($headerGroup as $key => $header) { + $this->headers[$groupKey][$key] = clone $header; + } + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleMessage.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleMessage.php index 62da1650a7b..1f87ce06452 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleMessage.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleMessage.php @@ -15,628 +15,628 @@ */ class Swift_Mime_SimpleMessage extends Swift_Mime_MimePart { - const PRIORITY_HIGHEST = 1; - const PRIORITY_HIGH = 2; - const PRIORITY_NORMAL = 3; - const PRIORITY_LOW = 4; - const PRIORITY_LOWEST = 5; - - /** - * Create a new SimpleMessage with $headers, $encoder and $cache. - * - * @param string $charset - */ - public function __construct(Swift_Mime_SimpleHeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_IdGenerator $idGenerator, $charset = null) - { - parent::__construct($headers, $encoder, $cache, $idGenerator, $charset); - $this->getHeaders()->defineOrdering([ - 'Return-Path', - 'Received', - 'DKIM-Signature', - 'DomainKey-Signature', - 'Sender', - 'Message-ID', - 'Date', - 'Subject', - 'From', - 'Reply-To', - 'To', - 'Cc', - 'Bcc', - 'MIME-Version', - 'Content-Type', - 'Content-Transfer-Encoding', - ]); - $this->getHeaders()->setAlwaysDisplayed(['Date', 'Message-ID', 'From']); - $this->getHeaders()->addTextHeader('MIME-Version', '1.0'); - $this->setDate(new DateTimeImmutable()); - $this->setId($this->getId()); - $this->getHeaders()->addMailboxHeader('From'); - } - - /** - * Always returns {@link LEVEL_TOP} for a message instance. - * - * @return int - */ - public function getNestingLevel() - { - return self::LEVEL_TOP; - } - - /** - * Set the subject of this message. - * - * @param string $subject - * - * @return $this - */ - public function setSubject($subject) - { - if (!$this->setHeaderFieldModel('Subject', $subject)) { - $this->getHeaders()->addTextHeader('Subject', $subject); - } - - return $this; - } - - /** - * Get the subject of this message. - * - * @return string - */ - public function getSubject() - { - return $this->getHeaderFieldModel('Subject'); - } - - /** - * Set the date at which this message was created. - * - * @return $this - */ - public function setDate(DateTimeInterface $dateTime) - { - if (!$this->setHeaderFieldModel('Date', $dateTime)) { - $this->getHeaders()->addDateHeader('Date', $dateTime); - } - - return $this; - } - - /** - * Get the date at which this message was created. - * - * @return DateTimeInterface - */ - public function getDate() - { - return $this->getHeaderFieldModel('Date'); - } - - /** - * Set the return-path (the bounce address) of this message. - * - * @param string $address - * - * @return $this - */ - public function setReturnPath($address) - { - if (!$this->setHeaderFieldModel('Return-Path', $address)) { - $this->getHeaders()->addPathHeader('Return-Path', $address); - } - - return $this; - } - - /** - * Get the return-path (bounce address) of this message. - * - * @return string - */ - public function getReturnPath() - { - return $this->getHeaderFieldModel('Return-Path'); - } - - /** - * Set the sender of this message. - * - * This does not override the From field, but it has a higher significance. - * - * @param string $address - * @param string $name optional - * - * @return $this - */ - public function setSender($address, $name = null) - { - if (!\is_array($address) && isset($name)) { - $address = [$address => $name]; - } - - if (!$this->setHeaderFieldModel('Sender', (array) $address)) { - $this->getHeaders()->addMailboxHeader('Sender', (array) $address); - } - - return $this; - } - - /** - * Get the sender of this message. - * - * @return string - */ - public function getSender() - { - return $this->getHeaderFieldModel('Sender'); - } - - /** - * Add a From: address to this message. - * - * If $name is passed this name will be associated with the address. - * - * @param string $address - * @param string $name optional - * - * @return $this - */ - public function addFrom($address, $name = null) - { - $current = $this->getFrom(); - $current[$address] = $name; - - return $this->setFrom($current); - } - - /** - * Set the from address of this message. - * - * You may pass an array of addresses if this message is from multiple people. - * - * If $name is passed and the first parameter is a string, this name will be - * associated with the address. - * - * @param string|array $addresses - * @param string $name optional - * - * @return $this - */ - public function setFrom($addresses, $name = null) - { - if (!\is_array($addresses) && isset($name)) { - $addresses = [$addresses => $name]; - } - - if (!$this->setHeaderFieldModel('From', (array) $addresses)) { - $this->getHeaders()->addMailboxHeader('From', (array) $addresses); - } - - return $this; - } - - /** - * Get the from address of this message. - * - * @return mixed - */ - public function getFrom() - { - return $this->getHeaderFieldModel('From'); - } - - /** - * Add a Reply-To: address to this message. - * - * If $name is passed this name will be associated with the address. - * - * @param string $address - * @param string $name optional - * - * @return $this - */ - public function addReplyTo($address, $name = null) - { - $current = $this->getReplyTo(); - $current[$address] = $name; - - return $this->setReplyTo($current); - } - - /** - * Set the reply-to address of this message. - * - * You may pass an array of addresses if replies will go to multiple people. - * - * If $name is passed and the first parameter is a string, this name will be - * associated with the address. - * - * @param mixed $addresses - * @param string $name optional - * - * @return $this - */ - public function setReplyTo($addresses, $name = null) - { - if (!\is_array($addresses) && isset($name)) { - $addresses = [$addresses => $name]; - } - - if (!$this->setHeaderFieldModel('Reply-To', (array) $addresses)) { - $this->getHeaders()->addMailboxHeader('Reply-To', (array) $addresses); - } - - return $this; - } - - /** - * Get the reply-to address of this message. - * - * @return string - */ - public function getReplyTo() - { - return $this->getHeaderFieldModel('Reply-To'); - } - - /** - * Add a To: address to this message. - * - * If $name is passed this name will be associated with the address. - * - * @param string $address - * @param string $name optional - * - * @return $this - */ - public function addTo($address, $name = null) - { - $current = $this->getTo(); - $current[$address] = $name; - - return $this->setTo($current); - } - - /** - * Set the to addresses of this message. - * - * If multiple recipients will receive the message an array should be used. - * Example: array('receiver@domain.org', 'other@domain.org' => 'A name') - * - * If $name is passed and the first parameter is a string, this name will be - * associated with the address. - * - * @param mixed $addresses - * @param string $name optional - * - * @return $this - */ - public function setTo($addresses, $name = null) - { - if (!\is_array($addresses) && isset($name)) { - $addresses = [$addresses => $name]; - } - - if (!$this->setHeaderFieldModel('To', (array) $addresses)) { - $this->getHeaders()->addMailboxHeader('To', (array) $addresses); - } - - return $this; - } - - /** - * Get the To addresses of this message. - * - * @return array - */ - public function getTo() - { - return $this->getHeaderFieldModel('To'); - } - - /** - * Add a Cc: address to this message. - * - * If $name is passed this name will be associated with the address. - * - * @param string $address - * @param string $name optional - * - * @return $this - */ - public function addCc($address, $name = null) - { - $current = $this->getCc(); - $current[$address] = $name; - - return $this->setCc($current); - } - - /** - * Set the Cc addresses of this message. - * - * If $name is passed and the first parameter is a string, this name will be - * associated with the address. - * - * @param mixed $addresses - * @param string $name optional - * - * @return $this - */ - public function setCc($addresses, $name = null) - { - if (!\is_array($addresses) && isset($name)) { - $addresses = [$addresses => $name]; - } - - if (!$this->setHeaderFieldModel('Cc', (array) $addresses)) { - $this->getHeaders()->addMailboxHeader('Cc', (array) $addresses); - } - - return $this; - } - - /** - * Get the Cc address of this message. - * - * @return array - */ - public function getCc() - { - return $this->getHeaderFieldModel('Cc'); - } - - /** - * Add a Bcc: address to this message. - * - * If $name is passed this name will be associated with the address. - * - * @param string $address - * @param string $name optional - * - * @return $this - */ - public function addBcc($address, $name = null) - { - $current = $this->getBcc(); - $current[$address] = $name; - - return $this->setBcc($current); - } - - /** - * Set the Bcc addresses of this message. - * - * If $name is passed and the first parameter is a string, this name will be - * associated with the address. - * - * @param mixed $addresses - * @param string $name optional - * - * @return $this - */ - public function setBcc($addresses, $name = null) - { - if (!\is_array($addresses) && isset($name)) { - $addresses = [$addresses => $name]; - } - - if (!$this->setHeaderFieldModel('Bcc', (array) $addresses)) { - $this->getHeaders()->addMailboxHeader('Bcc', (array) $addresses); - } - - return $this; - } - - /** - * Get the Bcc addresses of this message. - * - * @return array - */ - public function getBcc() - { - return $this->getHeaderFieldModel('Bcc'); - } - - /** - * Set the priority of this message. - * - * The value is an integer where 1 is the highest priority and 5 is the lowest. - * - * @param int $priority - * - * @return $this - */ - public function setPriority($priority) - { - $priorityMap = [ - self::PRIORITY_HIGHEST => 'Highest', - self::PRIORITY_HIGH => 'High', - self::PRIORITY_NORMAL => 'Normal', - self::PRIORITY_LOW => 'Low', - self::PRIORITY_LOWEST => 'Lowest', - ]; - $pMapKeys = array_keys($priorityMap); - if ($priority > max($pMapKeys)) { - $priority = max($pMapKeys); - } elseif ($priority < min($pMapKeys)) { - $priority = min($pMapKeys); - } - if (!$this->setHeaderFieldModel('X-Priority', - sprintf('%d (%s)', $priority, $priorityMap[$priority]))) { - $this->getHeaders()->addTextHeader('X-Priority', - sprintf('%d (%s)', $priority, $priorityMap[$priority])); - } - - return $this; - } - - /** - * Get the priority of this message. - * - * The returned value is an integer where 1 is the highest priority and 5 - * is the lowest. - * - * @return int - */ - public function getPriority() - { - list($priority) = sscanf($this->getHeaderFieldModel('X-Priority'), - '%[1-5]' - ); - - return $priority ?? 3; - } - - /** - * Ask for a delivery receipt from the recipient to be sent to $addresses. - * - * @param array $addresses - * - * @return $this - */ - public function setReadReceiptTo($addresses) - { - if (!$this->setHeaderFieldModel('Disposition-Notification-To', $addresses)) { - $this->getHeaders() - ->addMailboxHeader('Disposition-Notification-To', $addresses); - } - - return $this; - } - - /** - * Get the addresses to which a read-receipt will be sent. - * - * @return string - */ - public function getReadReceiptTo() - { - return $this->getHeaderFieldModel('Disposition-Notification-To'); - } - - /** - * Attach a {@link Swift_Mime_SimpleMimeEntity} such as an Attachment or MimePart. - * - * @return $this - */ - public function attach(Swift_Mime_SimpleMimeEntity $entity) - { - $this->setChildren(array_merge($this->getChildren(), [$entity])); - - return $this; - } - - /** - * Remove an already attached entity. - * - * @return $this - */ - public function detach(Swift_Mime_SimpleMimeEntity $entity) - { - $newChildren = []; - foreach ($this->getChildren() as $child) { - if ($entity !== $child) { - $newChildren[] = $child; - } - } - $this->setChildren($newChildren); - - return $this; - } - - /** - * Attach a {@link Swift_Mime_SimpleMimeEntity} and return it's CID source. - * - * This method should be used when embedding images or other data in a message. - * - * @return string - */ - public function embed(Swift_Mime_SimpleMimeEntity $entity) - { - $this->attach($entity); - - return 'cid:'.$entity->getId(); - } - - /** - * Get this message as a complete string. - * - * @return string - */ - public function toString() - { - if (\count($children = $this->getChildren()) > 0 && '' != $this->getBody()) { - $this->setChildren(array_merge([$this->becomeMimePart()], $children)); - $string = parent::toString(); - $this->setChildren($children); - } else { - $string = parent::toString(); - } - - return $string; - } - - /** - * Returns a string representation of this object. - * - * @see toString() - * - * @return string - */ - public function __toString() - { - return $this->toString(); - } - - /** - * Write this message to a {@link Swift_InputByteStream}. - */ - public function toByteStream(Swift_InputByteStream $is) - { - if (\count($children = $this->getChildren()) > 0 && '' != $this->getBody()) { - $this->setChildren(array_merge([$this->becomeMimePart()], $children)); - parent::toByteStream($is); - $this->setChildren($children); - } else { - parent::toByteStream($is); - } - } - - /** @see Swift_Mime_SimpleMimeEntity::getIdField() */ - protected function getIdField() - { - return 'Message-ID'; - } - - /** Turn the body of this message into a child of itself if needed */ - protected function becomeMimePart() - { - $part = new parent($this->getHeaders()->newInstance(), $this->getEncoder(), - $this->getCache(), $this->getIdGenerator(), $this->userCharset - ); - $part->setContentType($this->userContentType); - $part->setBody($this->getBody()); - $part->setFormat($this->userFormat); - $part->setDelSp($this->userDelSp); - $part->setNestingLevel($this->getTopNestingLevel()); - - return $part; - } - - /** Get the highest nesting level nested inside this message */ - private function getTopNestingLevel() - { - $highestLevel = $this->getNestingLevel(); - foreach ($this->getChildren() as $child) { - $childLevel = $child->getNestingLevel(); - if ($highestLevel < $childLevel) { - $highestLevel = $childLevel; - } - } - - return $highestLevel; - } + const PRIORITY_HIGHEST = 1; + const PRIORITY_HIGH = 2; + const PRIORITY_NORMAL = 3; + const PRIORITY_LOW = 4; + const PRIORITY_LOWEST = 5; + + /** + * Create a new SimpleMessage with $headers, $encoder and $cache. + * + * @param string $charset + */ + public function __construct(Swift_Mime_SimpleHeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_IdGenerator $idGenerator, $charset = null) + { + parent::__construct($headers, $encoder, $cache, $idGenerator, $charset); + $this->getHeaders()->defineOrdering([ + 'Return-Path', + 'Received', + 'DKIM-Signature', + 'DomainKey-Signature', + 'Sender', + 'Message-ID', + 'Date', + 'Subject', + 'From', + 'Reply-To', + 'To', + 'Cc', + 'Bcc', + 'MIME-Version', + 'Content-Type', + 'Content-Transfer-Encoding', + ]); + $this->getHeaders()->setAlwaysDisplayed(['Date', 'Message-ID', 'From']); + $this->getHeaders()->addTextHeader('MIME-Version', '1.0'); + $this->setDate(new DateTimeImmutable()); + $this->setId($this->getId()); + $this->getHeaders()->addMailboxHeader('From'); + } + + /** + * Always returns {@link LEVEL_TOP} for a message instance. + * + * @return int + */ + public function getNestingLevel() + { + return self::LEVEL_TOP; + } + + /** + * Set the subject of this message. + * + * @param string $subject + * + * @return $this + */ + public function setSubject($subject) + { + if (!$this->setHeaderFieldModel('Subject', $subject)) { + $this->getHeaders()->addTextHeader('Subject', $subject); + } + + return $this; + } + + /** + * Get the subject of this message. + * + * @return string + */ + public function getSubject() + { + return $this->getHeaderFieldModel('Subject'); + } + + /** + * Set the date at which this message was created. + * + * @return $this + */ + public function setDate(DateTimeInterface $dateTime) + { + if (!$this->setHeaderFieldModel('Date', $dateTime)) { + $this->getHeaders()->addDateHeader('Date', $dateTime); + } + + return $this; + } + + /** + * Get the date at which this message was created. + * + * @return DateTimeInterface + */ + public function getDate() + { + return $this->getHeaderFieldModel('Date'); + } + + /** + * Set the return-path (the bounce address) of this message. + * + * @param string $address + * + * @return $this + */ + public function setReturnPath($address) + { + if (!$this->setHeaderFieldModel('Return-Path', $address)) { + $this->getHeaders()->addPathHeader('Return-Path', $address); + } + + return $this; + } + + /** + * Get the return-path (bounce address) of this message. + * + * @return string + */ + public function getReturnPath() + { + return $this->getHeaderFieldModel('Return-Path'); + } + + /** + * Set the sender of this message. + * + * This does not override the From field, but it has a higher significance. + * + * @param string $address + * @param string $name optional + * + * @return $this + */ + public function setSender($address, $name = null) + { + if (!\is_array($address) && isset($name)) { + $address = [$address => $name]; + } + + if (!$this->setHeaderFieldModel('Sender', (array) $address)) { + $this->getHeaders()->addMailboxHeader('Sender', (array) $address); + } + + return $this; + } + + /** + * Get the sender of this message. + * + * @return string + */ + public function getSender() + { + return $this->getHeaderFieldModel('Sender'); + } + + /** + * Add a From: address to this message. + * + * If $name is passed this name will be associated with the address. + * + * @param string $address + * @param string $name optional + * + * @return $this + */ + public function addFrom($address, $name = null) + { + $current = $this->getFrom(); + $current[$address] = $name; + + return $this->setFrom($current); + } + + /** + * Set the from address of this message. + * + * You may pass an array of addresses if this message is from multiple people. + * + * If $name is passed and the first parameter is a string, this name will be + * associated with the address. + * + * @param string|array $addresses + * @param string $name optional + * + * @return $this + */ + public function setFrom($addresses, $name = null) + { + if (!\is_array($addresses) && isset($name)) { + $addresses = [$addresses => $name]; + } + + if (!$this->setHeaderFieldModel('From', (array) $addresses)) { + $this->getHeaders()->addMailboxHeader('From', (array) $addresses); + } + + return $this; + } + + /** + * Get the from address of this message. + * + * @return mixed + */ + public function getFrom() + { + return $this->getHeaderFieldModel('From'); + } + + /** + * Add a Reply-To: address to this message. + * + * If $name is passed this name will be associated with the address. + * + * @param string $address + * @param string $name optional + * + * @return $this + */ + public function addReplyTo($address, $name = null) + { + $current = $this->getReplyTo(); + $current[$address] = $name; + + return $this->setReplyTo($current); + } + + /** + * Set the reply-to address of this message. + * + * You may pass an array of addresses if replies will go to multiple people. + * + * If $name is passed and the first parameter is a string, this name will be + * associated with the address. + * + * @param mixed $addresses + * @param string $name optional + * + * @return $this + */ + public function setReplyTo($addresses, $name = null) + { + if (!\is_array($addresses) && isset($name)) { + $addresses = [$addresses => $name]; + } + + if (!$this->setHeaderFieldModel('Reply-To', (array) $addresses)) { + $this->getHeaders()->addMailboxHeader('Reply-To', (array) $addresses); + } + + return $this; + } + + /** + * Get the reply-to address of this message. + * + * @return string + */ + public function getReplyTo() + { + return $this->getHeaderFieldModel('Reply-To'); + } + + /** + * Add a To: address to this message. + * + * If $name is passed this name will be associated with the address. + * + * @param string $address + * @param string $name optional + * + * @return $this + */ + public function addTo($address, $name = null) + { + $current = $this->getTo(); + $current[$address] = $name; + + return $this->setTo($current); + } + + /** + * Set the to addresses of this message. + * + * If multiple recipients will receive the message an array should be used. + * Example: array('receiver@domain.org', 'other@domain.org' => 'A name') + * + * If $name is passed and the first parameter is a string, this name will be + * associated with the address. + * + * @param mixed $addresses + * @param string $name optional + * + * @return $this + */ + public function setTo($addresses, $name = null) + { + if (!\is_array($addresses) && isset($name)) { + $addresses = [$addresses => $name]; + } + + if (!$this->setHeaderFieldModel('To', (array) $addresses)) { + $this->getHeaders()->addMailboxHeader('To', (array) $addresses); + } + + return $this; + } + + /** + * Get the To addresses of this message. + * + * @return array + */ + public function getTo() + { + return $this->getHeaderFieldModel('To'); + } + + /** + * Add a Cc: address to this message. + * + * If $name is passed this name will be associated with the address. + * + * @param string $address + * @param string $name optional + * + * @return $this + */ + public function addCc($address, $name = null) + { + $current = $this->getCc(); + $current[$address] = $name; + + return $this->setCc($current); + } + + /** + * Set the Cc addresses of this message. + * + * If $name is passed and the first parameter is a string, this name will be + * associated with the address. + * + * @param mixed $addresses + * @param string $name optional + * + * @return $this + */ + public function setCc($addresses, $name = null) + { + if (!\is_array($addresses) && isset($name)) { + $addresses = [$addresses => $name]; + } + + if (!$this->setHeaderFieldModel('Cc', (array) $addresses)) { + $this->getHeaders()->addMailboxHeader('Cc', (array) $addresses); + } + + return $this; + } + + /** + * Get the Cc address of this message. + * + * @return array + */ + public function getCc() + { + return $this->getHeaderFieldModel('Cc'); + } + + /** + * Add a Bcc: address to this message. + * + * If $name is passed this name will be associated with the address. + * + * @param string $address + * @param string $name optional + * + * @return $this + */ + public function addBcc($address, $name = null) + { + $current = $this->getBcc(); + $current[$address] = $name; + + return $this->setBcc($current); + } + + /** + * Set the Bcc addresses of this message. + * + * If $name is passed and the first parameter is a string, this name will be + * associated with the address. + * + * @param mixed $addresses + * @param string $name optional + * + * @return $this + */ + public function setBcc($addresses, $name = null) + { + if (!\is_array($addresses) && isset($name)) { + $addresses = [$addresses => $name]; + } + + if (!$this->setHeaderFieldModel('Bcc', (array) $addresses)) { + $this->getHeaders()->addMailboxHeader('Bcc', (array) $addresses); + } + + return $this; + } + + /** + * Get the Bcc addresses of this message. + * + * @return array + */ + public function getBcc() + { + return $this->getHeaderFieldModel('Bcc'); + } + + /** + * Set the priority of this message. + * + * The value is an integer where 1 is the highest priority and 5 is the lowest. + * + * @param int $priority + * + * @return $this + */ + public function setPriority($priority) + { + $priorityMap = [ + self::PRIORITY_HIGHEST => 'Highest', + self::PRIORITY_HIGH => 'High', + self::PRIORITY_NORMAL => 'Normal', + self::PRIORITY_LOW => 'Low', + self::PRIORITY_LOWEST => 'Lowest', + ]; + $pMapKeys = array_keys($priorityMap); + if ($priority > max($pMapKeys)) { + $priority = max($pMapKeys); + } elseif ($priority < min($pMapKeys)) { + $priority = min($pMapKeys); + } + if (!$this->setHeaderFieldModel('X-Priority', + sprintf('%d (%s)', $priority, $priorityMap[$priority]))) { + $this->getHeaders()->addTextHeader('X-Priority', + sprintf('%d (%s)', $priority, $priorityMap[$priority])); + } + + return $this; + } + + /** + * Get the priority of this message. + * + * The returned value is an integer where 1 is the highest priority and 5 + * is the lowest. + * + * @return int + */ + public function getPriority() + { + list($priority) = sscanf($this->getHeaderFieldModel('X-Priority'), + '%[1-5]' + ); + + return $priority ?? 3; + } + + /** + * Ask for a delivery receipt from the recipient to be sent to $addresses. + * + * @param array $addresses + * + * @return $this + */ + public function setReadReceiptTo($addresses) + { + if (!$this->setHeaderFieldModel('Disposition-Notification-To', $addresses)) { + $this->getHeaders() + ->addMailboxHeader('Disposition-Notification-To', $addresses); + } + + return $this; + } + + /** + * Get the addresses to which a read-receipt will be sent. + * + * @return string + */ + public function getReadReceiptTo() + { + return $this->getHeaderFieldModel('Disposition-Notification-To'); + } + + /** + * Attach a {@link Swift_Mime_SimpleMimeEntity} such as an Attachment or MimePart. + * + * @return $this + */ + public function attach(Swift_Mime_SimpleMimeEntity $entity) + { + $this->setChildren(array_merge($this->getChildren(), [$entity])); + + return $this; + } + + /** + * Remove an already attached entity. + * + * @return $this + */ + public function detach(Swift_Mime_SimpleMimeEntity $entity) + { + $newChildren = []; + foreach ($this->getChildren() as $child) { + if ($entity !== $child) { + $newChildren[] = $child; + } + } + $this->setChildren($newChildren); + + return $this; + } + + /** + * Attach a {@link Swift_Mime_SimpleMimeEntity} and return it's CID source. + * + * This method should be used when embedding images or other data in a message. + * + * @return string + */ + public function embed(Swift_Mime_SimpleMimeEntity $entity) + { + $this->attach($entity); + + return 'cid:'.$entity->getId(); + } + + /** + * Get this message as a complete string. + * + * @return string + */ + public function toString() + { + if (\count($children = $this->getChildren()) > 0 && '' != $this->getBody()) { + $this->setChildren(array_merge([$this->becomeMimePart()], $children)); + $string = parent::toString(); + $this->setChildren($children); + } else { + $string = parent::toString(); + } + + return $string; + } + + /** + * Returns a string representation of this object. + * + * @see toString() + * + * @return string + */ + public function __toString() + { + return $this->toString(); + } + + /** + * Write this message to a {@link Swift_InputByteStream}. + */ + public function toByteStream(Swift_InputByteStream $is) + { + if (\count($children = $this->getChildren()) > 0 && '' != $this->getBody()) { + $this->setChildren(array_merge([$this->becomeMimePart()], $children)); + parent::toByteStream($is); + $this->setChildren($children); + } else { + parent::toByteStream($is); + } + } + + /** @see Swift_Mime_SimpleMimeEntity::getIdField() */ + protected function getIdField() + { + return 'Message-ID'; + } + + /** Turn the body of this message into a child of itself if needed */ + protected function becomeMimePart() + { + $part = new parent($this->getHeaders()->newInstance(), $this->getEncoder(), + $this->getCache(), $this->getIdGenerator(), $this->userCharset + ); + $part->setContentType($this->userContentType); + $part->setBody($this->getBody()); + $part->setFormat($this->userFormat); + $part->setDelSp($this->userDelSp); + $part->setNestingLevel($this->getTopNestingLevel()); + + return $part; + } + + /** Get the highest nesting level nested inside this message */ + private function getTopNestingLevel() + { + $highestLevel = $this->getNestingLevel(); + foreach ($this->getChildren() as $child) { + $childLevel = $child->getNestingLevel(); + if ($highestLevel < $childLevel) { + $highestLevel = $childLevel; + } + } + + return $highestLevel; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleMimeEntity.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleMimeEntity.php index 03eaf472dd5..668d076fb32 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleMimeEntity.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleMimeEntity.php @@ -15,812 +15,812 @@ */ class Swift_Mime_SimpleMimeEntity implements Swift_Mime_CharsetObserver, Swift_Mime_EncodingObserver { - /** Main message document; there can only be one of these */ - const LEVEL_TOP = 16; - - /** An entity which nests with the same precedence as an attachment */ - const LEVEL_MIXED = 256; - - /** An entity which nests with the same precedence as a mime part */ - const LEVEL_ALTERNATIVE = 4096; - - /** An entity which nests with the same precedence as embedded content */ - const LEVEL_RELATED = 65536; - - /** A collection of Headers for this mime entity */ - private $headers; - - /** The body as a string, or a stream */ - private $body; - - /** The encoder that encodes the body into a streamable format */ - private $encoder; - - /** Message ID generator */ - private $idGenerator; - - /** A mime boundary, if any is used */ - private $boundary; - - /** Mime types to be used based on the nesting level */ - private $compositeRanges = [ - 'multipart/mixed' => [self::LEVEL_TOP, self::LEVEL_MIXED], - 'multipart/alternative' => [self::LEVEL_MIXED, self::LEVEL_ALTERNATIVE], - 'multipart/related' => [self::LEVEL_ALTERNATIVE, self::LEVEL_RELATED], - ]; - - /** A set of filter rules to define what level an entity should be nested at */ - private $compoundLevelFilters = []; - - /** The nesting level of this entity */ - private $nestingLevel = self::LEVEL_ALTERNATIVE; - - /** A KeyCache instance used during encoding and streaming */ - private $cache; - - /** Direct descendants of this entity */ - private $immediateChildren = []; - - /** All descendants of this entity */ - private $children = []; - - /** The maximum line length of the body of this entity */ - private $maxLineLength = 78; - - /** The order in which alternative mime types should appear */ - private $alternativePartOrder = [ - 'text/plain' => 1, - 'text/html' => 2, - 'multipart/related' => 3, - ]; - - /** The CID of this entity */ - private $id; - - /** The key used for accessing the cache */ - private $cacheKey; - - protected $userContentType; - - /** - * Create a new SimpleMimeEntity with $headers, $encoder and $cache. - */ - public function __construct(Swift_Mime_SimpleHeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_IdGenerator $idGenerator) - { - $this->cacheKey = bin2hex(random_bytes(16)); // set 32 hex values - $this->cache = $cache; - $this->headers = $headers; - $this->idGenerator = $idGenerator; - $this->setEncoder($encoder); - $this->headers->defineOrdering(['Content-Type', 'Content-Transfer-Encoding']); - - // This array specifies that, when the entire MIME document contains - // $compoundLevel, then for each child within $level, if its Content-Type - // is $contentType then it should be treated as if it's level is - // $neededLevel instead. I tried to write that unambiguously! :-\ - // Data Structure: - // array ( - // $compoundLevel => array( - // $level => array( - // $contentType => $neededLevel - // ) - // ) - // ) - - $this->compoundLevelFilters = [ - (self::LEVEL_ALTERNATIVE + self::LEVEL_RELATED) => [ - self::LEVEL_ALTERNATIVE => [ - 'text/plain' => self::LEVEL_ALTERNATIVE, - 'text/html' => self::LEVEL_RELATED, - ], - ], - ]; - - $this->id = $this->idGenerator->generateId(); - } - - /** - * Generate a new Content-ID or Message-ID for this MIME entity. - * - * @return string - */ - public function generateId() - { - $this->setId($this->idGenerator->generateId()); - - return $this->id; - } - - /** - * Get the {@link Swift_Mime_SimpleHeaderSet} for this entity. - * - * @return Swift_Mime_SimpleHeaderSet - */ - public function getHeaders() - { - return $this->headers; - } - - /** - * Get the nesting level of this entity. - * - * @see LEVEL_TOP, LEVEL_MIXED, LEVEL_RELATED, LEVEL_ALTERNATIVE - * - * @return int - */ - public function getNestingLevel() - { - return $this->nestingLevel; - } - - /** - * Get the Content-type of this entity. - * - * @return string - */ - public function getContentType() - { - return $this->getHeaderFieldModel('Content-Type'); - } - - /** - * Get the Body Content-type of this entity. - * - * @return string - */ - public function getBodyContentType() - { - return $this->userContentType; - } - - /** - * Set the Content-type of this entity. - * - * @param string $type - * - * @return $this - */ - public function setContentType($type) - { - $this->setContentTypeInHeaders($type); - // Keep track of the value so that if the content-type changes automatically - // due to added child entities, it can be restored if they are later removed - $this->userContentType = $type; - - return $this; - } - - /** - * Get the CID of this entity. - * - * The CID will only be present in headers if a Content-ID header is present. - * - * @return string - */ - public function getId() - { - $tmp = (array) $this->getHeaderFieldModel($this->getIdField()); - - return $this->headers->has($this->getIdField()) ? current($tmp) : $this->id; - } - - /** - * Set the CID of this entity. - * - * @param string $id - * - * @return $this - */ - public function setId($id) - { - if (!$this->setHeaderFieldModel($this->getIdField(), $id)) { - $this->headers->addIdHeader($this->getIdField(), $id); - } - $this->id = $id; - - return $this; - } - - /** - * Get the description of this entity. - * - * This value comes from the Content-Description header if set. - * - * @return string - */ - public function getDescription() - { - return $this->getHeaderFieldModel('Content-Description'); - } - - /** - * Set the description of this entity. - * - * This method sets a value in the Content-ID header. - * - * @param string $description - * - * @return $this - */ - public function setDescription($description) - { - if (!$this->setHeaderFieldModel('Content-Description', $description)) { - $this->headers->addTextHeader('Content-Description', $description); - } - - return $this; - } - - /** - * Get the maximum line length of the body of this entity. - * - * @return int - */ - public function getMaxLineLength() - { - return $this->maxLineLength; - } - - /** - * Set the maximum line length of lines in this body. - * - * Though not enforced by the library, lines should not exceed 1000 chars. - * - * @param int $length - * - * @return $this - */ - public function setMaxLineLength($length) - { - $this->maxLineLength = $length; - - return $this; - } - - /** - * Get all children added to this entity. - * - * @return Swift_Mime_SimpleMimeEntity[] - */ - public function getChildren() - { - return $this->children; - } - - /** - * Set all children of this entity. - * - * @param Swift_Mime_SimpleMimeEntity[] $children - * @param int $compoundLevel For internal use only - * - * @return $this - */ - public function setChildren(array $children, $compoundLevel = null) - { - // TODO: Try to refactor this logic - $compoundLevel = $compoundLevel ?? $this->getCompoundLevel($children); - $immediateChildren = []; - $grandchildren = []; - $newContentType = $this->userContentType; - - foreach ($children as $child) { - $level = $this->getNeededChildLevel($child, $compoundLevel); - if (empty($immediateChildren)) { - //first iteration - $immediateChildren = [$child]; - } else { - $nextLevel = $this->getNeededChildLevel($immediateChildren[0], $compoundLevel); - if ($nextLevel == $level) { - $immediateChildren[] = $child; - } elseif ($level < $nextLevel) { - // Re-assign immediateChildren to grandchildren - $grandchildren = array_merge($grandchildren, $immediateChildren); - // Set new children - $immediateChildren = [$child]; - } else { - $grandchildren[] = $child; - } - } - } - - if ($immediateChildren) { - $lowestLevel = $this->getNeededChildLevel($immediateChildren[0], $compoundLevel); - - // Determine which composite media type is needed to accommodate the - // immediate children - foreach ($this->compositeRanges as $mediaType => $range) { - if ($lowestLevel > $range[0] && $lowestLevel <= $range[1]) { - $newContentType = $mediaType; - - break; - } - } - - // Put any grandchildren in a subpart - if (!empty($grandchildren)) { - $subentity = $this->createChild(); - $subentity->setNestingLevel($lowestLevel); - $subentity->setChildren($grandchildren, $compoundLevel); - array_unshift($immediateChildren, $subentity); - } - } - - $this->immediateChildren = $immediateChildren; - $this->children = $children; - $this->setContentTypeInHeaders($newContentType); - $this->fixHeaders(); - $this->sortChildren(); - - return $this; - } - - /** - * Get the body of this entity as a string. - * - * @return string - */ - public function getBody() - { - return $this->body instanceof Swift_OutputByteStream ? $this->readStream($this->body) : $this->body; - } - - /** - * Set the body of this entity, either as a string, or as an instance of - * {@link Swift_OutputByteStream}. - * - * @param mixed $body - * @param string $contentType optional - * - * @return $this - */ - public function setBody($body, $contentType = null) - { - if ($body !== $this->body) { - $this->clearCache(); - } - - $this->body = $body; - if (null !== $contentType) { - $this->setContentType($contentType); - } - - return $this; - } - - /** - * Get the encoder used for the body of this entity. - * - * @return Swift_Mime_ContentEncoder - */ - public function getEncoder() - { - return $this->encoder; - } - - /** - * Set the encoder used for the body of this entity. - * - * @return $this - */ - public function setEncoder(Swift_Mime_ContentEncoder $encoder) - { - if ($encoder !== $this->encoder) { - $this->clearCache(); - } - - $this->encoder = $encoder; - $this->setEncoding($encoder->getName()); - $this->notifyEncoderChanged($encoder); - - return $this; - } - - /** - * Get the boundary used to separate children in this entity. - * - * @return string - */ - public function getBoundary() - { - if (!isset($this->boundary)) { - $this->boundary = '_=_swift_'.time().'_'.bin2hex(random_bytes(16)).'_=_'; - } - - return $this->boundary; - } - - /** - * Set the boundary used to separate children in this entity. - * - * @param string $boundary - * - * @throws Swift_RfcComplianceException - * - * @return $this - */ - public function setBoundary($boundary) - { - $this->assertValidBoundary($boundary); - $this->boundary = $boundary; - - return $this; - } - - /** - * Receive notification that the charset of this entity, or a parent entity - * has changed. - * - * @param string $charset - */ - public function charsetChanged($charset) - { - $this->notifyCharsetChanged($charset); - } - - /** - * Receive notification that the encoder of this entity or a parent entity - * has changed. - */ - public function encoderChanged(Swift_Mime_ContentEncoder $encoder) - { - $this->notifyEncoderChanged($encoder); - } - - /** - * Get this entire entity as a string. - * - * @return string - */ - public function toString() - { - $string = $this->headers->toString(); - $string .= $this->bodyToString(); - - return $string; - } - - /** - * Get this entire entity as a string. - * - * @return string - */ - protected function bodyToString() - { - $string = ''; - - if (isset($this->body) && empty($this->immediateChildren)) { - if ($this->cache->hasKey($this->cacheKey, 'body')) { - $body = $this->cache->getString($this->cacheKey, 'body'); - } else { - $body = "\r\n".$this->encoder->encodeString($this->getBody(), 0, $this->getMaxLineLength()); - $this->cache->setString($this->cacheKey, 'body', $body, Swift_KeyCache::MODE_WRITE); - } - $string .= $body; - } - - if (!empty($this->immediateChildren)) { - foreach ($this->immediateChildren as $child) { - $string .= "\r\n\r\n--".$this->getBoundary()."\r\n"; - $string .= $child->toString(); - } - $string .= "\r\n\r\n--".$this->getBoundary()."--\r\n"; - } - - return $string; - } - - /** - * Returns a string representation of this object. - * - * @see toString() - * - * @return string - */ - public function __toString() - { - return $this->toString(); - } - - /** - * Write this entire entity to a {@see Swift_InputByteStream}. - */ - public function toByteStream(Swift_InputByteStream $is) - { - $is->write($this->headers->toString()); - $is->commit(); - - $this->bodyToByteStream($is); - } - - /** - * Write this entire entity to a {@link Swift_InputByteStream}. - */ - protected function bodyToByteStream(Swift_InputByteStream $is) - { - if (empty($this->immediateChildren)) { - if (isset($this->body)) { - if ($this->cache->hasKey($this->cacheKey, 'body')) { - $this->cache->exportToByteStream($this->cacheKey, 'body', $is); - } else { - $cacheIs = $this->cache->getInputByteStream($this->cacheKey, 'body'); - if ($cacheIs) { - $is->bind($cacheIs); - } - - $is->write("\r\n"); - - if ($this->body instanceof Swift_OutputByteStream) { - $this->body->setReadPointer(0); - - $this->encoder->encodeByteStream($this->body, $is, 0, $this->getMaxLineLength()); - } else { - $is->write($this->encoder->encodeString($this->getBody(), 0, $this->getMaxLineLength())); - } - - if ($cacheIs) { - $is->unbind($cacheIs); - } - } - } - } - - if (!empty($this->immediateChildren)) { - foreach ($this->immediateChildren as $child) { - $is->write("\r\n\r\n--".$this->getBoundary()."\r\n"); - $child->toByteStream($is); - } - $is->write("\r\n\r\n--".$this->getBoundary()."--\r\n"); - } - } - - /** - * Get the name of the header that provides the ID of this entity. - */ - protected function getIdField() - { - return 'Content-ID'; - } - - /** - * Get the model data (usually an array or a string) for $field. - */ - protected function getHeaderFieldModel($field) - { - if ($this->headers->has($field)) { - return $this->headers->get($field)->getFieldBodyModel(); - } - } - - /** - * Set the model data for $field. - */ - protected function setHeaderFieldModel($field, $model) - { - if ($this->headers->has($field)) { - $this->headers->get($field)->setFieldBodyModel($model); - - return true; - } - - return false; - } - - /** - * Get the parameter value of $parameter on $field header. - */ - protected function getHeaderParameter($field, $parameter) - { - if ($this->headers->has($field)) { - return $this->headers->get($field)->getParameter($parameter); - } - } - - /** - * Set the parameter value of $parameter on $field header. - */ - protected function setHeaderParameter($field, $parameter, $value) - { - if ($this->headers->has($field)) { - $this->headers->get($field)->setParameter($parameter, $value); - - return true; - } - - return false; - } - - /** - * Re-evaluate what content type and encoding should be used on this entity. - */ - protected function fixHeaders() - { - if (\count($this->immediateChildren)) { - $this->setHeaderParameter('Content-Type', 'boundary', - $this->getBoundary() - ); - $this->headers->remove('Content-Transfer-Encoding'); - } else { - $this->setHeaderParameter('Content-Type', 'boundary', null); - $this->setEncoding($this->encoder->getName()); - } - } - - /** - * Get the KeyCache used in this entity. - * - * @return Swift_KeyCache - */ - protected function getCache() - { - return $this->cache; - } - - /** - * Get the ID generator. - * - * @return Swift_IdGenerator - */ - protected function getIdGenerator() - { - return $this->idGenerator; - } - - /** - * Empty the KeyCache for this entity. - */ - protected function clearCache() - { - $this->cache->clearKey($this->cacheKey, 'body'); - } - - private function readStream(Swift_OutputByteStream $os) - { - $string = ''; - while (false !== $bytes = $os->read(8192)) { - $string .= $bytes; - } - - $os->setReadPointer(0); - - return $string; - } - - private function setEncoding($encoding) - { - if (!$this->setHeaderFieldModel('Content-Transfer-Encoding', $encoding)) { - $this->headers->addTextHeader('Content-Transfer-Encoding', $encoding); - } - } - - private function assertValidBoundary($boundary) - { - if (!preg_match('/^[a-z0-9\'\(\)\+_\-,\.\/:=\?\ ]{0,69}[a-z0-9\'\(\)\+_\-,\.\/:=\?]$/Di', $boundary)) { - throw new Swift_RfcComplianceException('Mime boundary set is not RFC 2046 compliant.'); - } - } - - private function setContentTypeInHeaders($type) - { - if (!$this->setHeaderFieldModel('Content-Type', $type)) { - $this->headers->addParameterizedHeader('Content-Type', $type); - } - } - - private function setNestingLevel($level) - { - $this->nestingLevel = $level; - } - - private function getCompoundLevel($children) - { - $level = 0; - foreach ($children as $child) { - $level |= $child->getNestingLevel(); - } - - return $level; - } - - private function getNeededChildLevel($child, $compoundLevel) - { - $filter = []; - foreach ($this->compoundLevelFilters as $bitmask => $rules) { - if (($compoundLevel & $bitmask) === $bitmask) { - $filter = $rules + $filter; - } - } - - $realLevel = $child->getNestingLevel(); - $lowercaseType = strtolower($child->getContentType() ?? ''); - - if (isset($filter[$realLevel]) && isset($filter[$realLevel][$lowercaseType])) { - return $filter[$realLevel][$lowercaseType]; - } - - return $realLevel; - } - - private function createChild() - { - return new self($this->headers->newInstance(), $this->encoder, $this->cache, $this->idGenerator); - } - - private function notifyEncoderChanged(Swift_Mime_ContentEncoder $encoder) - { - foreach ($this->immediateChildren as $child) { - $child->encoderChanged($encoder); - } - } - - private function notifyCharsetChanged($charset) - { - $this->encoder->charsetChanged($charset); - $this->headers->charsetChanged($charset); - foreach ($this->immediateChildren as $child) { - $child->charsetChanged($charset); - } - } - - private function sortChildren() - { - $shouldSort = false; - foreach ($this->immediateChildren as $child) { - // NOTE: This include alternative parts moved into a related part - if (self::LEVEL_ALTERNATIVE == $child->getNestingLevel()) { - $shouldSort = true; - break; - } - } - - // Sort in order of preference, if there is one - if ($shouldSort) { - // Group the messages by order of preference - $sorted = []; - foreach ($this->immediateChildren as $child) { - $type = $child->getContentType(); - $level = \array_key_exists($type, $this->alternativePartOrder) ? $this->alternativePartOrder[$type] : max($this->alternativePartOrder) + 1; - - if (empty($sorted[$level])) { - $sorted[$level] = []; - } - - $sorted[$level][] = $child; - } - - ksort($sorted); - - $this->immediateChildren = array_reduce($sorted, 'array_merge', []); - } - } - - /** - * Empties it's own contents from the cache. - */ - public function __destruct() - { - if ($this->cache instanceof Swift_KeyCache) { - $this->cache->clearAll($this->cacheKey); - } - } - - /** - * Make a deep copy of object. - */ - public function __clone() - { - $this->headers = clone $this->headers; - $this->encoder = clone $this->encoder; - $this->cacheKey = bin2hex(random_bytes(16)); // set 32 hex values - $children = []; - foreach ($this->children as $pos => $child) { - $children[$pos] = clone $child; - } - $this->setChildren($children); - } - - public function __wakeup() - { - $this->cacheKey = bin2hex(random_bytes(16)); // set 32 hex values - $this->cache = new Swift_KeyCache_ArrayKeyCache(new Swift_KeyCache_SimpleKeyCacheInputStream()); - } + /** Main message document; there can only be one of these */ + const LEVEL_TOP = 16; + + /** An entity which nests with the same precedence as an attachment */ + const LEVEL_MIXED = 256; + + /** An entity which nests with the same precedence as a mime part */ + const LEVEL_ALTERNATIVE = 4096; + + /** An entity which nests with the same precedence as embedded content */ + const LEVEL_RELATED = 65536; + + /** A collection of Headers for this mime entity */ + private $headers; + + /** The body as a string, or a stream */ + private $body; + + /** The encoder that encodes the body into a streamable format */ + private $encoder; + + /** Message ID generator */ + private $idGenerator; + + /** A mime boundary, if any is used */ + private $boundary; + + /** Mime types to be used based on the nesting level */ + private $compositeRanges = [ + 'multipart/mixed' => [self::LEVEL_TOP, self::LEVEL_MIXED], + 'multipart/alternative' => [self::LEVEL_MIXED, self::LEVEL_ALTERNATIVE], + 'multipart/related' => [self::LEVEL_ALTERNATIVE, self::LEVEL_RELATED], + ]; + + /** A set of filter rules to define what level an entity should be nested at */ + private $compoundLevelFilters = []; + + /** The nesting level of this entity */ + private $nestingLevel = self::LEVEL_ALTERNATIVE; + + /** A KeyCache instance used during encoding and streaming */ + private $cache; + + /** Direct descendants of this entity */ + private $immediateChildren = []; + + /** All descendants of this entity */ + private $children = []; + + /** The maximum line length of the body of this entity */ + private $maxLineLength = 78; + + /** The order in which alternative mime types should appear */ + private $alternativePartOrder = [ + 'text/plain' => 1, + 'text/html' => 2, + 'multipart/related' => 3, + ]; + + /** The CID of this entity */ + private $id; + + /** The key used for accessing the cache */ + private $cacheKey; + + protected $userContentType; + + /** + * Create a new SimpleMimeEntity with $headers, $encoder and $cache. + */ + public function __construct(Swift_Mime_SimpleHeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_IdGenerator $idGenerator) + { + $this->cacheKey = bin2hex(random_bytes(16)); // set 32 hex values + $this->cache = $cache; + $this->headers = $headers; + $this->idGenerator = $idGenerator; + $this->setEncoder($encoder); + $this->headers->defineOrdering(['Content-Type', 'Content-Transfer-Encoding']); + + // This array specifies that, when the entire MIME document contains + // $compoundLevel, then for each child within $level, if its Content-Type + // is $contentType then it should be treated as if it's level is + // $neededLevel instead. I tried to write that unambiguously! :-\ + // Data Structure: + // array ( + // $compoundLevel => array( + // $level => array( + // $contentType => $neededLevel + // ) + // ) + // ) + + $this->compoundLevelFilters = [ + (self::LEVEL_ALTERNATIVE + self::LEVEL_RELATED) => [ + self::LEVEL_ALTERNATIVE => [ + 'text/plain' => self::LEVEL_ALTERNATIVE, + 'text/html' => self::LEVEL_RELATED, + ], + ], + ]; + + $this->id = $this->idGenerator->generateId(); + } + + /** + * Generate a new Content-ID or Message-ID for this MIME entity. + * + * @return string + */ + public function generateId() + { + $this->setId($this->idGenerator->generateId()); + + return $this->id; + } + + /** + * Get the {@link Swift_Mime_SimpleHeaderSet} for this entity. + * + * @return Swift_Mime_SimpleHeaderSet + */ + public function getHeaders() + { + return $this->headers; + } + + /** + * Get the nesting level of this entity. + * + * @see LEVEL_TOP, LEVEL_MIXED, LEVEL_RELATED, LEVEL_ALTERNATIVE + * + * @return int + */ + public function getNestingLevel() + { + return $this->nestingLevel; + } + + /** + * Get the Content-type of this entity. + * + * @return string + */ + public function getContentType() + { + return $this->getHeaderFieldModel('Content-Type'); + } + + /** + * Get the Body Content-type of this entity. + * + * @return string + */ + public function getBodyContentType() + { + return $this->userContentType; + } + + /** + * Set the Content-type of this entity. + * + * @param string $type + * + * @return $this + */ + public function setContentType($type) + { + $this->setContentTypeInHeaders($type); + // Keep track of the value so that if the content-type changes automatically + // due to added child entities, it can be restored if they are later removed + $this->userContentType = $type; + + return $this; + } + + /** + * Get the CID of this entity. + * + * The CID will only be present in headers if a Content-ID header is present. + * + * @return string + */ + public function getId() + { + $tmp = (array) $this->getHeaderFieldModel($this->getIdField()); + + return $this->headers->has($this->getIdField()) ? current($tmp) : $this->id; + } + + /** + * Set the CID of this entity. + * + * @param string $id + * + * @return $this + */ + public function setId($id) + { + if (!$this->setHeaderFieldModel($this->getIdField(), $id)) { + $this->headers->addIdHeader($this->getIdField(), $id); + } + $this->id = $id; + + return $this; + } + + /** + * Get the description of this entity. + * + * This value comes from the Content-Description header if set. + * + * @return string + */ + public function getDescription() + { + return $this->getHeaderFieldModel('Content-Description'); + } + + /** + * Set the description of this entity. + * + * This method sets a value in the Content-ID header. + * + * @param string $description + * + * @return $this + */ + public function setDescription($description) + { + if (!$this->setHeaderFieldModel('Content-Description', $description)) { + $this->headers->addTextHeader('Content-Description', $description); + } + + return $this; + } + + /** + * Get the maximum line length of the body of this entity. + * + * @return int + */ + public function getMaxLineLength() + { + return $this->maxLineLength; + } + + /** + * Set the maximum line length of lines in this body. + * + * Though not enforced by the library, lines should not exceed 1000 chars. + * + * @param int $length + * + * @return $this + */ + public function setMaxLineLength($length) + { + $this->maxLineLength = $length; + + return $this; + } + + /** + * Get all children added to this entity. + * + * @return Swift_Mime_SimpleMimeEntity[] + */ + public function getChildren() + { + return $this->children; + } + + /** + * Set all children of this entity. + * + * @param Swift_Mime_SimpleMimeEntity[] $children + * @param int $compoundLevel For internal use only + * + * @return $this + */ + public function setChildren(array $children, $compoundLevel = null) + { + // TODO: Try to refactor this logic + $compoundLevel = $compoundLevel ?? $this->getCompoundLevel($children); + $immediateChildren = []; + $grandchildren = []; + $newContentType = $this->userContentType; + + foreach ($children as $child) { + $level = $this->getNeededChildLevel($child, $compoundLevel); + if (empty($immediateChildren)) { + //first iteration + $immediateChildren = [$child]; + } else { + $nextLevel = $this->getNeededChildLevel($immediateChildren[0], $compoundLevel); + if ($nextLevel == $level) { + $immediateChildren[] = $child; + } elseif ($level < $nextLevel) { + // Re-assign immediateChildren to grandchildren + $grandchildren = array_merge($grandchildren, $immediateChildren); + // Set new children + $immediateChildren = [$child]; + } else { + $grandchildren[] = $child; + } + } + } + + if ($immediateChildren) { + $lowestLevel = $this->getNeededChildLevel($immediateChildren[0], $compoundLevel); + + // Determine which composite media type is needed to accommodate the + // immediate children + foreach ($this->compositeRanges as $mediaType => $range) { + if ($lowestLevel > $range[0] && $lowestLevel <= $range[1]) { + $newContentType = $mediaType; + + break; + } + } + + // Put any grandchildren in a subpart + if (!empty($grandchildren)) { + $subentity = $this->createChild(); + $subentity->setNestingLevel($lowestLevel); + $subentity->setChildren($grandchildren, $compoundLevel); + array_unshift($immediateChildren, $subentity); + } + } + + $this->immediateChildren = $immediateChildren; + $this->children = $children; + $this->setContentTypeInHeaders($newContentType); + $this->fixHeaders(); + $this->sortChildren(); + + return $this; + } + + /** + * Get the body of this entity as a string. + * + * @return string + */ + public function getBody() + { + return $this->body instanceof Swift_OutputByteStream ? $this->readStream($this->body) : $this->body; + } + + /** + * Set the body of this entity, either as a string, or as an instance of + * {@link Swift_OutputByteStream}. + * + * @param mixed $body + * @param string $contentType optional + * + * @return $this + */ + public function setBody($body, $contentType = null) + { + if ($body !== $this->body) { + $this->clearCache(); + } + + $this->body = $body; + if (null !== $contentType) { + $this->setContentType($contentType); + } + + return $this; + } + + /** + * Get the encoder used for the body of this entity. + * + * @return Swift_Mime_ContentEncoder + */ + public function getEncoder() + { + return $this->encoder; + } + + /** + * Set the encoder used for the body of this entity. + * + * @return $this + */ + public function setEncoder(Swift_Mime_ContentEncoder $encoder) + { + if ($encoder !== $this->encoder) { + $this->clearCache(); + } + + $this->encoder = $encoder; + $this->setEncoding($encoder->getName()); + $this->notifyEncoderChanged($encoder); + + return $this; + } + + /** + * Get the boundary used to separate children in this entity. + * + * @return string + */ + public function getBoundary() + { + if (!isset($this->boundary)) { + $this->boundary = '_=_swift_'.time().'_'.bin2hex(random_bytes(16)).'_=_'; + } + + return $this->boundary; + } + + /** + * Set the boundary used to separate children in this entity. + * + * @param string $boundary + * + * @throws Swift_RfcComplianceException + * + * @return $this + */ + public function setBoundary($boundary) + { + $this->assertValidBoundary($boundary); + $this->boundary = $boundary; + + return $this; + } + + /** + * Receive notification that the charset of this entity, or a parent entity + * has changed. + * + * @param string $charset + */ + public function charsetChanged($charset) + { + $this->notifyCharsetChanged($charset); + } + + /** + * Receive notification that the encoder of this entity or a parent entity + * has changed. + */ + public function encoderChanged(Swift_Mime_ContentEncoder $encoder) + { + $this->notifyEncoderChanged($encoder); + } + + /** + * Get this entire entity as a string. + * + * @return string + */ + public function toString() + { + $string = $this->headers->toString(); + $string .= $this->bodyToString(); + + return $string; + } + + /** + * Get this entire entity as a string. + * + * @return string + */ + protected function bodyToString() + { + $string = ''; + + if (isset($this->body) && empty($this->immediateChildren)) { + if ($this->cache->hasKey($this->cacheKey, 'body')) { + $body = $this->cache->getString($this->cacheKey, 'body'); + } else { + $body = "\r\n".$this->encoder->encodeString($this->getBody(), 0, $this->getMaxLineLength()); + $this->cache->setString($this->cacheKey, 'body', $body, Swift_KeyCache::MODE_WRITE); + } + $string .= $body; + } + + if (!empty($this->immediateChildren)) { + foreach ($this->immediateChildren as $child) { + $string .= "\r\n\r\n--".$this->getBoundary()."\r\n"; + $string .= $child->toString(); + } + $string .= "\r\n\r\n--".$this->getBoundary()."--\r\n"; + } + + return $string; + } + + /** + * Returns a string representation of this object. + * + * @see toString() + * + * @return string + */ + public function __toString() + { + return $this->toString(); + } + + /** + * Write this entire entity to a {@see Swift_InputByteStream}. + */ + public function toByteStream(Swift_InputByteStream $is) + { + $is->write($this->headers->toString()); + $is->commit(); + + $this->bodyToByteStream($is); + } + + /** + * Write this entire entity to a {@link Swift_InputByteStream}. + */ + protected function bodyToByteStream(Swift_InputByteStream $is) + { + if (empty($this->immediateChildren)) { + if (isset($this->body)) { + if ($this->cache->hasKey($this->cacheKey, 'body')) { + $this->cache->exportToByteStream($this->cacheKey, 'body', $is); + } else { + $cacheIs = $this->cache->getInputByteStream($this->cacheKey, 'body'); + if ($cacheIs) { + $is->bind($cacheIs); + } + + $is->write("\r\n"); + + if ($this->body instanceof Swift_OutputByteStream) { + $this->body->setReadPointer(0); + + $this->encoder->encodeByteStream($this->body, $is, 0, $this->getMaxLineLength()); + } else { + $is->write($this->encoder->encodeString($this->getBody(), 0, $this->getMaxLineLength())); + } + + if ($cacheIs) { + $is->unbind($cacheIs); + } + } + } + } + + if (!empty($this->immediateChildren)) { + foreach ($this->immediateChildren as $child) { + $is->write("\r\n\r\n--".$this->getBoundary()."\r\n"); + $child->toByteStream($is); + } + $is->write("\r\n\r\n--".$this->getBoundary()."--\r\n"); + } + } + + /** + * Get the name of the header that provides the ID of this entity. + */ + protected function getIdField() + { + return 'Content-ID'; + } + + /** + * Get the model data (usually an array or a string) for $field. + */ + protected function getHeaderFieldModel($field) + { + if ($this->headers->has($field)) { + return $this->headers->get($field)->getFieldBodyModel(); + } + } + + /** + * Set the model data for $field. + */ + protected function setHeaderFieldModel($field, $model) + { + if ($this->headers->has($field)) { + $this->headers->get($field)->setFieldBodyModel($model); + + return true; + } + + return false; + } + + /** + * Get the parameter value of $parameter on $field header. + */ + protected function getHeaderParameter($field, $parameter) + { + if ($this->headers->has($field)) { + return $this->headers->get($field)->getParameter($parameter); + } + } + + /** + * Set the parameter value of $parameter on $field header. + */ + protected function setHeaderParameter($field, $parameter, $value) + { + if ($this->headers->has($field)) { + $this->headers->get($field)->setParameter($parameter, $value); + + return true; + } + + return false; + } + + /** + * Re-evaluate what content type and encoding should be used on this entity. + */ + protected function fixHeaders() + { + if (\count($this->immediateChildren)) { + $this->setHeaderParameter('Content-Type', 'boundary', + $this->getBoundary() + ); + $this->headers->remove('Content-Transfer-Encoding'); + } else { + $this->setHeaderParameter('Content-Type', 'boundary', null); + $this->setEncoding($this->encoder->getName()); + } + } + + /** + * Get the KeyCache used in this entity. + * + * @return Swift_KeyCache + */ + protected function getCache() + { + return $this->cache; + } + + /** + * Get the ID generator. + * + * @return Swift_IdGenerator + */ + protected function getIdGenerator() + { + return $this->idGenerator; + } + + /** + * Empty the KeyCache for this entity. + */ + protected function clearCache() + { + $this->cache->clearKey($this->cacheKey, 'body'); + } + + private function readStream(Swift_OutputByteStream $os) + { + $string = ''; + while (false !== $bytes = $os->read(8192)) { + $string .= $bytes; + } + + $os->setReadPointer(0); + + return $string; + } + + private function setEncoding($encoding) + { + if (!$this->setHeaderFieldModel('Content-Transfer-Encoding', $encoding)) { + $this->headers->addTextHeader('Content-Transfer-Encoding', $encoding); + } + } + + private function assertValidBoundary($boundary) + { + if (!preg_match('/^[a-z0-9\'\(\)\+_\-,\.\/:=\?\ ]{0,69}[a-z0-9\'\(\)\+_\-,\.\/:=\?]$/Di', $boundary)) { + throw new Swift_RfcComplianceException('Mime boundary set is not RFC 2046 compliant.'); + } + } + + private function setContentTypeInHeaders($type) + { + if (!$this->setHeaderFieldModel('Content-Type', $type)) { + $this->headers->addParameterizedHeader('Content-Type', $type); + } + } + + private function setNestingLevel($level) + { + $this->nestingLevel = $level; + } + + private function getCompoundLevel($children) + { + $level = 0; + foreach ($children as $child) { + $level |= $child->getNestingLevel(); + } + + return $level; + } + + private function getNeededChildLevel($child, $compoundLevel) + { + $filter = []; + foreach ($this->compoundLevelFilters as $bitmask => $rules) { + if (($compoundLevel & $bitmask) === $bitmask) { + $filter = $rules + $filter; + } + } + + $realLevel = $child->getNestingLevel(); + $lowercaseType = strtolower($child->getContentType() ?? ''); + + if (isset($filter[$realLevel]) && isset($filter[$realLevel][$lowercaseType])) { + return $filter[$realLevel][$lowercaseType]; + } + + return $realLevel; + } + + private function createChild() + { + return new self($this->headers->newInstance(), $this->encoder, $this->cache, $this->idGenerator); + } + + private function notifyEncoderChanged(Swift_Mime_ContentEncoder $encoder) + { + foreach ($this->immediateChildren as $child) { + $child->encoderChanged($encoder); + } + } + + private function notifyCharsetChanged($charset) + { + $this->encoder->charsetChanged($charset); + $this->headers->charsetChanged($charset); + foreach ($this->immediateChildren as $child) { + $child->charsetChanged($charset); + } + } + + private function sortChildren() + { + $shouldSort = false; + foreach ($this->immediateChildren as $child) { + // NOTE: This include alternative parts moved into a related part + if (self::LEVEL_ALTERNATIVE == $child->getNestingLevel()) { + $shouldSort = true; + break; + } + } + + // Sort in order of preference, if there is one + if ($shouldSort) { + // Group the messages by order of preference + $sorted = []; + foreach ($this->immediateChildren as $child) { + $type = $child->getContentType(); + $level = \array_key_exists($type, $this->alternativePartOrder) ? $this->alternativePartOrder[$type] : max($this->alternativePartOrder) + 1; + + if (empty($sorted[$level])) { + $sorted[$level] = []; + } + + $sorted[$level][] = $child; + } + + ksort($sorted); + + $this->immediateChildren = array_reduce($sorted, 'array_merge', []); + } + } + + /** + * Empties it's own contents from the cache. + */ + public function __destruct() + { + if ($this->cache instanceof Swift_KeyCache) { + $this->cache->clearAll($this->cacheKey); + } + } + + /** + * Make a deep copy of object. + */ + public function __clone() + { + $this->headers = clone $this->headers; + $this->encoder = clone $this->encoder; + $this->cacheKey = bin2hex(random_bytes(16)); // set 32 hex values + $children = []; + foreach ($this->children as $pos => $child) { + $children[$pos] = clone $child; + } + $this->setChildren($children); + } + + public function __wakeup() + { + $this->cacheKey = bin2hex(random_bytes(16)); // set 32 hex values + $this->cache = new Swift_KeyCache_ArrayKeyCache(new Swift_KeyCache_SimpleKeyCacheInputStream()); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/MimePart.php b/htdocs/includes/swiftmailer/lib/classes/Swift/MimePart.php index ea97619ad69..e3440ae0cc3 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/MimePart.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/MimePart.php @@ -15,31 +15,31 @@ */ class Swift_MimePart extends Swift_Mime_MimePart { - /** - * Create a new MimePart. - * - * Details may be optionally passed into the constructor. - * - * @param string $body - * @param string $contentType - * @param string $charset - */ - public function __construct($body = null, $contentType = null, $charset = null) - { - \call_user_func_array( - [$this, 'Swift_Mime_MimePart::__construct'], - Swift_DependencyContainer::getInstance() - ->createDependenciesFor('mime.part') - ); + /** + * Create a new MimePart. + * + * Details may be optionally passed into the constructor. + * + * @param string $body + * @param string $contentType + * @param string $charset + */ + public function __construct($body = null, $contentType = null, $charset = null) + { + \call_user_func_array( + [$this, 'Swift_Mime_MimePart::__construct'], + Swift_DependencyContainer::getInstance() + ->createDependenciesFor('mime.part') + ); - if (!isset($charset)) { - $charset = Swift_DependencyContainer::getInstance() - ->lookup('properties.charset'); - } - $this->setBody($body); - $this->setCharset($charset); - if ($contentType) { - $this->setContentType($contentType); - } - } + if (!isset($charset)) { + $charset = Swift_DependencyContainer::getInstance() + ->lookup('properties.charset'); + } + $this->setBody($body); + $this->setCharset($charset); + if ($contentType) { + $this->setContentType($contentType); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/NullTransport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/NullTransport.php index e44b7af982f..5be32bfabac 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/NullTransport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/NullTransport.php @@ -15,12 +15,12 @@ */ class Swift_NullTransport extends Swift_Transport_NullTransport { - public function __construct() - { - \call_user_func_array( - [$this, 'Swift_Transport_NullTransport::__construct'], - Swift_DependencyContainer::getInstance() - ->createDependenciesFor('transport.null') - ); - } + public function __construct() + { + \call_user_func_array( + [$this, 'Swift_Transport_NullTransport::__construct'], + Swift_DependencyContainer::getInstance() + ->createDependenciesFor('transport.null') + ); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/AntiFloodPlugin.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/AntiFloodPlugin.php index 5b1d7deefff..083ee263ec5 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/AntiFloodPlugin.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/AntiFloodPlugin.php @@ -15,123 +15,123 @@ */ class Swift_Plugins_AntiFloodPlugin implements Swift_Events_SendListener, Swift_Plugins_Sleeper { - /** - * The number of emails to send before restarting Transport. - * - * @var int - */ - private $threshold; + /** + * The number of emails to send before restarting Transport. + * + * @var int + */ + private $threshold; - /** - * The number of seconds to sleep for during a restart. - * - * @var int - */ - private $sleep; + /** + * The number of seconds to sleep for during a restart. + * + * @var int + */ + private $sleep; - /** - * The internal counter. - * - * @var int - */ - private $counter = 0; + /** + * The internal counter. + * + * @var int + */ + private $counter = 0; - /** - * The Sleeper instance for sleeping. - * - * @var Swift_Plugins_Sleeper - */ - private $sleeper; + /** + * The Sleeper instance for sleeping. + * + * @var Swift_Plugins_Sleeper + */ + private $sleeper; - /** - * Create a new AntiFloodPlugin with $threshold and $sleep time. - * - * @param int $threshold - * @param int $sleep time - * @param Swift_Plugins_Sleeper $sleeper (not needed really) - */ - public function __construct($threshold = 99, $sleep = 0, Swift_Plugins_Sleeper $sleeper = null) - { - $this->setThreshold($threshold); - $this->setSleepTime($sleep); - $this->sleeper = $sleeper; - } + /** + * Create a new AntiFloodPlugin with $threshold and $sleep time. + * + * @param int $threshold + * @param int $sleep time + * @param Swift_Plugins_Sleeper $sleeper (not needed really) + */ + public function __construct($threshold = 99, $sleep = 0, Swift_Plugins_Sleeper $sleeper = null) + { + $this->setThreshold($threshold); + $this->setSleepTime($sleep); + $this->sleeper = $sleeper; + } - /** - * Set the number of emails to send before restarting. - * - * @param int $threshold - */ - public function setThreshold($threshold) - { - $this->threshold = $threshold; - } + /** + * Set the number of emails to send before restarting. + * + * @param int $threshold + */ + public function setThreshold($threshold) + { + $this->threshold = $threshold; + } - /** - * Get the number of emails to send before restarting. - * - * @return int - */ - public function getThreshold() - { - return $this->threshold; - } + /** + * Get the number of emails to send before restarting. + * + * @return int + */ + public function getThreshold() + { + return $this->threshold; + } - /** - * Set the number of seconds to sleep for during a restart. - * - * @param int $sleep time - */ - public function setSleepTime($sleep) - { - $this->sleep = $sleep; - } + /** + * Set the number of seconds to sleep for during a restart. + * + * @param int $sleep time + */ + public function setSleepTime($sleep) + { + $this->sleep = $sleep; + } - /** - * Get the number of seconds to sleep for during a restart. - * - * @return int - */ - public function getSleepTime() - { - return $this->sleep; - } + /** + * Get the number of seconds to sleep for during a restart. + * + * @return int + */ + public function getSleepTime() + { + return $this->sleep; + } - /** - * Invoked immediately before the Message is sent. - */ - public function beforeSendPerformed(Swift_Events_SendEvent $evt) - { - } + /** + * Invoked immediately before the Message is sent. + */ + public function beforeSendPerformed(Swift_Events_SendEvent $evt) + { + } - /** - * Invoked immediately after the Message is sent. - */ - public function sendPerformed(Swift_Events_SendEvent $evt) - { - ++$this->counter; - if ($this->counter >= $this->threshold) { - $transport = $evt->getTransport(); - $transport->stop(); - if ($this->sleep) { - $this->sleep($this->sleep); - } - $transport->start(); - $this->counter = 0; - } - } + /** + * Invoked immediately after the Message is sent. + */ + public function sendPerformed(Swift_Events_SendEvent $evt) + { + ++$this->counter; + if ($this->counter >= $this->threshold) { + $transport = $evt->getTransport(); + $transport->stop(); + if ($this->sleep) { + $this->sleep($this->sleep); + } + $transport->start(); + $this->counter = 0; + } + } - /** - * Sleep for $seconds. - * - * @param int $seconds - */ - public function sleep($seconds) - { - if (isset($this->sleeper)) { - $this->sleeper->sleep($seconds); - } else { - sleep($seconds); - } - } + /** + * Sleep for $seconds. + * + * @param int $seconds + */ + public function sleep($seconds) + { + if (isset($this->sleeper)) { + $this->sleeper->sleep($seconds); + } else { + sleep($seconds); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/BandwidthMonitorPlugin.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/BandwidthMonitorPlugin.php index 36451f44f1f..efffe57c9fb 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/BandwidthMonitorPlugin.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/BandwidthMonitorPlugin.php @@ -15,140 +15,140 @@ */ class Swift_Plugins_BandwidthMonitorPlugin implements Swift_Events_SendListener, Swift_Events_CommandListener, Swift_Events_ResponseListener, Swift_InputByteStream { - /** - * The outgoing traffic counter. - * - * @var int - */ - private $out = 0; + /** + * The outgoing traffic counter. + * + * @var int + */ + private $out = 0; - /** - * The incoming traffic counter. - * - * @var int - */ - private $in = 0; + /** + * The incoming traffic counter. + * + * @var int + */ + private $in = 0; - /** Bound byte streams */ - private $mirrors = []; + /** Bound byte streams */ + private $mirrors = []; - /** - * Not used. - */ - public function beforeSendPerformed(Swift_Events_SendEvent $evt) - { - } + /** + * Not used. + */ + public function beforeSendPerformed(Swift_Events_SendEvent $evt) + { + } - /** - * Invoked immediately after the Message is sent. - */ - public function sendPerformed(Swift_Events_SendEvent $evt) - { - $message = $evt->getMessage(); - $message->toByteStream($this); - } + /** + * Invoked immediately after the Message is sent. + */ + public function sendPerformed(Swift_Events_SendEvent $evt) + { + $message = $evt->getMessage(); + $message->toByteStream($this); + } - /** - * Invoked immediately following a command being sent. - */ - public function commandSent(Swift_Events_CommandEvent $evt) - { - $command = $evt->getCommand(); - $this->out += \strlen($command); - } + /** + * Invoked immediately following a command being sent. + */ + public function commandSent(Swift_Events_CommandEvent $evt) + { + $command = $evt->getCommand(); + $this->out += \strlen($command); + } - /** - * Invoked immediately following a response coming back. - */ - public function responseReceived(Swift_Events_ResponseEvent $evt) - { - $response = $evt->getResponse(); - $this->in += \strlen($response); - } + /** + * Invoked immediately following a response coming back. + */ + public function responseReceived(Swift_Events_ResponseEvent $evt) + { + $response = $evt->getResponse(); + $this->in += \strlen($response); + } - /** - * Called when a message is sent so that the outgoing counter can be increased. - * - * @param string $bytes - */ - public function write($bytes) - { - $this->out += \strlen($bytes); - foreach ($this->mirrors as $stream) { - $stream->write($bytes); - } - } + /** + * Called when a message is sent so that the outgoing counter can be increased. + * + * @param string $bytes + */ + public function write($bytes) + { + $this->out += \strlen($bytes); + foreach ($this->mirrors as $stream) { + $stream->write($bytes); + } + } - /** - * Not used. - */ - public function commit() - { - } + /** + * Not used. + */ + public function commit() + { + } - /** - * Attach $is to this stream. - * - * The stream acts as an observer, receiving all data that is written. - * All {@link write()} and {@link flushBuffers()} operations will be mirrored. - */ - public function bind(Swift_InputByteStream $is) - { - $this->mirrors[] = $is; - } + /** + * Attach $is to this stream. + * + * The stream acts as an observer, receiving all data that is written. + * All {@link write()} and {@link flushBuffers()} operations will be mirrored. + */ + public function bind(Swift_InputByteStream $is) + { + $this->mirrors[] = $is; + } - /** - * Remove an already bound stream. - * - * If $is is not bound, no errors will be raised. - * If the stream currently has any buffered data it will be written to $is - * before unbinding occurs. - */ - public function unbind(Swift_InputByteStream $is) - { - foreach ($this->mirrors as $k => $stream) { - if ($is === $stream) { - unset($this->mirrors[$k]); - } - } - } + /** + * Remove an already bound stream. + * + * If $is is not bound, no errors will be raised. + * If the stream currently has any buffered data it will be written to $is + * before unbinding occurs. + */ + public function unbind(Swift_InputByteStream $is) + { + foreach ($this->mirrors as $k => $stream) { + if ($is === $stream) { + unset($this->mirrors[$k]); + } + } + } - /** - * Not used. - */ - public function flushBuffers() - { - foreach ($this->mirrors as $stream) { - $stream->flushBuffers(); - } - } + /** + * Not used. + */ + public function flushBuffers() + { + foreach ($this->mirrors as $stream) { + $stream->flushBuffers(); + } + } - /** - * Get the total number of bytes sent to the server. - * - * @return int - */ - public function getBytesOut() - { - return $this->out; - } + /** + * Get the total number of bytes sent to the server. + * + * @return int + */ + public function getBytesOut() + { + return $this->out; + } - /** - * Get the total number of bytes received from the server. - * - * @return int - */ - public function getBytesIn() - { - return $this->in; - } + /** + * Get the total number of bytes received from the server. + * + * @return int + */ + public function getBytesIn() + { + return $this->in; + } - /** - * Reset the internal counters to zero. - */ - public function reset() - { - $this->out = 0; - $this->in = 0; - } + /** + * Reset the internal counters to zero. + */ + public function reset() + { + $this->out = 0; + $this->in = 0; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/DecoratorPlugin.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/DecoratorPlugin.php index 93124c9a5f4..796965dca4b 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/DecoratorPlugin.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/DecoratorPlugin.php @@ -16,185 +16,185 @@ */ class Swift_Plugins_DecoratorPlugin implements Swift_Events_SendListener, Swift_Plugins_Decorator_Replacements { - /** The replacement map */ - private $replacements; + /** The replacement map */ + private $replacements; - /** The body as it was before replacements */ - private $originalBody; + /** The body as it was before replacements */ + private $originalBody; - /** The original headers of the message, before replacements */ - private $originalHeaders = []; + /** The original headers of the message, before replacements */ + private $originalHeaders = []; - /** Bodies of children before they are replaced */ - private $originalChildBodies = []; + /** Bodies of children before they are replaced */ + private $originalChildBodies = []; - /** The Message that was last replaced */ - private $lastMessage; + /** The Message that was last replaced */ + private $lastMessage; - /** - * Create a new DecoratorPlugin with $replacements. - * - * The $replacements can either be an associative array, or an implementation - * of {@link Swift_Plugins_Decorator_Replacements}. - * - * When using an array, it should be of the form: - * - * $replacements = array( - * "address1@domain.tld" => array("{a}" => "b", "{c}" => "d"), - * "address2@domain.tld" => array("{a}" => "x", "{c}" => "y") - * ) - * - * - * When using an instance of {@link Swift_Plugins_Decorator_Replacements}, - * the object should return just the array of replacements for the address - * given to {@link Swift_Plugins_Decorator_Replacements::getReplacementsFor()}. - * - * @param mixed $replacements Array or Swift_Plugins_Decorator_Replacements - */ - public function __construct($replacements) - { - $this->setReplacements($replacements); - } + /** + * Create a new DecoratorPlugin with $replacements. + * + * The $replacements can either be an associative array, or an implementation + * of {@link Swift_Plugins_Decorator_Replacements}. + * + * When using an array, it should be of the form: + * + * $replacements = array( + * "address1@domain.tld" => array("{a}" => "b", "{c}" => "d"), + * "address2@domain.tld" => array("{a}" => "x", "{c}" => "y") + * ) + * + * + * When using an instance of {@link Swift_Plugins_Decorator_Replacements}, + * the object should return just the array of replacements for the address + * given to {@link Swift_Plugins_Decorator_Replacements::getReplacementsFor()}. + * + * @param mixed $replacements Array or Swift_Plugins_Decorator_Replacements + */ + public function __construct($replacements) + { + $this->setReplacements($replacements); + } - /** - * Sets replacements. - * - * @param mixed $replacements Array or Swift_Plugins_Decorator_Replacements - * - * @see __construct() - */ - public function setReplacements($replacements) - { - if (!($replacements instanceof Swift_Plugins_Decorator_Replacements)) { - $this->replacements = (array) $replacements; - } else { - $this->replacements = $replacements; - } - } + /** + * Sets replacements. + * + * @param mixed $replacements Array or Swift_Plugins_Decorator_Replacements + * + * @see __construct() + */ + public function setReplacements($replacements) + { + if (!($replacements instanceof Swift_Plugins_Decorator_Replacements)) { + $this->replacements = (array) $replacements; + } else { + $this->replacements = $replacements; + } + } - /** - * Invoked immediately before the Message is sent. - */ - public function beforeSendPerformed(Swift_Events_SendEvent $evt) - { - $message = $evt->getMessage(); - $this->restoreMessage($message); - $to = array_keys($message->getTo()); - $address = array_shift($to); - if ($replacements = $this->getReplacementsFor($address)) { - $body = $message->getBody(); - $search = array_keys($replacements); - $replace = array_values($replacements); - $bodyReplaced = str_replace( - $search, $replace, $body - ); - if ($body != $bodyReplaced) { - $this->originalBody = $body; - $message->setBody($bodyReplaced); - } + /** + * Invoked immediately before the Message is sent. + */ + public function beforeSendPerformed(Swift_Events_SendEvent $evt) + { + $message = $evt->getMessage(); + $this->restoreMessage($message); + $to = array_keys($message->getTo()); + $address = array_shift($to); + if ($replacements = $this->getReplacementsFor($address)) { + $body = $message->getBody(); + $search = array_keys($replacements); + $replace = array_values($replacements); + $bodyReplaced = str_replace( + $search, $replace, $body + ); + if ($body != $bodyReplaced) { + $this->originalBody = $body; + $message->setBody($bodyReplaced); + } - foreach ($message->getHeaders()->getAll() as $header) { - $body = $header->getFieldBodyModel(); - $count = 0; - if (\is_array($body)) { - $bodyReplaced = []; - foreach ($body as $key => $value) { - $count1 = 0; - $count2 = 0; - $key = \is_string($key) ? str_replace($search, $replace, $key, $count1) : $key; - $value = \is_string($value) ? str_replace($search, $replace, $value, $count2) : $value; - $bodyReplaced[$key] = $value; + foreach ($message->getHeaders()->getAll() as $header) { + $body = $header->getFieldBodyModel(); + $count = 0; + if (\is_array($body)) { + $bodyReplaced = []; + foreach ($body as $key => $value) { + $count1 = 0; + $count2 = 0; + $key = \is_string($key) ? str_replace($search, $replace, $key, $count1) : $key; + $value = \is_string($value) ? str_replace($search, $replace, $value, $count2) : $value; + $bodyReplaced[$key] = $value; - if (!$count && ($count1 || $count2)) { - $count = 1; - } - } - } elseif (\is_string($body)) { - $bodyReplaced = str_replace($search, $replace, $body, $count); - } + if (!$count && ($count1 || $count2)) { + $count = 1; + } + } + } elseif (\is_string($body)) { + $bodyReplaced = str_replace($search, $replace, $body, $count); + } - if ($count) { - $this->originalHeaders[$header->getFieldName()] = $body; - $header->setFieldBodyModel($bodyReplaced); - } - } + if ($count) { + $this->originalHeaders[$header->getFieldName()] = $body; + $header->setFieldBodyModel($bodyReplaced); + } + } - $children = (array) $message->getChildren(); - foreach ($children as $child) { - list($type) = sscanf($child->getContentType(), '%[^/]/%s'); - if ('text' == $type) { - $body = $child->getBody(); - $bodyReplaced = str_replace( - $search, $replace, $body - ); - if ($body != $bodyReplaced) { - $child->setBody($bodyReplaced); - $this->originalChildBodies[$child->getId()] = $body; - } - } - } - $this->lastMessage = $message; - } - } + $children = (array) $message->getChildren(); + foreach ($children as $child) { + list($type) = sscanf($child->getContentType(), '%[^/]/%s'); + if ('text' == $type) { + $body = $child->getBody(); + $bodyReplaced = str_replace( + $search, $replace, $body + ); + if ($body != $bodyReplaced) { + $child->setBody($bodyReplaced); + $this->originalChildBodies[$child->getId()] = $body; + } + } + } + $this->lastMessage = $message; + } + } - /** - * Find a map of replacements for the address. - * - * If this plugin was provided with a delegate instance of - * {@link Swift_Plugins_Decorator_Replacements} then the call will be - * delegated to it. Otherwise, it will attempt to find the replacements - * from the array provided in the constructor. - * - * If no replacements can be found, an empty value (NULL) is returned. - * - * @param string $address - * - * @return array - */ - public function getReplacementsFor($address) - { - if ($this->replacements instanceof Swift_Plugins_Decorator_Replacements) { - return $this->replacements->getReplacementsFor($address); - } + /** + * Find a map of replacements for the address. + * + * If this plugin was provided with a delegate instance of + * {@link Swift_Plugins_Decorator_Replacements} then the call will be + * delegated to it. Otherwise, it will attempt to find the replacements + * from the array provided in the constructor. + * + * If no replacements can be found, an empty value (NULL) is returned. + * + * @param string $address + * + * @return array + */ + public function getReplacementsFor($address) + { + if ($this->replacements instanceof Swift_Plugins_Decorator_Replacements) { + return $this->replacements->getReplacementsFor($address); + } - return $this->replacements[$address] ?? null; - } + return $this->replacements[$address] ?? null; + } - /** - * Invoked immediately after the Message is sent. - */ - public function sendPerformed(Swift_Events_SendEvent $evt) - { - $this->restoreMessage($evt->getMessage()); - } + /** + * Invoked immediately after the Message is sent. + */ + public function sendPerformed(Swift_Events_SendEvent $evt) + { + $this->restoreMessage($evt->getMessage()); + } - /** Restore a changed message back to its original state */ - private function restoreMessage(Swift_Mime_SimpleMessage $message) - { - if ($this->lastMessage === $message) { - if (isset($this->originalBody)) { - $message->setBody($this->originalBody); - $this->originalBody = null; - } - if (!empty($this->originalHeaders)) { - foreach ($message->getHeaders()->getAll() as $header) { - if (\array_key_exists($header->getFieldName(), $this->originalHeaders)) { - $header->setFieldBodyModel($this->originalHeaders[$header->getFieldName()]); - } - } - $this->originalHeaders = []; - } - if (!empty($this->originalChildBodies)) { - $children = (array) $message->getChildren(); - foreach ($children as $child) { - $id = $child->getId(); - if (\array_key_exists($id, $this->originalChildBodies)) { - $child->setBody($this->originalChildBodies[$id]); - } - } - $this->originalChildBodies = []; - } - $this->lastMessage = null; - } - } + /** Restore a changed message back to its original state */ + private function restoreMessage(Swift_Mime_SimpleMessage $message) + { + if ($this->lastMessage === $message) { + if (isset($this->originalBody)) { + $message->setBody($this->originalBody); + $this->originalBody = null; + } + if (!empty($this->originalHeaders)) { + foreach ($message->getHeaders()->getAll() as $header) { + if (\array_key_exists($header->getFieldName(), $this->originalHeaders)) { + $header->setFieldBodyModel($this->originalHeaders[$header->getFieldName()]); + } + } + $this->originalHeaders = []; + } + if (!empty($this->originalChildBodies)) { + $children = (array) $message->getChildren(); + foreach ($children as $child) { + $id = $child->getId(); + if (\array_key_exists($id, $this->originalChildBodies)) { + $child->setBody($this->originalChildBodies[$id]); + } + } + $this->originalChildBodies = []; + } + $this->lastMessage = null; + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/ImpersonatePlugin.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/ImpersonatePlugin.php index 3f4dbbfa40f..69d31f0a465 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/ImpersonatePlugin.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/ImpersonatePlugin.php @@ -15,51 +15,51 @@ */ class Swift_Plugins_ImpersonatePlugin implements Swift_Events_SendListener { - /** - * The sender to impersonate. - * - * @var string - */ - private $sender; + /** + * The sender to impersonate. + * + * @var string + */ + private $sender; - /** - * Create a new ImpersonatePlugin to impersonate $sender. - * - * @param string $sender address - */ - public function __construct($sender) - { - $this->sender = $sender; - } + /** + * Create a new ImpersonatePlugin to impersonate $sender. + * + * @param string $sender address + */ + public function __construct($sender) + { + $this->sender = $sender; + } - /** - * Invoked immediately before the Message is sent. - */ - public function beforeSendPerformed(Swift_Events_SendEvent $evt) - { - $message = $evt->getMessage(); - $headers = $message->getHeaders(); + /** + * Invoked immediately before the Message is sent. + */ + public function beforeSendPerformed(Swift_Events_SendEvent $evt) + { + $message = $evt->getMessage(); + $headers = $message->getHeaders(); - // save current recipients - $headers->addPathHeader('X-Swift-Return-Path', $message->getReturnPath()); + // save current recipients + $headers->addPathHeader('X-Swift-Return-Path', $message->getReturnPath()); - // replace them with the one to send to - $message->setReturnPath($this->sender); - } + // replace them with the one to send to + $message->setReturnPath($this->sender); + } - /** - * Invoked immediately after the Message is sent. - */ - public function sendPerformed(Swift_Events_SendEvent $evt) - { - $message = $evt->getMessage(); + /** + * Invoked immediately after the Message is sent. + */ + public function sendPerformed(Swift_Events_SendEvent $evt) + { + $message = $evt->getMessage(); - // restore original headers - $headers = $message->getHeaders(); + // restore original headers + $headers = $message->getHeaders(); - if ($headers->has('X-Swift-Return-Path')) { - $message->setReturnPath($headers->get('X-Swift-Return-Path')->getAddress()); - $headers->removeAll('X-Swift-Return-Path'); - } - } + if ($headers->has('X-Swift-Return-Path')) { + $message->setReturnPath($headers->get('X-Swift-Return-Path')->getAddress()); + $headers->removeAll('X-Swift-Return-Path'); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/LoggerPlugin.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/LoggerPlugin.php index e183749b7ec..afb0a3df297 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/LoggerPlugin.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/LoggerPlugin.php @@ -15,112 +15,112 @@ */ class Swift_Plugins_LoggerPlugin implements Swift_Events_CommandListener, Swift_Events_ResponseListener, Swift_Events_TransportChangeListener, Swift_Events_TransportExceptionListener, Swift_Plugins_Logger { - /** The logger which is delegated to */ - private $logger; + /** The logger which is delegated to */ + private $logger; - /** - * Create a new LoggerPlugin using $logger. - */ - public function __construct(Swift_Plugins_Logger $logger) - { - $this->logger = $logger; - } + /** + * Create a new LoggerPlugin using $logger. + */ + public function __construct(Swift_Plugins_Logger $logger) + { + $this->logger = $logger; + } - /** - * Add a log entry. - * - * @param string $entry - */ - public function add($entry) - { - $this->logger->add($entry); - } + /** + * Add a log entry. + * + * @param string $entry + */ + public function add($entry) + { + $this->logger->add($entry); + } - /** - * Clear the log contents. - */ - public function clear() - { - $this->logger->clear(); - } + /** + * Clear the log contents. + */ + public function clear() + { + $this->logger->clear(); + } - /** - * Get this log as a string. - * - * @return string - */ - public function dump() - { - return $this->logger->dump(); - } + /** + * Get this log as a string. + * + * @return string + */ + public function dump() + { + return $this->logger->dump(); + } - /** - * Invoked immediately following a command being sent. - */ - public function commandSent(Swift_Events_CommandEvent $evt) - { - $command = $evt->getCommand(); - $this->logger->add(sprintf('>> %s', $command)); - } + /** + * Invoked immediately following a command being sent. + */ + public function commandSent(Swift_Events_CommandEvent $evt) + { + $command = $evt->getCommand(); + $this->logger->add(sprintf('>> %s', $command)); + } - /** - * Invoked immediately following a response coming back. - */ - public function responseReceived(Swift_Events_ResponseEvent $evt) - { - $response = $evt->getResponse(); - $this->logger->add(sprintf('<< %s', $response)); - } + /** + * Invoked immediately following a response coming back. + */ + public function responseReceived(Swift_Events_ResponseEvent $evt) + { + $response = $evt->getResponse(); + $this->logger->add(sprintf('<< %s', $response)); + } - /** - * Invoked just before a Transport is started. - */ - public function beforeTransportStarted(Swift_Events_TransportChangeEvent $evt) - { - $transportName = \get_class($evt->getSource()); - $this->logger->add(sprintf('++ Starting %s', $transportName)); - } + /** + * Invoked just before a Transport is started. + */ + public function beforeTransportStarted(Swift_Events_TransportChangeEvent $evt) + { + $transportName = \get_class($evt->getSource()); + $this->logger->add(sprintf('++ Starting %s', $transportName)); + } - /** - * Invoked immediately after the Transport is started. - */ - public function transportStarted(Swift_Events_TransportChangeEvent $evt) - { - $transportName = \get_class($evt->getSource()); - $this->logger->add(sprintf('++ %s started', $transportName)); - } + /** + * Invoked immediately after the Transport is started. + */ + public function transportStarted(Swift_Events_TransportChangeEvent $evt) + { + $transportName = \get_class($evt->getSource()); + $this->logger->add(sprintf('++ %s started', $transportName)); + } - /** - * Invoked just before a Transport is stopped. - */ - public function beforeTransportStopped(Swift_Events_TransportChangeEvent $evt) - { - $transportName = \get_class($evt->getSource()); - $this->logger->add(sprintf('++ Stopping %s', $transportName)); - } + /** + * Invoked just before a Transport is stopped. + */ + public function beforeTransportStopped(Swift_Events_TransportChangeEvent $evt) + { + $transportName = \get_class($evt->getSource()); + $this->logger->add(sprintf('++ Stopping %s', $transportName)); + } - /** - * Invoked immediately after the Transport is stopped. - */ - public function transportStopped(Swift_Events_TransportChangeEvent $evt) - { - $transportName = \get_class($evt->getSource()); - $this->logger->add(sprintf('++ %s stopped', $transportName)); - } + /** + * Invoked immediately after the Transport is stopped. + */ + public function transportStopped(Swift_Events_TransportChangeEvent $evt) + { + $transportName = \get_class($evt->getSource()); + $this->logger->add(sprintf('++ %s stopped', $transportName)); + } - /** - * Invoked as a TransportException is thrown in the Transport system. - */ - public function exceptionThrown(Swift_Events_TransportExceptionEvent $evt) - { - $e = $evt->getException(); - $message = $e->getMessage(); - $code = $e->getCode(); - $this->logger->add(sprintf('!! %s (code: %s)', $message, $code)); - $message .= PHP_EOL; - $message .= 'Log data:'.PHP_EOL; - $message .= $this->logger->dump(); - $evt->cancelBubble(); - throw new Swift_TransportException($message, $code, $e->getPrevious()); - } + /** + * Invoked as a TransportException is thrown in the Transport system. + */ + public function exceptionThrown(Swift_Events_TransportExceptionEvent $evt) + { + $e = $evt->getException(); + $message = $e->getMessage(); + $code = $e->getCode(); + $this->logger->add(sprintf('!! %s (code: %s)', $message, $code)); + $message .= PHP_EOL; + $message .= 'Log data:'.PHP_EOL; + $message .= $this->logger->dump(); + $evt->cancelBubble(); + throw new Swift_TransportException($message, $code, $e->getPrevious()); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Loggers/ArrayLogger.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Loggers/ArrayLogger.php index 6f595adaa4d..0761b84f83d 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Loggers/ArrayLogger.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Loggers/ArrayLogger.php @@ -15,58 +15,58 @@ */ class Swift_Plugins_Loggers_ArrayLogger implements Swift_Plugins_Logger { - /** - * The log contents. - * - * @var array - */ - private $log = []; + /** + * The log contents. + * + * @var array + */ + private $log = []; - /** - * Max size of the log. - * - * @var int - */ - private $size = 0; + /** + * Max size of the log. + * + * @var int + */ + private $size = 0; - /** - * Create a new ArrayLogger with a maximum of $size entries. - * - * @var int - */ - public function __construct($size = 50) - { - $this->size = $size; - } + /** + * Create a new ArrayLogger with a maximum of $size entries. + * + * @var int + */ + public function __construct($size = 50) + { + $this->size = $size; + } - /** - * Add a log entry. - * - * @param string $entry - */ - public function add($entry) - { - $this->log[] = $entry; - while (\count($this->log) > $this->size) { - array_shift($this->log); - } - } + /** + * Add a log entry. + * + * @param string $entry + */ + public function add($entry) + { + $this->log[] = $entry; + while (\count($this->log) > $this->size) { + array_shift($this->log); + } + } - /** - * Clear the log contents. - */ - public function clear() - { - $this->log = []; - } + /** + * Clear the log contents. + */ + public function clear() + { + $this->log = []; + } - /** - * Get this log as a string. - * - * @return string - */ - public function dump() - { - return implode(PHP_EOL, $this->log); - } + /** + * Get this log as a string. + * + * @return string + */ + public function dump() + { + return implode(PHP_EOL, $this->log); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/MessageLogger.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/MessageLogger.php index 39c48ed18f5..6aaf87599cb 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/MessageLogger.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/MessageLogger.php @@ -15,56 +15,56 @@ */ class Swift_Plugins_MessageLogger implements Swift_Events_SendListener { - /** - * @var Swift_Mime_SimpleMessage[] - */ - private $messages; + /** + * @var Swift_Mime_SimpleMessage[] + */ + private $messages; - public function __construct() - { - $this->messages = []; - } + public function __construct() + { + $this->messages = []; + } - /** - * Get the message list. - * - * @return Swift_Mime_SimpleMessage[] - */ - public function getMessages() - { - return $this->messages; - } + /** + * Get the message list. + * + * @return Swift_Mime_SimpleMessage[] + */ + public function getMessages() + { + return $this->messages; + } - /** - * Get the message count. - * - * @return int count - */ - public function countMessages() - { - return \count($this->messages); - } + /** + * Get the message count. + * + * @return int count + */ + public function countMessages() + { + return \count($this->messages); + } - /** - * Empty the message list. - */ - public function clear() - { - $this->messages = []; - } + /** + * Empty the message list. + */ + public function clear() + { + $this->messages = []; + } - /** - * Invoked immediately before the Message is sent. - */ - public function beforeSendPerformed(Swift_Events_SendEvent $evt) - { - $this->messages[] = clone $evt->getMessage(); - } + /** + * Invoked immediately before the Message is sent. + */ + public function beforeSendPerformed(Swift_Events_SendEvent $evt) + { + $this->messages[] = clone $evt->getMessage(); + } - /** - * Invoked immediately after the Message is sent. - */ - public function sendPerformed(Swift_Events_SendEvent $evt) - { - } + /** + * Invoked immediately after the Message is sent. + */ + public function sendPerformed(Swift_Events_SendEvent $evt) + { + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/PopBeforeSmtpPlugin.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/PopBeforeSmtpPlugin.php index 9448594090b..cf4f2438ec0 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/PopBeforeSmtpPlugin.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/PopBeforeSmtpPlugin.php @@ -15,228 +15,228 @@ */ class Swift_Plugins_PopBeforeSmtpPlugin implements Swift_Events_TransportChangeListener, Swift_Plugins_Pop_Pop3Connection { - /** A delegate connection to use (mostly a test hook) */ - private $connection; + /** A delegate connection to use (mostly a test hook) */ + private $connection; - /** Hostname of the POP3 server */ - private $host; + /** Hostname of the POP3 server */ + private $host; - /** Port number to connect on */ - private $port; + /** Port number to connect on */ + private $port; - /** Encryption type to use (if any) */ - private $crypto; + /** Encryption type to use (if any) */ + private $crypto; - /** Username to use (if any) */ - private $username; + /** Username to use (if any) */ + private $username; - /** Password to use (if any) */ - private $password; + /** Password to use (if any) */ + private $password; - /** Established connection via TCP socket */ - private $socket; + /** Established connection via TCP socket */ + private $socket; - /** Connect timeout in seconds */ - private $timeout = 10; + /** Connect timeout in seconds */ + private $timeout = 10; - /** SMTP Transport to bind to */ - private $transport; + /** SMTP Transport to bind to */ + private $transport; - /** - * Create a new PopBeforeSmtpPlugin for $host and $port. - * - * @param string $host Hostname or IP. Literal IPv6 addresses should be - * wrapped in square brackets. - * @param int $port - * @param string $crypto as "tls" or "ssl" - */ - public function __construct($host, $port = 110, $crypto = null) - { - $this->host = $host; - $this->port = $port; - $this->crypto = $crypto; - } + /** + * Create a new PopBeforeSmtpPlugin for $host and $port. + * + * @param string $host Hostname or IP. Literal IPv6 addresses should be + * wrapped in square brackets. + * @param int $port + * @param string $crypto as "tls" or "ssl" + */ + public function __construct($host, $port = 110, $crypto = null) + { + $this->host = $host; + $this->port = $port; + $this->crypto = $crypto; + } - /** - * Set a Pop3Connection to delegate to instead of connecting directly. - * - * @return $this - */ - public function setConnection(Swift_Plugins_Pop_Pop3Connection $connection) - { - $this->connection = $connection; + /** + * Set a Pop3Connection to delegate to instead of connecting directly. + * + * @return $this + */ + public function setConnection(Swift_Plugins_Pop_Pop3Connection $connection) + { + $this->connection = $connection; - return $this; - } + return $this; + } - /** - * Bind this plugin to a specific SMTP transport instance. - */ - public function bindSmtp(Swift_Transport $smtp) - { - $this->transport = $smtp; - } + /** + * Bind this plugin to a specific SMTP transport instance. + */ + public function bindSmtp(Swift_Transport $smtp) + { + $this->transport = $smtp; + } - /** - * Set the connection timeout in seconds (default 10). - * - * @param int $timeout - * - * @return $this - */ - public function setTimeout($timeout) - { - $this->timeout = (int) $timeout; + /** + * Set the connection timeout in seconds (default 10). + * + * @param int $timeout + * + * @return $this + */ + public function setTimeout($timeout) + { + $this->timeout = (int) $timeout; - return $this; - } + return $this; + } - /** - * Set the username to use when connecting (if needed). - * - * @param string $username - * - * @return $this - */ - public function setUsername($username) - { - $this->username = $username; + /** + * Set the username to use when connecting (if needed). + * + * @param string $username + * + * @return $this + */ + public function setUsername($username) + { + $this->username = $username; - return $this; - } + return $this; + } - /** - * Set the password to use when connecting (if needed). - * - * @param string $password - * - * @return $this - */ - public function setPassword($password) - { - $this->password = $password; + /** + * Set the password to use when connecting (if needed). + * + * @param string $password + * + * @return $this + */ + public function setPassword($password) + { + $this->password = $password; - return $this; - } + return $this; + } - /** - * Connect to the POP3 host and authenticate. - * - * @throws Swift_Plugins_Pop_Pop3Exception if connection fails - */ - public function connect() - { - if (isset($this->connection)) { - $this->connection->connect(); - } else { - if (!isset($this->socket)) { - if (!$socket = fsockopen( - $this->getHostString(), $this->port, $errno, $errstr, $this->timeout)) { - throw new Swift_Plugins_Pop_Pop3Exception(sprintf('Failed to connect to POP3 host [%s]: %s', $this->host, $errstr)); - } - $this->socket = $socket; + /** + * Connect to the POP3 host and authenticate. + * + * @throws Swift_Plugins_Pop_Pop3Exception if connection fails + */ + public function connect() + { + if (isset($this->connection)) { + $this->connection->connect(); + } else { + if (!isset($this->socket)) { + if (!$socket = fsockopen( + $this->getHostString(), $this->port, $errno, $errstr, $this->timeout)) { + throw new Swift_Plugins_Pop_Pop3Exception(sprintf('Failed to connect to POP3 host [%s]: %s', $this->host, $errstr)); + } + $this->socket = $socket; - if (false === $greeting = fgets($this->socket)) { - throw new Swift_Plugins_Pop_Pop3Exception(sprintf('Failed to connect to POP3 host [%s]', trim($greeting ?? ''))); - } + if (false === $greeting = fgets($this->socket)) { + throw new Swift_Plugins_Pop_Pop3Exception(sprintf('Failed to connect to POP3 host [%s]', trim($greeting ?? ''))); + } - $this->assertOk($greeting); + $this->assertOk($greeting); - if ($this->username) { - $this->command(sprintf("USER %s\r\n", $this->username)); - $this->command(sprintf("PASS %s\r\n", $this->password)); - } - } - } - } + if ($this->username) { + $this->command(sprintf("USER %s\r\n", $this->username)); + $this->command(sprintf("PASS %s\r\n", $this->password)); + } + } + } + } - /** - * Disconnect from the POP3 host. - */ - public function disconnect() - { - if (isset($this->connection)) { - $this->connection->disconnect(); - } else { - $this->command("QUIT\r\n"); - if (!fclose($this->socket)) { - throw new Swift_Plugins_Pop_Pop3Exception(sprintf('POP3 host [%s] connection could not be stopped', $this->host)); - } - $this->socket = null; - } - } + /** + * Disconnect from the POP3 host. + */ + public function disconnect() + { + if (isset($this->connection)) { + $this->connection->disconnect(); + } else { + $this->command("QUIT\r\n"); + if (!fclose($this->socket)) { + throw new Swift_Plugins_Pop_Pop3Exception(sprintf('POP3 host [%s] connection could not be stopped', $this->host)); + } + $this->socket = null; + } + } - /** - * Invoked just before a Transport is started. - */ - public function beforeTransportStarted(Swift_Events_TransportChangeEvent $evt) - { - if (isset($this->transport)) { - if ($this->transport !== $evt->getTransport()) { - return; - } - } + /** + * Invoked just before a Transport is started. + */ + public function beforeTransportStarted(Swift_Events_TransportChangeEvent $evt) + { + if (isset($this->transport)) { + if ($this->transport !== $evt->getTransport()) { + return; + } + } - $this->connect(); - $this->disconnect(); - } + $this->connect(); + $this->disconnect(); + } - /** - * Not used. - */ - public function transportStarted(Swift_Events_TransportChangeEvent $evt) - { - } + /** + * Not used. + */ + public function transportStarted(Swift_Events_TransportChangeEvent $evt) + { + } - /** - * Not used. - */ - public function beforeTransportStopped(Swift_Events_TransportChangeEvent $evt) - { - } + /** + * Not used. + */ + public function beforeTransportStopped(Swift_Events_TransportChangeEvent $evt) + { + } - /** - * Not used. - */ - public function transportStopped(Swift_Events_TransportChangeEvent $evt) - { - } + /** + * Not used. + */ + public function transportStopped(Swift_Events_TransportChangeEvent $evt) + { + } - private function command($command) - { - if (!fwrite($this->socket, $command)) { - throw new Swift_Plugins_Pop_Pop3Exception(sprintf('Failed to write command [%s] to POP3 host', trim($command ?? ''))); - } + private function command($command) + { + if (!fwrite($this->socket, $command)) { + throw new Swift_Plugins_Pop_Pop3Exception(sprintf('Failed to write command [%s] to POP3 host', trim($command ?? ''))); + } - if (false === $response = fgets($this->socket)) { - throw new Swift_Plugins_Pop_Pop3Exception(sprintf('Failed to read from POP3 host after command [%s]', trim($command ?? ''))); - } + if (false === $response = fgets($this->socket)) { + throw new Swift_Plugins_Pop_Pop3Exception(sprintf('Failed to read from POP3 host after command [%s]', trim($command ?? ''))); + } - $this->assertOk($response); + $this->assertOk($response); - return $response; - } + return $response; + } - private function assertOk($response) - { - if ('+OK' != substr($response, 0, 3)) { - throw new Swift_Plugins_Pop_Pop3Exception(sprintf('POP3 command failed [%s]', trim($response ?? ''))); - } - } + private function assertOk($response) + { + if ('+OK' != substr($response, 0, 3)) { + throw new Swift_Plugins_Pop_Pop3Exception(sprintf('POP3 command failed [%s]', trim($response ?? ''))); + } + } - private function getHostString() - { - $host = $this->host; - switch (strtolower($this->crypto ?? '')) { - case 'ssl': - $host = 'ssl://'.$host; - break; + private function getHostString() + { + $host = $this->host; + switch (strtolower($this->crypto ?? '')) { + case 'ssl': + $host = 'ssl://'.$host; + break; - case 'tls': - $host = 'tls://'.$host; - break; - } + case 'tls': + $host = 'tls://'.$host; + break; + } - return $host; - } + return $host; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/RedirectingPlugin.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/RedirectingPlugin.php index f7373b2424c..756faa89c67 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/RedirectingPlugin.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/RedirectingPlugin.php @@ -15,187 +15,187 @@ */ class Swift_Plugins_RedirectingPlugin implements Swift_Events_SendListener { - /** - * The recipient who will receive all messages. - * - * @var mixed - */ - private $recipient; + /** + * The recipient who will receive all messages. + * + * @var mixed + */ + private $recipient; - /** - * List of regular expression for recipient whitelisting. - * - * @var array - */ - private $whitelist = []; + /** + * List of regular expression for recipient whitelisting. + * + * @var array + */ + private $whitelist = []; - /** - * Create a new RedirectingPlugin. - * - * @param mixed $recipient - */ - public function __construct($recipient, array $whitelist = []) - { - $this->recipient = $recipient; - $this->whitelist = $whitelist; - } + /** + * Create a new RedirectingPlugin. + * + * @param mixed $recipient + */ + public function __construct($recipient, array $whitelist = []) + { + $this->recipient = $recipient; + $this->whitelist = $whitelist; + } - /** - * Set the recipient of all messages. - * - * @param mixed $recipient - */ - public function setRecipient($recipient) - { - $this->recipient = $recipient; - } + /** + * Set the recipient of all messages. + * + * @param mixed $recipient + */ + public function setRecipient($recipient) + { + $this->recipient = $recipient; + } - /** - * Get the recipient of all messages. - * - * @return mixed - */ - public function getRecipient() - { - return $this->recipient; - } + /** + * Get the recipient of all messages. + * + * @return mixed + */ + public function getRecipient() + { + return $this->recipient; + } - /** - * Set a list of regular expressions to whitelist certain recipients. - */ - public function setWhitelist(array $whitelist) - { - $this->whitelist = $whitelist; - } + /** + * Set a list of regular expressions to whitelist certain recipients. + */ + public function setWhitelist(array $whitelist) + { + $this->whitelist = $whitelist; + } - /** - * Get the whitelist. - * - * @return array - */ - public function getWhitelist() - { - return $this->whitelist; - } + /** + * Get the whitelist. + * + * @return array + */ + public function getWhitelist() + { + return $this->whitelist; + } - /** - * Invoked immediately before the Message is sent. - */ - public function beforeSendPerformed(Swift_Events_SendEvent $evt) - { - $message = $evt->getMessage(); - $headers = $message->getHeaders(); + /** + * Invoked immediately before the Message is sent. + */ + public function beforeSendPerformed(Swift_Events_SendEvent $evt) + { + $message = $evt->getMessage(); + $headers = $message->getHeaders(); - // conditionally save current recipients + // conditionally save current recipients - if ($headers->has('to')) { - $headers->addMailboxHeader('X-Swift-To', $message->getTo()); - } + if ($headers->has('to')) { + $headers->addMailboxHeader('X-Swift-To', $message->getTo()); + } - if ($headers->has('cc')) { - $headers->addMailboxHeader('X-Swift-Cc', $message->getCc()); - } + if ($headers->has('cc')) { + $headers->addMailboxHeader('X-Swift-Cc', $message->getCc()); + } - if ($headers->has('bcc')) { - $headers->addMailboxHeader('X-Swift-Bcc', $message->getBcc()); - } + if ($headers->has('bcc')) { + $headers->addMailboxHeader('X-Swift-Bcc', $message->getBcc()); + } - // Filter remaining headers against whitelist - $this->filterHeaderSet($headers, 'To'); - $this->filterHeaderSet($headers, 'Cc'); - $this->filterHeaderSet($headers, 'Bcc'); + // Filter remaining headers against whitelist + $this->filterHeaderSet($headers, 'To'); + $this->filterHeaderSet($headers, 'Cc'); + $this->filterHeaderSet($headers, 'Bcc'); - // Add each hard coded recipient - $to = $message->getTo(); - if (null === $to) { - $to = []; - } + // Add each hard coded recipient + $to = $message->getTo(); + if (null === $to) { + $to = []; + } - foreach ((array) $this->recipient as $recipient) { - if (!\array_key_exists($recipient, $to)) { - $message->addTo($recipient); - } - } - } + foreach ((array) $this->recipient as $recipient) { + if (!\array_key_exists($recipient, $to)) { + $message->addTo($recipient); + } + } + } - /** - * Filter header set against a whitelist of regular expressions. - * - * @param string $type - */ - private function filterHeaderSet(Swift_Mime_SimpleHeaderSet $headerSet, $type) - { - foreach ($headerSet->getAll($type) as $headers) { - $headers->setNameAddresses($this->filterNameAddresses($headers->getNameAddresses())); - } - } + /** + * Filter header set against a whitelist of regular expressions. + * + * @param string $type + */ + private function filterHeaderSet(Swift_Mime_SimpleHeaderSet $headerSet, $type) + { + foreach ($headerSet->getAll($type) as $headers) { + $headers->setNameAddresses($this->filterNameAddresses($headers->getNameAddresses())); + } + } - /** - * Filtered list of addresses => name pairs. - * - * @return array - */ - private function filterNameAddresses(array $recipients) - { - $filtered = []; + /** + * Filtered list of addresses => name pairs. + * + * @return array + */ + private function filterNameAddresses(array $recipients) + { + $filtered = []; - foreach ($recipients as $address => $name) { - if ($this->isWhitelisted($address)) { - $filtered[$address] = $name; - } - } + foreach ($recipients as $address => $name) { + if ($this->isWhitelisted($address)) { + $filtered[$address] = $name; + } + } - return $filtered; - } + return $filtered; + } - /** - * Matches address against whitelist of regular expressions. - * - * @return bool - */ - protected function isWhitelisted($recipient) - { - if (\in_array($recipient, (array) $this->recipient)) { - return true; - } + /** + * Matches address against whitelist of regular expressions. + * + * @return bool + */ + protected function isWhitelisted($recipient) + { + if (\in_array($recipient, (array) $this->recipient)) { + return true; + } - foreach ($this->whitelist as $pattern) { - if (preg_match($pattern, $recipient)) { - return true; - } - } + foreach ($this->whitelist as $pattern) { + if (preg_match($pattern, $recipient)) { + return true; + } + } - return false; - } + return false; + } - /** - * Invoked immediately after the Message is sent. - */ - public function sendPerformed(Swift_Events_SendEvent $evt) - { - $this->restoreMessage($evt->getMessage()); - } + /** + * Invoked immediately after the Message is sent. + */ + public function sendPerformed(Swift_Events_SendEvent $evt) + { + $this->restoreMessage($evt->getMessage()); + } - private function restoreMessage(Swift_Mime_SimpleMessage $message) - { - // restore original headers - $headers = $message->getHeaders(); + private function restoreMessage(Swift_Mime_SimpleMessage $message) + { + // restore original headers + $headers = $message->getHeaders(); - if ($headers->has('X-Swift-To')) { - $message->setTo($headers->get('X-Swift-To')->getNameAddresses()); - $headers->removeAll('X-Swift-To'); - } else { - $message->setTo(null); - } + if ($headers->has('X-Swift-To')) { + $message->setTo($headers->get('X-Swift-To')->getNameAddresses()); + $headers->removeAll('X-Swift-To'); + } else { + $message->setTo(null); + } - if ($headers->has('X-Swift-Cc')) { - $message->setCc($headers->get('X-Swift-Cc')->getNameAddresses()); - $headers->removeAll('X-Swift-Cc'); - } + if ($headers->has('X-Swift-Cc')) { + $message->setCc($headers->get('X-Swift-Cc')->getNameAddresses()); + $headers->removeAll('X-Swift-Cc'); + } - if ($headers->has('X-Swift-Bcc')) { - $message->setBcc($headers->get('X-Swift-Bcc')->getNameAddresses()); - $headers->removeAll('X-Swift-Bcc'); - } - } + if ($headers->has('X-Swift-Bcc')) { + $message->setBcc($headers->get('X-Swift-Bcc')->getNameAddresses()); + $headers->removeAll('X-Swift-Bcc'); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Reporter.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Reporter.php index b8818339722..384487ba6f8 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Reporter.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Reporter.php @@ -15,17 +15,17 @@ */ interface Swift_Plugins_Reporter { - /** The recipient was accepted for delivery */ - const RESULT_PASS = 0x01; + /** The recipient was accepted for delivery */ + const RESULT_PASS = 0x01; - /** The recipient could not be accepted */ - const RESULT_FAIL = 0x10; + /** The recipient could not be accepted */ + const RESULT_FAIL = 0x10; - /** - * Notifies this ReportNotifier that $address failed or succeeded. - * - * @param string $address - * @param int $result from {@link RESULT_PASS, RESULT_FAIL} - */ - public function notify(Swift_Mime_SimpleMessage $message, $address, $result); + /** + * Notifies this ReportNotifier that $address failed or succeeded. + * + * @param string $address + * @param int $result from {@link RESULT_PASS, RESULT_FAIL} + */ + public function notify(Swift_Mime_SimpleMessage $message, $address, $result); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/ReporterPlugin.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/ReporterPlugin.php index c4a016520f6..2ac77ba2d13 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/ReporterPlugin.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/ReporterPlugin.php @@ -15,43 +15,43 @@ */ class Swift_Plugins_ReporterPlugin implements Swift_Events_SendListener { - /** - * The reporter backend which takes notifications. - * - * @var Swift_Plugins_Reporter - */ - private $reporter; + /** + * The reporter backend which takes notifications. + * + * @var Swift_Plugins_Reporter + */ + private $reporter; - /** - * Create a new ReporterPlugin using $reporter. - */ - public function __construct(Swift_Plugins_Reporter $reporter) - { - $this->reporter = $reporter; - } + /** + * Create a new ReporterPlugin using $reporter. + */ + public function __construct(Swift_Plugins_Reporter $reporter) + { + $this->reporter = $reporter; + } - /** - * Not used. - */ - public function beforeSendPerformed(Swift_Events_SendEvent $evt) - { - } + /** + * Not used. + */ + public function beforeSendPerformed(Swift_Events_SendEvent $evt) + { + } - /** - * Invoked immediately after the Message is sent. - */ - public function sendPerformed(Swift_Events_SendEvent $evt) - { - $message = $evt->getMessage(); - $failures = array_flip($evt->getFailedRecipients()); - foreach ((array) $message->getTo() as $address => $null) { - $this->reporter->notify($message, $address, (\array_key_exists($address, $failures) ? Swift_Plugins_Reporter::RESULT_FAIL : Swift_Plugins_Reporter::RESULT_PASS)); - } - foreach ((array) $message->getCc() as $address => $null) { - $this->reporter->notify($message, $address, (\array_key_exists($address, $failures) ? Swift_Plugins_Reporter::RESULT_FAIL : Swift_Plugins_Reporter::RESULT_PASS)); - } - foreach ((array) $message->getBcc() as $address => $null) { - $this->reporter->notify($message, $address, (\array_key_exists($address, $failures) ? Swift_Plugins_Reporter::RESULT_FAIL : Swift_Plugins_Reporter::RESULT_PASS)); - } - } + /** + * Invoked immediately after the Message is sent. + */ + public function sendPerformed(Swift_Events_SendEvent $evt) + { + $message = $evt->getMessage(); + $failures = array_flip($evt->getFailedRecipients()); + foreach ((array) $message->getTo() as $address => $null) { + $this->reporter->notify($message, $address, (\array_key_exists($address, $failures) ? Swift_Plugins_Reporter::RESULT_FAIL : Swift_Plugins_Reporter::RESULT_PASS)); + } + foreach ((array) $message->getCc() as $address => $null) { + $this->reporter->notify($message, $address, (\array_key_exists($address, $failures) ? Swift_Plugins_Reporter::RESULT_FAIL : Swift_Plugins_Reporter::RESULT_PASS)); + } + foreach ((array) $message->getBcc() as $address => $null) { + $this->reporter->notify($message, $address, (\array_key_exists($address, $failures) ? Swift_Plugins_Reporter::RESULT_FAIL : Swift_Plugins_Reporter::RESULT_PASS)); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Reporters/HitReporter.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Reporters/HitReporter.php index 249cffbde7b..ef88d47119e 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Reporters/HitReporter.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Reporters/HitReporter.php @@ -15,44 +15,44 @@ */ class Swift_Plugins_Reporters_HitReporter implements Swift_Plugins_Reporter { - /** - * The list of failures. - * - * @var array - */ - private $failures = []; + /** + * The list of failures. + * + * @var array + */ + private $failures = []; - private $failures_cache = []; + private $failures_cache = []; - /** - * Notifies this ReportNotifier that $address failed or succeeded. - * - * @param string $address - * @param int $result from {@link RESULT_PASS, RESULT_FAIL} - */ - public function notify(Swift_Mime_SimpleMessage $message, $address, $result) - { - if (self::RESULT_FAIL == $result && !isset($this->failures_cache[$address])) { - $this->failures[] = $address; - $this->failures_cache[$address] = true; - } - } + /** + * Notifies this ReportNotifier that $address failed or succeeded. + * + * @param string $address + * @param int $result from {@link RESULT_PASS, RESULT_FAIL} + */ + public function notify(Swift_Mime_SimpleMessage $message, $address, $result) + { + if (self::RESULT_FAIL == $result && !isset($this->failures_cache[$address])) { + $this->failures[] = $address; + $this->failures_cache[$address] = true; + } + } - /** - * Get an array of addresses for which delivery failed. - * - * @return array - */ - public function getFailedRecipients() - { - return $this->failures; - } + /** + * Get an array of addresses for which delivery failed. + * + * @return array + */ + public function getFailedRecipients() + { + return $this->failures; + } - /** - * Clear the buffer (empty the list). - */ - public function clear() - { - $this->failures = $this->failures_cache = []; - } + /** + * Clear the buffer (empty the list). + */ + public function clear() + { + $this->failures = $this->failures_cache = []; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Reporters/HtmlReporter.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Reporters/HtmlReporter.php index 1cfc3f974f8..710a0b370dd 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Reporters/HtmlReporter.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Reporters/HtmlReporter.php @@ -15,24 +15,24 @@ */ class Swift_Plugins_Reporters_HtmlReporter implements Swift_Plugins_Reporter { - /** - * Notifies this ReportNotifier that $address failed or succeeded. - * - * @param string $address - * @param int $result from {@see RESULT_PASS, RESULT_FAIL} - */ - public function notify(Swift_Mime_SimpleMessage $message, $address, $result) - { - if (self::RESULT_PASS == $result) { - echo '
'.PHP_EOL; - echo 'PASS '.$address.PHP_EOL; - echo '
'.PHP_EOL; - flush(); - } else { - echo '
'.PHP_EOL; - echo 'FAIL '.$address.PHP_EOL; - echo '
'.PHP_EOL; - flush(); - } - } + /** + * Notifies this ReportNotifier that $address failed or succeeded. + * + * @param string $address + * @param int $result from {@see RESULT_PASS, RESULT_FAIL} + */ + public function notify(Swift_Mime_SimpleMessage $message, $address, $result) + { + if (self::RESULT_PASS == $result) { + echo '
'.PHP_EOL; + echo 'PASS '.$address.PHP_EOL; + echo '
'.PHP_EOL; + flush(); + } else { + echo '
'.PHP_EOL; + echo 'FAIL '.$address.PHP_EOL; + echo '
'.PHP_EOL; + flush(); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/ThrottlerPlugin.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/ThrottlerPlugin.php index 83d3044927f..82c5d9fb99f 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/ThrottlerPlugin.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/ThrottlerPlugin.php @@ -15,182 +15,182 @@ */ class Swift_Plugins_ThrottlerPlugin extends Swift_Plugins_BandwidthMonitorPlugin implements Swift_Plugins_Sleeper, Swift_Plugins_Timer { - /** Flag for throttling in bytes per minute */ - const BYTES_PER_MINUTE = 0x01; + /** Flag for throttling in bytes per minute */ + const BYTES_PER_MINUTE = 0x01; - /** Flag for throttling in emails per second (Amazon SES) */ - const MESSAGES_PER_SECOND = 0x11; + /** Flag for throttling in emails per second (Amazon SES) */ + const MESSAGES_PER_SECOND = 0x11; - /** Flag for throttling in emails per minute */ - const MESSAGES_PER_MINUTE = 0x10; + /** Flag for throttling in emails per minute */ + const MESSAGES_PER_MINUTE = 0x10; - /** - * The Sleeper instance for sleeping. - * - * @var Swift_Plugins_Sleeper - */ - private $sleeper; + /** + * The Sleeper instance for sleeping. + * + * @var Swift_Plugins_Sleeper + */ + private $sleeper; - /** - * The Timer instance which provides the timestamp. - * - * @var Swift_Plugins_Timer - */ - private $timer; + /** + * The Timer instance which provides the timestamp. + * + * @var Swift_Plugins_Timer + */ + private $timer; - /** - * The time at which the first email was sent. - * - * @var int - */ - private $start; + /** + * The time at which the first email was sent. + * + * @var int + */ + private $start; - /** - * The rate at which messages should be sent. - * - * @var int - */ - private $rate; + /** + * The rate at which messages should be sent. + * + * @var int + */ + private $rate; - /** - * The mode for throttling. - * - * This is {@link BYTES_PER_MINUTE} or {@link MESSAGES_PER_MINUTE} - * - * @var int - */ - private $mode; + /** + * The mode for throttling. + * + * This is {@link BYTES_PER_MINUTE} or {@link MESSAGES_PER_MINUTE} + * + * @var int + */ + private $mode; - /** - * An internal counter of the number of messages sent. - * - * @var int - */ - private $messages = 0; + /** + * An internal counter of the number of messages sent. + * + * @var int + */ + private $messages = 0; - /** - * Create a new ThrottlerPlugin. - * - * @param int $rate - * @param int $mode defaults to {@link BYTES_PER_MINUTE} - * @param Swift_Plugins_Sleeper $sleeper (only needed in testing) - * @param Swift_Plugins_Timer $timer (only needed in testing) - */ - public function __construct($rate, $mode = self::BYTES_PER_MINUTE, Swift_Plugins_Sleeper $sleeper = null, Swift_Plugins_Timer $timer = null) - { - $this->rate = $rate; - $this->mode = $mode; - $this->sleeper = $sleeper; - $this->timer = $timer; - } + /** + * Create a new ThrottlerPlugin. + * + * @param int $rate + * @param int $mode defaults to {@link BYTES_PER_MINUTE} + * @param Swift_Plugins_Sleeper $sleeper (only needed in testing) + * @param Swift_Plugins_Timer $timer (only needed in testing) + */ + public function __construct($rate, $mode = self::BYTES_PER_MINUTE, Swift_Plugins_Sleeper $sleeper = null, Swift_Plugins_Timer $timer = null) + { + $this->rate = $rate; + $this->mode = $mode; + $this->sleeper = $sleeper; + $this->timer = $timer; + } - /** - * Invoked immediately before the Message is sent. - */ - public function beforeSendPerformed(Swift_Events_SendEvent $evt) - { - $time = $this->getTimestamp(); - if (!isset($this->start)) { - $this->start = $time; - } - $duration = $time - $this->start; + /** + * Invoked immediately before the Message is sent. + */ + public function beforeSendPerformed(Swift_Events_SendEvent $evt) + { + $time = $this->getTimestamp(); + if (!isset($this->start)) { + $this->start = $time; + } + $duration = $time - $this->start; - switch ($this->mode) { - case self::BYTES_PER_MINUTE: - $sleep = $this->throttleBytesPerMinute($duration); - break; - case self::MESSAGES_PER_SECOND: - $sleep = $this->throttleMessagesPerSecond($duration); - break; - case self::MESSAGES_PER_MINUTE: - $sleep = $this->throttleMessagesPerMinute($duration); - break; - default: - $sleep = 0; - break; - } + switch ($this->mode) { + case self::BYTES_PER_MINUTE: + $sleep = $this->throttleBytesPerMinute($duration); + break; + case self::MESSAGES_PER_SECOND: + $sleep = $this->throttleMessagesPerSecond($duration); + break; + case self::MESSAGES_PER_MINUTE: + $sleep = $this->throttleMessagesPerMinute($duration); + break; + default: + $sleep = 0; + break; + } - if ($sleep > 0) { - $this->sleep($sleep); - } - } + if ($sleep > 0) { + $this->sleep($sleep); + } + } - /** - * Invoked when a Message is sent. - */ - public function sendPerformed(Swift_Events_SendEvent $evt) - { - parent::sendPerformed($evt); - ++$this->messages; - } + /** + * Invoked when a Message is sent. + */ + public function sendPerformed(Swift_Events_SendEvent $evt) + { + parent::sendPerformed($evt); + ++$this->messages; + } - /** - * Sleep for $seconds. - * - * @param int $seconds - */ - public function sleep($seconds) - { - if (isset($this->sleeper)) { - $this->sleeper->sleep($seconds); - } else { - sleep($seconds); - } - } + /** + * Sleep for $seconds. + * + * @param int $seconds + */ + public function sleep($seconds) + { + if (isset($this->sleeper)) { + $this->sleeper->sleep($seconds); + } else { + sleep($seconds); + } + } - /** - * Get the current UNIX timestamp. - * - * @return int - */ - public function getTimestamp() - { - if (isset($this->timer)) { - return $this->timer->getTimestamp(); - } + /** + * Get the current UNIX timestamp. + * + * @return int + */ + public function getTimestamp() + { + if (isset($this->timer)) { + return $this->timer->getTimestamp(); + } - return time(); - } + return time(); + } - /** - * Get a number of seconds to sleep for. - * - * @param int $timePassed - * - * @return int - */ - private function throttleBytesPerMinute($timePassed) - { - $expectedDuration = $this->getBytesOut() / ($this->rate / 60); + /** + * Get a number of seconds to sleep for. + * + * @param int $timePassed + * + * @return int + */ + private function throttleBytesPerMinute($timePassed) + { + $expectedDuration = $this->getBytesOut() / ($this->rate / 60); - return (int) ceil($expectedDuration - $timePassed); - } + return (int) ceil($expectedDuration - $timePassed); + } - /** - * Get a number of seconds to sleep for. - * - * @param int $timePassed - * - * @return int - */ - private function throttleMessagesPerSecond($timePassed) - { - $expectedDuration = $this->messages / $this->rate; + /** + * Get a number of seconds to sleep for. + * + * @param int $timePassed + * + * @return int + */ + private function throttleMessagesPerSecond($timePassed) + { + $expectedDuration = $this->messages / $this->rate; - return (int) ceil($expectedDuration - $timePassed); - } + return (int) ceil($expectedDuration - $timePassed); + } - /** - * Get a number of seconds to sleep for. - * - * @param int $timePassed - * - * @return int - */ - private function throttleMessagesPerMinute($timePassed) - { - $expectedDuration = $this->messages / ($this->rate / 60); + /** + * Get a number of seconds to sleep for. + * + * @param int $timePassed + * + * @return int + */ + private function throttleMessagesPerMinute($timePassed) + { + $expectedDuration = $this->messages / ($this->rate / 60); - return (int) ceil($expectedDuration - $timePassed); - } + return (int) ceil($expectedDuration - $timePassed); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Preferences.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Preferences.php index 16103e11031..237824ea180 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Preferences.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Preferences.php @@ -15,86 +15,86 @@ */ class Swift_Preferences { - /** Singleton instance */ - private static $instance = null; + /** Singleton instance */ + private static $instance = null; - /** Constructor not to be used */ - private function __construct() - { - } + /** Constructor not to be used */ + private function __construct() + { + } - /** - * Gets the instance of Preferences. - * - * @return self - */ - public static function getInstance() - { - if (!isset(self::$instance)) { - self::$instance = new self(); - } + /** + * Gets the instance of Preferences. + * + * @return self + */ + public static function getInstance() + { + if (!isset(self::$instance)) { + self::$instance = new self(); + } - return self::$instance; - } + return self::$instance; + } - /** - * Set the default charset used. - * - * @param string $charset - * - * @return $this - */ - public function setCharset($charset) - { - Swift_DependencyContainer::getInstance()->register('properties.charset')->asValue($charset); + /** + * Set the default charset used. + * + * @param string $charset + * + * @return $this + */ + public function setCharset($charset) + { + Swift_DependencyContainer::getInstance()->register('properties.charset')->asValue($charset); - return $this; - } + return $this; + } - /** - * Set the directory where temporary files can be saved. - * - * @param string $dir - * - * @return $this - */ - public function setTempDir($dir) - { - Swift_DependencyContainer::getInstance()->register('tempdir')->asValue($dir); + /** + * Set the directory where temporary files can be saved. + * + * @param string $dir + * + * @return $this + */ + public function setTempDir($dir) + { + Swift_DependencyContainer::getInstance()->register('tempdir')->asValue($dir); - return $this; - } + return $this; + } - /** - * Set the type of cache to use (i.e. "disk" or "array"). - * - * @param string $type - * - * @return $this - */ - public function setCacheType($type) - { - Swift_DependencyContainer::getInstance()->register('cache')->asAliasOf(sprintf('cache.%s', $type)); + /** + * Set the type of cache to use (i.e. "disk" or "array"). + * + * @param string $type + * + * @return $this + */ + public function setCacheType($type) + { + Swift_DependencyContainer::getInstance()->register('cache')->asAliasOf(sprintf('cache.%s', $type)); - return $this; - } + return $this; + } - /** - * Set the QuotedPrintable dot escaper preference. - * - * @param bool $dotEscape - * - * @return $this - */ - public function setQPDotEscape($dotEscape) - { - $dotEscape = !empty($dotEscape); - Swift_DependencyContainer::getInstance() - ->register('mime.qpcontentencoder') - ->asNewInstanceOf('Swift_Mime_ContentEncoder_QpContentEncoder') - ->withDependencies(['mime.charstream', 'mime.bytecanonicalizer']) - ->addConstructorValue($dotEscape); + /** + * Set the QuotedPrintable dot escaper preference. + * + * @param bool $dotEscape + * + * @return $this + */ + public function setQPDotEscape($dotEscape) + { + $dotEscape = !empty($dotEscape); + Swift_DependencyContainer::getInstance() + ->register('mime.qpcontentencoder') + ->asNewInstanceOf('Swift_Mime_ContentEncoder_QpContentEncoder') + ->withDependencies(['mime.charstream', 'mime.bytecanonicalizer']) + ->addConstructorValue($dotEscape); - return $this; - } + return $this; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/SendmailTransport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/SendmailTransport.php index 3c756436cc8..9f159857a51 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/SendmailTransport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/SendmailTransport.php @@ -15,19 +15,19 @@ */ class Swift_SendmailTransport extends Swift_Transport_SendmailTransport { - /** - * Create a new SendmailTransport, optionally using $command for sending. - * - * @param string $command - */ - public function __construct($command = '/usr/sbin/sendmail -bs') - { - \call_user_func_array( - [$this, 'Swift_Transport_SendmailTransport::__construct'], - Swift_DependencyContainer::getInstance() - ->createDependenciesFor('transport.sendmail') - ); + /** + * Create a new SendmailTransport, optionally using $command for sending. + * + * @param string $command + */ + public function __construct($command = '/usr/sbin/sendmail -bs') + { + \call_user_func_array( + [$this, 'Swift_Transport_SendmailTransport::__construct'], + Swift_DependencyContainer::getInstance() + ->createDependenciesFor('transport.sendmail') + ); - $this->setCommand($command); - } + $this->setCommand($command); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Signer.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Signer.php index 26c5e285c03..4a681f83bfa 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Signer.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Signer.php @@ -15,5 +15,5 @@ */ interface Swift_Signer { - public function reset(); + public function reset(); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/BodySigner.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/BodySigner.php index b25c427af83..a874e1ab2cb 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/BodySigner.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/BodySigner.php @@ -15,17 +15,17 @@ */ interface Swift_Signers_BodySigner extends Swift_Signer { - /** - * Change the Swift_Signed_Message to apply the singing. - * - * @return self - */ - public function signMessage(Swift_Message $message); + /** + * Change the Swift_Signed_Message to apply the singing. + * + * @return self + */ + public function signMessage(Swift_Message $message); - /** - * Return the list of header a signer might tamper. - * - * @return array - */ - public function getAlteredHeaders(); + /** + * Return the list of header a signer might tamper. + * + * @return array + */ + public function getAlteredHeaders(); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/DKIMSigner.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/DKIMSigner.php index ec82dc05663..e7323cb19b9 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/DKIMSigner.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/DKIMSigner.php @@ -15,668 +15,668 @@ */ class Swift_Signers_DKIMSigner implements Swift_Signers_HeaderSigner { - /** - * PrivateKey. - * - * @var string - */ - protected $privateKey; - - /** - * DomainName. - * - * @var string - */ - protected $domainName; - - /** - * Selector. - * - * @var string - */ - protected $selector; - - private $passphrase = ''; - - /** - * Hash algorithm used. - * - * @see RFC6376 3.3: Signers MUST implement and SHOULD sign using rsa-sha256. - * - * @var string - */ - protected $hashAlgorithm = 'rsa-sha256'; - - /** - * Body canon method. - * - * @var string - */ - protected $bodyCanon = 'simple'; - - /** - * Header canon method. - * - * @var string - */ - protected $headerCanon = 'simple'; - - /** - * Headers not being signed. - * - * @var array - */ - protected $ignoredHeaders = ['return-path' => true]; - - /** - * Signer identity. - * - * @var string - */ - protected $signerIdentity; - - /** - * BodyLength. - * - * @var int - */ - protected $bodyLen = 0; - - /** - * Maximum signedLen. - * - * @var int - */ - protected $maxLen = PHP_INT_MAX; - - /** - * Embbed bodyLen in signature. - * - * @var bool - */ - protected $showLen = false; - - /** - * When the signature has been applied (true means time()), false means not embedded. - * - * @var mixed - */ - protected $signatureTimestamp = true; - - /** - * When will the signature expires false means not embedded, if sigTimestamp is auto - * Expiration is relative, otherwise it's absolute. - * - * @var int - */ - protected $signatureExpiration = false; - - /** - * Must we embed signed headers? - * - * @var bool - */ - protected $debugHeaders = false; - - // work variables - /** - * Headers used to generate hash. - * - * @var array - */ - protected $signedHeaders = []; - - /** - * If debugHeaders is set store debugData here. - * - * @var string[] - */ - private $debugHeadersData = []; - - /** - * Stores the bodyHash. - * - * @var string - */ - private $bodyHash = ''; - - /** - * Stores the signature header. - * - * @var Swift_Mime_Headers_ParameterizedHeader - */ - protected $dkimHeader; - - private $bodyHashHandler; - - private $headerHash; - - private $headerCanonData = ''; - - private $bodyCanonEmptyCounter = 0; - - private $bodyCanonIgnoreStart = 2; - - private $bodyCanonSpace = false; - - private $bodyCanonLastChar = null; - - private $bodyCanonLine = ''; - - private $bound = []; - - /** - * Constructor. - * - * @param string $privateKey - * @param string $domainName - * @param string $selector - * @param string $passphrase - */ - public function __construct($privateKey, $domainName, $selector, $passphrase = '') - { - $this->privateKey = $privateKey; - $this->domainName = $domainName; - $this->signerIdentity = '@'.$domainName; - $this->selector = $selector; - $this->passphrase = $passphrase; - } - - /** - * Reset the Signer. - * - * @see Swift_Signer::reset() - */ - public function reset() - { - $this->headerHash = null; - $this->signedHeaders = []; - $this->bodyHash = null; - $this->bodyHashHandler = null; - $this->bodyCanonIgnoreStart = 2; - $this->bodyCanonEmptyCounter = 0; - $this->bodyCanonLastChar = null; - $this->bodyCanonSpace = false; - } - - /** - * Writes $bytes to the end of the stream. - * - * Writing may not happen immediately if the stream chooses to buffer. If - * you want to write these bytes with immediate effect, call {@link commit()} - * after calling write(). - * - * This method returns the sequence ID of the write (i.e. 1 for first, 2 for - * second, etc etc). - * - * @param string $bytes - * - * @return int - * - * @throws Swift_IoException - */ - // TODO fix return - public function write($bytes) - { - $this->canonicalizeBody($bytes); - foreach ($this->bound as $is) { - $is->write($bytes); - } - } - - /** - * For any bytes that are currently buffered inside the stream, force them - * off the buffer. - */ - public function commit() - { - // Nothing to do - return; - } - - /** - * Attach $is to this stream. - * - * The stream acts as an observer, receiving all data that is written. - * All {@link write()} and {@link flushBuffers()} operations will be mirrored. - */ - public function bind(Swift_InputByteStream $is) - { - // Don't have to mirror anything - $this->bound[] = $is; - - return; - } - - /** - * Remove an already bound stream. - * - * If $is is not bound, no errors will be raised. - * If the stream currently has any buffered data it will be written to $is - * before unbinding occurs. - */ - public function unbind(Swift_InputByteStream $is) - { - // Don't have to mirror anything - foreach ($this->bound as $k => $stream) { - if ($stream === $is) { - unset($this->bound[$k]); - - return; - } - } - } - - /** - * Flush the contents of the stream (empty it) and set the internal pointer - * to the beginning. - * - * @throws Swift_IoException - */ - public function flushBuffers() - { - $this->reset(); - } - - /** - * Set hash_algorithm, must be one of rsa-sha256 | rsa-sha1. - * - * @param string $hash 'rsa-sha1' or 'rsa-sha256' - * - * @throws Swift_SwiftException - * - * @return $this - */ - public function setHashAlgorithm($hash) - { - switch ($hash) { - case 'rsa-sha1': - $this->hashAlgorithm = 'rsa-sha1'; - break; - case 'rsa-sha256': - $this->hashAlgorithm = 'rsa-sha256'; - if (!\defined('OPENSSL_ALGO_SHA256')) { - throw new Swift_SwiftException('Unable to set sha256 as it is not supported by OpenSSL.'); - } - break; - default: - throw new Swift_SwiftException('Unable to set the hash algorithm, must be one of rsa-sha1 or rsa-sha256 (%s given).', $hash); - } - - return $this; - } - - /** - * Set the body canonicalization algorithm. - * - * @param string $canon - * - * @return $this - */ - public function setBodyCanon($canon) - { - if ('relaxed' == $canon) { - $this->bodyCanon = 'relaxed'; - } else { - $this->bodyCanon = 'simple'; - } - - return $this; - } - - /** - * Set the header canonicalization algorithm. - * - * @param string $canon - * - * @return $this - */ - public function setHeaderCanon($canon) - { - if ('relaxed' == $canon) { - $this->headerCanon = 'relaxed'; - } else { - $this->headerCanon = 'simple'; - } - - return $this; - } - - /** - * Set the signer identity. - * - * @param string $identity - * - * @return $this - */ - public function setSignerIdentity($identity) - { - $this->signerIdentity = $identity; - - return $this; - } - - /** - * Set the length of the body to sign. - * - * @param mixed $len (bool or int) - * - * @return $this - */ - public function setBodySignedLen($len) - { - if (true === $len) { - $this->showLen = true; - $this->maxLen = PHP_INT_MAX; - } elseif (false === $len) { - $this->showLen = false; - $this->maxLen = PHP_INT_MAX; - } else { - $this->showLen = true; - $this->maxLen = (int) $len; - } - - return $this; - } - - /** - * Set the signature timestamp. - * - * @param int $time A timestamp - * - * @return $this - */ - public function setSignatureTimestamp($time) - { - $this->signatureTimestamp = $time; - - return $this; - } - - /** - * Set the signature expiration timestamp. - * - * @param int $time A timestamp - * - * @return $this - */ - public function setSignatureExpiration($time) - { - $this->signatureExpiration = $time; - - return $this; - } - - /** - * Enable / disable the DebugHeaders. - * - * @param bool $debug - * - * @return Swift_Signers_DKIMSigner - */ - public function setDebugHeaders($debug) - { - $this->debugHeaders = (bool) $debug; - - return $this; - } - - /** - * Start Body. - */ - public function startBody() - { - // Init - switch ($this->hashAlgorithm) { - case 'rsa-sha256': - $this->bodyHashHandler = hash_init('sha256'); - break; - case 'rsa-sha1': - $this->bodyHashHandler = hash_init('sha1'); - break; - } - $this->bodyCanonLine = ''; - } - - /** - * End Body. - */ - public function endBody() - { - $this->endOfBody(); - } - - /** - * Returns the list of Headers Tampered by this plugin. - * - * @return array - */ - public function getAlteredHeaders() - { - if ($this->debugHeaders) { - return ['DKIM-Signature', 'X-DebugHash']; - } else { - return ['DKIM-Signature']; - } - } - - /** - * Adds an ignored Header. - * - * @param string $header_name - * - * @return Swift_Signers_DKIMSigner - */ - public function ignoreHeader($header_name) - { - $this->ignoredHeaders[strtolower($header_name ?? '')] = true; - - return $this; - } - - /** - * Set the headers to sign. - * - * @return Swift_Signers_DKIMSigner - */ - public function setHeaders(Swift_Mime_SimpleHeaderSet $headers) - { - $this->headerCanonData = ''; - // Loop through Headers - $listHeaders = $headers->listAll(); - foreach ($listHeaders as $hName) { - // Check if we need to ignore Header - if (!isset($this->ignoredHeaders[strtolower($hName ?? '')])) { - if ($headers->has($hName)) { - $tmp = $headers->getAll($hName); - foreach ($tmp as $header) { - if ('' != $header->getFieldBody()) { - $this->addHeader($header->toString()); - $this->signedHeaders[] = $header->getFieldName(); - } - } - } - } - } - - return $this; - } - - /** - * Add the signature to the given Headers. - * - * @return Swift_Signers_DKIMSigner - */ - public function addSignature(Swift_Mime_SimpleHeaderSet $headers) - { - // Prepare the DKIM-Signature - $params = ['v' => '1', 'a' => $this->hashAlgorithm, 'bh' => base64_encode($this->bodyHash ?? ''), 'd' => $this->domainName, 'h' => implode(': ', $this->signedHeaders), 'i' => $this->signerIdentity, 's' => $this->selector]; - if ('simple' != $this->bodyCanon) { - $params['c'] = $this->headerCanon.'/'.$this->bodyCanon; - } elseif ('simple' != $this->headerCanon) { - $params['c'] = $this->headerCanon; - } - if ($this->showLen) { - $params['l'] = $this->bodyLen; - } - if (true === $this->signatureTimestamp) { - $params['t'] = time(); - if (false !== $this->signatureExpiration) { - $params['x'] = $params['t'] + $this->signatureExpiration; - } - } else { - if (false !== $this->signatureTimestamp) { - $params['t'] = $this->signatureTimestamp; - } - if (false !== $this->signatureExpiration) { - $params['x'] = $this->signatureExpiration; - } - } - if ($this->debugHeaders) { - $params['z'] = implode('|', $this->debugHeadersData); - } - $string = ''; - foreach ($params as $k => $v) { - $string .= $k.'='.$v.'; '; - } - $string = trim($string); - $headers->addTextHeader('DKIM-Signature', $string); - // Add the last DKIM-Signature - $tmp = $headers->getAll('DKIM-Signature'); - $this->dkimHeader = end($tmp); - $this->addHeader(trim($this->dkimHeader->toString() ?? '')."\r\n b=", true); - if ($this->debugHeaders) { - $headers->addTextHeader('X-DebugHash', base64_encode($this->headerHash ?? '')); - } - $this->dkimHeader->setValue($string.' b='.trim(chunk_split(base64_encode($this->getEncryptedHash() ?? ''), 73, ' '))); - - return $this; - } - - /* Private helpers */ - - protected function addHeader($header, $is_sig = false) - { - switch ($this->headerCanon) { - case 'relaxed': - // Prepare Header and cascade - $exploded = explode(':', $header, 2); - $name = strtolower(trim($exploded[0])); - $value = str_replace("\r\n", '', $exploded[1]); - $value = preg_replace("/[ \t][ \t]+/", ' ', $value); - $header = $name.':'.trim($value).($is_sig ? '' : "\r\n"); - // no break - case 'simple': - // Nothing to do - } - $this->addToHeaderHash($header); - } - - protected function canonicalizeBody($string) - { - $len = \strlen($string); - $canon = ''; - $method = ('relaxed' == $this->bodyCanon); - for ($i = 0; $i < $len; ++$i) { - if ($this->bodyCanonIgnoreStart > 0) { - --$this->bodyCanonIgnoreStart; - continue; - } - switch ($string[$i]) { - case "\r": - $this->bodyCanonLastChar = "\r"; - break; - case "\n": - if ("\r" == $this->bodyCanonLastChar) { - if ($method) { - $this->bodyCanonSpace = false; - } - if ('' == $this->bodyCanonLine) { - ++$this->bodyCanonEmptyCounter; - } else { - $this->bodyCanonLine = ''; - $canon .= "\r\n"; - } - } else { - // Wooops Error - // todo handle it but should never happen - } - break; - case ' ': - case "\t": - if ($method) { - $this->bodyCanonSpace = true; - break; - } - // no break - default: - if ($this->bodyCanonEmptyCounter > 0) { - $canon .= str_repeat("\r\n", $this->bodyCanonEmptyCounter); - $this->bodyCanonEmptyCounter = 0; - } - if ($this->bodyCanonSpace) { - $this->bodyCanonLine .= ' '; - $canon .= ' '; - $this->bodyCanonSpace = false; - } - $this->bodyCanonLine .= $string[$i]; - $canon .= $string[$i]; - } - } - $this->addToBodyHash($canon); - } - - protected function endOfBody() - { - // Add trailing Line return if last line is non empty - if (\strlen($this->bodyCanonLine) > 0) { - $this->addToBodyHash("\r\n"); - } - $this->bodyHash = hash_final($this->bodyHashHandler, true); - } - - private function addToBodyHash($string) - { - $len = \strlen($string); - if ($len > ($new_len = ($this->maxLen - $this->bodyLen))) { - $string = substr($string, 0, $new_len); - $len = $new_len; - } - hash_update($this->bodyHashHandler, $string); - $this->bodyLen += $len; - } - - private function addToHeaderHash($header) - { - if ($this->debugHeaders) { - $this->debugHeadersData[] = trim($header ?? ''); - } - $this->headerCanonData .= $header; - } - - /** - * @throws Swift_SwiftException - * - * @return string - */ - private function getEncryptedHash() - { - $signature = ''; - switch ($this->hashAlgorithm) { - case 'rsa-sha1': - $algorithm = OPENSSL_ALGO_SHA1; - break; - case 'rsa-sha256': - $algorithm = OPENSSL_ALGO_SHA256; - break; - } - $pkeyId = openssl_get_privatekey($this->privateKey, $this->passphrase); - if (!$pkeyId) { - throw new Swift_SwiftException('Unable to load DKIM Private Key ['.openssl_error_string().']'); - } - if (openssl_sign($this->headerCanonData, $signature, $pkeyId, $algorithm)) { - return $signature; - } - throw new Swift_SwiftException('Unable to sign DKIM Hash ['.openssl_error_string().']'); - } + /** + * PrivateKey. + * + * @var string + */ + protected $privateKey; + + /** + * DomainName. + * + * @var string + */ + protected $domainName; + + /** + * Selector. + * + * @var string + */ + protected $selector; + + private $passphrase = ''; + + /** + * Hash algorithm used. + * + * @see RFC6376 3.3: Signers MUST implement and SHOULD sign using rsa-sha256. + * + * @var string + */ + protected $hashAlgorithm = 'rsa-sha256'; + + /** + * Body canon method. + * + * @var string + */ + protected $bodyCanon = 'simple'; + + /** + * Header canon method. + * + * @var string + */ + protected $headerCanon = 'simple'; + + /** + * Headers not being signed. + * + * @var array + */ + protected $ignoredHeaders = ['return-path' => true]; + + /** + * Signer identity. + * + * @var string + */ + protected $signerIdentity; + + /** + * BodyLength. + * + * @var int + */ + protected $bodyLen = 0; + + /** + * Maximum signedLen. + * + * @var int + */ + protected $maxLen = PHP_INT_MAX; + + /** + * Embbed bodyLen in signature. + * + * @var bool + */ + protected $showLen = false; + + /** + * When the signature has been applied (true means time()), false means not embedded. + * + * @var mixed + */ + protected $signatureTimestamp = true; + + /** + * When will the signature expires false means not embedded, if sigTimestamp is auto + * Expiration is relative, otherwise it's absolute. + * + * @var int + */ + protected $signatureExpiration = false; + + /** + * Must we embed signed headers? + * + * @var bool + */ + protected $debugHeaders = false; + + // work variables + /** + * Headers used to generate hash. + * + * @var array + */ + protected $signedHeaders = []; + + /** + * If debugHeaders is set store debugData here. + * + * @var string[] + */ + private $debugHeadersData = []; + + /** + * Stores the bodyHash. + * + * @var string + */ + private $bodyHash = ''; + + /** + * Stores the signature header. + * + * @var Swift_Mime_Headers_ParameterizedHeader + */ + protected $dkimHeader; + + private $bodyHashHandler; + + private $headerHash; + + private $headerCanonData = ''; + + private $bodyCanonEmptyCounter = 0; + + private $bodyCanonIgnoreStart = 2; + + private $bodyCanonSpace = false; + + private $bodyCanonLastChar = null; + + private $bodyCanonLine = ''; + + private $bound = []; + + /** + * Constructor. + * + * @param string $privateKey + * @param string $domainName + * @param string $selector + * @param string $passphrase + */ + public function __construct($privateKey, $domainName, $selector, $passphrase = '') + { + $this->privateKey = $privateKey; + $this->domainName = $domainName; + $this->signerIdentity = '@'.$domainName; + $this->selector = $selector; + $this->passphrase = $passphrase; + } + + /** + * Reset the Signer. + * + * @see Swift_Signer::reset() + */ + public function reset() + { + $this->headerHash = null; + $this->signedHeaders = []; + $this->bodyHash = null; + $this->bodyHashHandler = null; + $this->bodyCanonIgnoreStart = 2; + $this->bodyCanonEmptyCounter = 0; + $this->bodyCanonLastChar = null; + $this->bodyCanonSpace = false; + } + + /** + * Writes $bytes to the end of the stream. + * + * Writing may not happen immediately if the stream chooses to buffer. If + * you want to write these bytes with immediate effect, call {@link commit()} + * after calling write(). + * + * This method returns the sequence ID of the write (i.e. 1 for first, 2 for + * second, etc etc). + * + * @param string $bytes + * + * @return int + * + * @throws Swift_IoException + */ + // TODO fix return + public function write($bytes) + { + $this->canonicalizeBody($bytes); + foreach ($this->bound as $is) { + $is->write($bytes); + } + } + + /** + * For any bytes that are currently buffered inside the stream, force them + * off the buffer. + */ + public function commit() + { + // Nothing to do + return; + } + + /** + * Attach $is to this stream. + * + * The stream acts as an observer, receiving all data that is written. + * All {@link write()} and {@link flushBuffers()} operations will be mirrored. + */ + public function bind(Swift_InputByteStream $is) + { + // Don't have to mirror anything + $this->bound[] = $is; + + return; + } + + /** + * Remove an already bound stream. + * + * If $is is not bound, no errors will be raised. + * If the stream currently has any buffered data it will be written to $is + * before unbinding occurs. + */ + public function unbind(Swift_InputByteStream $is) + { + // Don't have to mirror anything + foreach ($this->bound as $k => $stream) { + if ($stream === $is) { + unset($this->bound[$k]); + + return; + } + } + } + + /** + * Flush the contents of the stream (empty it) and set the internal pointer + * to the beginning. + * + * @throws Swift_IoException + */ + public function flushBuffers() + { + $this->reset(); + } + + /** + * Set hash_algorithm, must be one of rsa-sha256 | rsa-sha1. + * + * @param string $hash 'rsa-sha1' or 'rsa-sha256' + * + * @throws Swift_SwiftException + * + * @return $this + */ + public function setHashAlgorithm($hash) + { + switch ($hash) { + case 'rsa-sha1': + $this->hashAlgorithm = 'rsa-sha1'; + break; + case 'rsa-sha256': + $this->hashAlgorithm = 'rsa-sha256'; + if (!\defined('OPENSSL_ALGO_SHA256')) { + throw new Swift_SwiftException('Unable to set sha256 as it is not supported by OpenSSL.'); + } + break; + default: + throw new Swift_SwiftException('Unable to set the hash algorithm, must be one of rsa-sha1 or rsa-sha256 (%s given).', $hash); + } + + return $this; + } + + /** + * Set the body canonicalization algorithm. + * + * @param string $canon + * + * @return $this + */ + public function setBodyCanon($canon) + { + if ('relaxed' == $canon) { + $this->bodyCanon = 'relaxed'; + } else { + $this->bodyCanon = 'simple'; + } + + return $this; + } + + /** + * Set the header canonicalization algorithm. + * + * @param string $canon + * + * @return $this + */ + public function setHeaderCanon($canon) + { + if ('relaxed' == $canon) { + $this->headerCanon = 'relaxed'; + } else { + $this->headerCanon = 'simple'; + } + + return $this; + } + + /** + * Set the signer identity. + * + * @param string $identity + * + * @return $this + */ + public function setSignerIdentity($identity) + { + $this->signerIdentity = $identity; + + return $this; + } + + /** + * Set the length of the body to sign. + * + * @param mixed $len (bool or int) + * + * @return $this + */ + public function setBodySignedLen($len) + { + if (true === $len) { + $this->showLen = true; + $this->maxLen = PHP_INT_MAX; + } elseif (false === $len) { + $this->showLen = false; + $this->maxLen = PHP_INT_MAX; + } else { + $this->showLen = true; + $this->maxLen = (int) $len; + } + + return $this; + } + + /** + * Set the signature timestamp. + * + * @param int $time A timestamp + * + * @return $this + */ + public function setSignatureTimestamp($time) + { + $this->signatureTimestamp = $time; + + return $this; + } + + /** + * Set the signature expiration timestamp. + * + * @param int $time A timestamp + * + * @return $this + */ + public function setSignatureExpiration($time) + { + $this->signatureExpiration = $time; + + return $this; + } + + /** + * Enable / disable the DebugHeaders. + * + * @param bool $debug + * + * @return Swift_Signers_DKIMSigner + */ + public function setDebugHeaders($debug) + { + $this->debugHeaders = (bool) $debug; + + return $this; + } + + /** + * Start Body. + */ + public function startBody() + { + // Init + switch ($this->hashAlgorithm) { + case 'rsa-sha256': + $this->bodyHashHandler = hash_init('sha256'); + break; + case 'rsa-sha1': + $this->bodyHashHandler = hash_init('sha1'); + break; + } + $this->bodyCanonLine = ''; + } + + /** + * End Body. + */ + public function endBody() + { + $this->endOfBody(); + } + + /** + * Returns the list of Headers Tampered by this plugin. + * + * @return array + */ + public function getAlteredHeaders() + { + if ($this->debugHeaders) { + return ['DKIM-Signature', 'X-DebugHash']; + } else { + return ['DKIM-Signature']; + } + } + + /** + * Adds an ignored Header. + * + * @param string $header_name + * + * @return Swift_Signers_DKIMSigner + */ + public function ignoreHeader($header_name) + { + $this->ignoredHeaders[strtolower($header_name ?? '')] = true; + + return $this; + } + + /** + * Set the headers to sign. + * + * @return Swift_Signers_DKIMSigner + */ + public function setHeaders(Swift_Mime_SimpleHeaderSet $headers) + { + $this->headerCanonData = ''; + // Loop through Headers + $listHeaders = $headers->listAll(); + foreach ($listHeaders as $hName) { + // Check if we need to ignore Header + if (!isset($this->ignoredHeaders[strtolower($hName ?? '')])) { + if ($headers->has($hName)) { + $tmp = $headers->getAll($hName); + foreach ($tmp as $header) { + if ('' != $header->getFieldBody()) { + $this->addHeader($header->toString()); + $this->signedHeaders[] = $header->getFieldName(); + } + } + } + } + } + + return $this; + } + + /** + * Add the signature to the given Headers. + * + * @return Swift_Signers_DKIMSigner + */ + public function addSignature(Swift_Mime_SimpleHeaderSet $headers) + { + // Prepare the DKIM-Signature + $params = ['v' => '1', 'a' => $this->hashAlgorithm, 'bh' => base64_encode($this->bodyHash ?? ''), 'd' => $this->domainName, 'h' => implode(': ', $this->signedHeaders), 'i' => $this->signerIdentity, 's' => $this->selector]; + if ('simple' != $this->bodyCanon) { + $params['c'] = $this->headerCanon.'/'.$this->bodyCanon; + } elseif ('simple' != $this->headerCanon) { + $params['c'] = $this->headerCanon; + } + if ($this->showLen) { + $params['l'] = $this->bodyLen; + } + if (true === $this->signatureTimestamp) { + $params['t'] = time(); + if (false !== $this->signatureExpiration) { + $params['x'] = $params['t'] + $this->signatureExpiration; + } + } else { + if (false !== $this->signatureTimestamp) { + $params['t'] = $this->signatureTimestamp; + } + if (false !== $this->signatureExpiration) { + $params['x'] = $this->signatureExpiration; + } + } + if ($this->debugHeaders) { + $params['z'] = implode('|', $this->debugHeadersData); + } + $string = ''; + foreach ($params as $k => $v) { + $string .= $k.'='.$v.'; '; + } + $string = trim($string); + $headers->addTextHeader('DKIM-Signature', $string); + // Add the last DKIM-Signature + $tmp = $headers->getAll('DKIM-Signature'); + $this->dkimHeader = end($tmp); + $this->addHeader(trim($this->dkimHeader->toString() ?? '')."\r\n b=", true); + if ($this->debugHeaders) { + $headers->addTextHeader('X-DebugHash', base64_encode($this->headerHash ?? '')); + } + $this->dkimHeader->setValue($string.' b='.trim(chunk_split(base64_encode($this->getEncryptedHash() ?? ''), 73, ' '))); + + return $this; + } + + /* Private helpers */ + + protected function addHeader($header, $is_sig = false) + { + switch ($this->headerCanon) { + case 'relaxed': + // Prepare Header and cascade + $exploded = explode(':', $header, 2); + $name = strtolower(trim($exploded[0])); + $value = str_replace("\r\n", '', $exploded[1]); + $value = preg_replace("/[ \t][ \t]+/", ' ', $value); + $header = $name.':'.trim($value).($is_sig ? '' : "\r\n"); + // no break + case 'simple': + // Nothing to do + } + $this->addToHeaderHash($header); + } + + protected function canonicalizeBody($string) + { + $len = \strlen($string); + $canon = ''; + $method = ('relaxed' == $this->bodyCanon); + for ($i = 0; $i < $len; ++$i) { + if ($this->bodyCanonIgnoreStart > 0) { + --$this->bodyCanonIgnoreStart; + continue; + } + switch ($string[$i]) { + case "\r": + $this->bodyCanonLastChar = "\r"; + break; + case "\n": + if ("\r" == $this->bodyCanonLastChar) { + if ($method) { + $this->bodyCanonSpace = false; + } + if ('' == $this->bodyCanonLine) { + ++$this->bodyCanonEmptyCounter; + } else { + $this->bodyCanonLine = ''; + $canon .= "\r\n"; + } + } else { + // Wooops Error + // todo handle it but should never happen + } + break; + case ' ': + case "\t": + if ($method) { + $this->bodyCanonSpace = true; + break; + } + // no break + default: + if ($this->bodyCanonEmptyCounter > 0) { + $canon .= str_repeat("\r\n", $this->bodyCanonEmptyCounter); + $this->bodyCanonEmptyCounter = 0; + } + if ($this->bodyCanonSpace) { + $this->bodyCanonLine .= ' '; + $canon .= ' '; + $this->bodyCanonSpace = false; + } + $this->bodyCanonLine .= $string[$i]; + $canon .= $string[$i]; + } + } + $this->addToBodyHash($canon); + } + + protected function endOfBody() + { + // Add trailing Line return if last line is non empty + if (\strlen($this->bodyCanonLine) > 0) { + $this->addToBodyHash("\r\n"); + } + $this->bodyHash = hash_final($this->bodyHashHandler, true); + } + + private function addToBodyHash($string) + { + $len = \strlen($string); + if ($len > ($new_len = ($this->maxLen - $this->bodyLen))) { + $string = substr($string, 0, $new_len); + $len = $new_len; + } + hash_update($this->bodyHashHandler, $string); + $this->bodyLen += $len; + } + + private function addToHeaderHash($header) + { + if ($this->debugHeaders) { + $this->debugHeadersData[] = trim($header ?? ''); + } + $this->headerCanonData .= $header; + } + + /** + * @throws Swift_SwiftException + * + * @return string + */ + private function getEncryptedHash() + { + $signature = ''; + switch ($this->hashAlgorithm) { + case 'rsa-sha1': + $algorithm = OPENSSL_ALGO_SHA1; + break; + case 'rsa-sha256': + $algorithm = OPENSSL_ALGO_SHA256; + break; + } + $pkeyId = openssl_get_privatekey($this->privateKey, $this->passphrase); + if (!$pkeyId) { + throw new Swift_SwiftException('Unable to load DKIM Private Key ['.openssl_error_string().']'); + } + if (openssl_sign($this->headerCanonData, $signature, $pkeyId, $algorithm)) { + return $signature; + } + throw new Swift_SwiftException('Unable to sign DKIM Hash ['.openssl_error_string().']'); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/DomainKeySigner.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/DomainKeySigner.php index 5e2b67b6520..884996b40eb 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/DomainKeySigner.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/DomainKeySigner.php @@ -15,490 +15,490 @@ */ class Swift_Signers_DomainKeySigner implements Swift_Signers_HeaderSigner { - /** - * PrivateKey. - * - * @var string - */ - protected $privateKey; + /** + * PrivateKey. + * + * @var string + */ + protected $privateKey; - /** - * DomainName. - * - * @var string - */ - protected $domainName; + /** + * DomainName. + * + * @var string + */ + protected $domainName; - /** - * Selector. - * - * @var string - */ - protected $selector; + /** + * Selector. + * + * @var string + */ + protected $selector; - /** - * Hash algorithm used. - * - * @var string - */ - protected $hashAlgorithm = 'rsa-sha1'; + /** + * Hash algorithm used. + * + * @var string + */ + protected $hashAlgorithm = 'rsa-sha1'; - /** - * Canonisation method. - * - * @var string - */ - protected $canon = 'simple'; + /** + * Canonisation method. + * + * @var string + */ + protected $canon = 'simple'; - /** - * Headers not being signed. - * - * @var array - */ - protected $ignoredHeaders = []; + /** + * Headers not being signed. + * + * @var array + */ + protected $ignoredHeaders = []; - /** - * Signer identity. - * - * @var string - */ - protected $signerIdentity; + /** + * Signer identity. + * + * @var string + */ + protected $signerIdentity; - /** - * Must we embed signed headers? - * - * @var bool - */ - protected $debugHeaders = false; + /** + * Must we embed signed headers? + * + * @var bool + */ + protected $debugHeaders = false; - // work variables - /** - * Headers used to generate hash. - * - * @var array - */ - private $signedHeaders = []; + // work variables + /** + * Headers used to generate hash. + * + * @var array + */ + private $signedHeaders = []; - /** - * Stores the signature header. - * - * @var Swift_Mime_Headers_ParameterizedHeader - */ - protected $domainKeyHeader; + /** + * Stores the signature header. + * + * @var Swift_Mime_Headers_ParameterizedHeader + */ + protected $domainKeyHeader; - /** - * Hash Handler. - * - * @var resource|null - */ - private $hashHandler; + /** + * Hash Handler. + * + * @var resource|null + */ + private $hashHandler; - private $canonData = ''; + private $canonData = ''; - private $bodyCanonEmptyCounter = 0; + private $bodyCanonEmptyCounter = 0; - private $bodyCanonIgnoreStart = 2; + private $bodyCanonIgnoreStart = 2; - private $bodyCanonSpace = false; + private $bodyCanonSpace = false; - private $bodyCanonLastChar = null; + private $bodyCanonLastChar = null; - private $bodyCanonLine = ''; + private $bodyCanonLine = ''; - private $bound = []; + private $bound = []; - /** - * Constructor. - * - * @param string $privateKey - * @param string $domainName - * @param string $selector - */ - public function __construct($privateKey, $domainName, $selector) - { - $this->privateKey = $privateKey; - $this->domainName = $domainName; - $this->signerIdentity = '@'.$domainName; - $this->selector = $selector; - } + /** + * Constructor. + * + * @param string $privateKey + * @param string $domainName + * @param string $selector + */ + public function __construct($privateKey, $domainName, $selector) + { + $this->privateKey = $privateKey; + $this->domainName = $domainName; + $this->signerIdentity = '@'.$domainName; + $this->selector = $selector; + } - /** - * Resets internal states. - * - * @return $this - */ - public function reset() - { - $this->hashHandler = null; - $this->bodyCanonIgnoreStart = 2; - $this->bodyCanonEmptyCounter = 0; - $this->bodyCanonLastChar = null; - $this->bodyCanonSpace = false; + /** + * Resets internal states. + * + * @return $this + */ + public function reset() + { + $this->hashHandler = null; + $this->bodyCanonIgnoreStart = 2; + $this->bodyCanonEmptyCounter = 0; + $this->bodyCanonLastChar = null; + $this->bodyCanonSpace = false; - return $this; - } + return $this; + } - /** - * Writes $bytes to the end of the stream. - * - * Writing may not happen immediately if the stream chooses to buffer. If - * you want to write these bytes with immediate effect, call {@link commit()} - * after calling write(). - * - * This method returns the sequence ID of the write (i.e. 1 for first, 2 for - * second, etc etc). - * - * @param string $bytes - * - * @return int - * - * @throws Swift_IoException - * - * @return $this - */ - public function write($bytes) - { - $this->canonicalizeBody($bytes); - foreach ($this->bound as $is) { - $is->write($bytes); - } + /** + * Writes $bytes to the end of the stream. + * + * Writing may not happen immediately if the stream chooses to buffer. If + * you want to write these bytes with immediate effect, call {@link commit()} + * after calling write(). + * + * This method returns the sequence ID of the write (i.e. 1 for first, 2 for + * second, etc etc). + * + * @param string $bytes + * + * @return int + * + * @throws Swift_IoException + * + * @return $this + */ + public function write($bytes) + { + $this->canonicalizeBody($bytes); + foreach ($this->bound as $is) { + $is->write($bytes); + } - return $this; - } + return $this; + } - /** - * For any bytes that are currently buffered inside the stream, force them - * off the buffer. - * - * @throws Swift_IoException - * - * @return $this - */ - public function commit() - { - // Nothing to do - return $this; - } + /** + * For any bytes that are currently buffered inside the stream, force them + * off the buffer. + * + * @throws Swift_IoException + * + * @return $this + */ + public function commit() + { + // Nothing to do + return $this; + } - /** - * Attach $is to this stream. - * - * The stream acts as an observer, receiving all data that is written. - * All {@link write()} and {@link flushBuffers()} operations will be mirrored. - * - * @return $this - */ - public function bind(Swift_InputByteStream $is) - { - // Don't have to mirror anything - $this->bound[] = $is; + /** + * Attach $is to this stream. + * + * The stream acts as an observer, receiving all data that is written. + * All {@link write()} and {@link flushBuffers()} operations will be mirrored. + * + * @return $this + */ + public function bind(Swift_InputByteStream $is) + { + // Don't have to mirror anything + $this->bound[] = $is; - return $this; - } + return $this; + } - /** - * Remove an already bound stream. - * - * If $is is not bound, no errors will be raised. - * If the stream currently has any buffered data it will be written to $is - * before unbinding occurs. - * - * @return $this - */ - public function unbind(Swift_InputByteStream $is) - { - // Don't have to mirror anything - foreach ($this->bound as $k => $stream) { - if ($stream === $is) { - unset($this->bound[$k]); + /** + * Remove an already bound stream. + * + * If $is is not bound, no errors will be raised. + * If the stream currently has any buffered data it will be written to $is + * before unbinding occurs. + * + * @return $this + */ + public function unbind(Swift_InputByteStream $is) + { + // Don't have to mirror anything + foreach ($this->bound as $k => $stream) { + if ($stream === $is) { + unset($this->bound[$k]); - break; - } - } + break; + } + } - return $this; - } + return $this; + } - /** - * Flush the contents of the stream (empty it) and set the internal pointer - * to the beginning. - * - * @throws Swift_IoException - * - * @return $this - */ - public function flushBuffers() - { - $this->reset(); + /** + * Flush the contents of the stream (empty it) and set the internal pointer + * to the beginning. + * + * @throws Swift_IoException + * + * @return $this + */ + public function flushBuffers() + { + $this->reset(); - return $this; - } + return $this; + } - /** - * Set hash_algorithm, must be one of rsa-sha256 | rsa-sha1 defaults to rsa-sha256. - * - * @param string $hash - * - * @return $this - */ - public function setHashAlgorithm($hash) - { - $this->hashAlgorithm = 'rsa-sha1'; + /** + * Set hash_algorithm, must be one of rsa-sha256 | rsa-sha1 defaults to rsa-sha256. + * + * @param string $hash + * + * @return $this + */ + public function setHashAlgorithm($hash) + { + $this->hashAlgorithm = 'rsa-sha1'; - return $this; - } + return $this; + } - /** - * Set the canonicalization algorithm. - * - * @param string $canon simple | nofws defaults to simple - * - * @return $this - */ - public function setCanon($canon) - { - if ('nofws' == $canon) { - $this->canon = 'nofws'; - } else { - $this->canon = 'simple'; - } + /** + * Set the canonicalization algorithm. + * + * @param string $canon simple | nofws defaults to simple + * + * @return $this + */ + public function setCanon($canon) + { + if ('nofws' == $canon) { + $this->canon = 'nofws'; + } else { + $this->canon = 'simple'; + } - return $this; - } + return $this; + } - /** - * Set the signer identity. - * - * @param string $identity - * - * @return $this - */ - public function setSignerIdentity($identity) - { - $this->signerIdentity = $identity; + /** + * Set the signer identity. + * + * @param string $identity + * + * @return $this + */ + public function setSignerIdentity($identity) + { + $this->signerIdentity = $identity; - return $this; - } + return $this; + } - /** - * Enable / disable the DebugHeaders. - * - * @param bool $debug - * - * @return $this - */ - public function setDebugHeaders($debug) - { - $this->debugHeaders = (bool) $debug; + /** + * Enable / disable the DebugHeaders. + * + * @param bool $debug + * + * @return $this + */ + public function setDebugHeaders($debug) + { + $this->debugHeaders = (bool) $debug; - return $this; - } + return $this; + } - /** - * Start Body. - */ - public function startBody() - { - } + /** + * Start Body. + */ + public function startBody() + { + } - /** - * End Body. - */ - public function endBody() - { - $this->endOfBody(); - } + /** + * End Body. + */ + public function endBody() + { + $this->endOfBody(); + } - /** - * Returns the list of Headers Tampered by this plugin. - * - * @return array - */ - public function getAlteredHeaders() - { - if ($this->debugHeaders) { - return ['DomainKey-Signature', 'X-DebugHash']; - } + /** + * Returns the list of Headers Tampered by this plugin. + * + * @return array + */ + public function getAlteredHeaders() + { + if ($this->debugHeaders) { + return ['DomainKey-Signature', 'X-DebugHash']; + } - return ['DomainKey-Signature']; - } + return ['DomainKey-Signature']; + } - /** - * Adds an ignored Header. - * - * @param string $header_name - * - * @return $this - */ - public function ignoreHeader($header_name) - { - $this->ignoredHeaders[strtolower($header_name ?? '')] = true; + /** + * Adds an ignored Header. + * + * @param string $header_name + * + * @return $this + */ + public function ignoreHeader($header_name) + { + $this->ignoredHeaders[strtolower($header_name ?? '')] = true; - return $this; - } + return $this; + } - /** - * Set the headers to sign. - * - * @return $this - */ - public function setHeaders(Swift_Mime_SimpleHeaderSet $headers) - { - $this->startHash(); - $this->canonData = ''; - // Loop through Headers - $listHeaders = $headers->listAll(); - foreach ($listHeaders as $hName) { - // Check if we need to ignore Header - if (!isset($this->ignoredHeaders[strtolower($hName ?? '')])) { - if ($headers->has($hName)) { - $tmp = $headers->getAll($hName); - foreach ($tmp as $header) { - if ('' != $header->getFieldBody()) { - $this->addHeader($header->toString()); - $this->signedHeaders[] = $header->getFieldName(); - } - } - } - } - } - $this->endOfHeaders(); + /** + * Set the headers to sign. + * + * @return $this + */ + public function setHeaders(Swift_Mime_SimpleHeaderSet $headers) + { + $this->startHash(); + $this->canonData = ''; + // Loop through Headers + $listHeaders = $headers->listAll(); + foreach ($listHeaders as $hName) { + // Check if we need to ignore Header + if (!isset($this->ignoredHeaders[strtolower($hName ?? '')])) { + if ($headers->has($hName)) { + $tmp = $headers->getAll($hName); + foreach ($tmp as $header) { + if ('' != $header->getFieldBody()) { + $this->addHeader($header->toString()); + $this->signedHeaders[] = $header->getFieldName(); + } + } + } + } + } + $this->endOfHeaders(); - return $this; - } + return $this; + } - /** - * Add the signature to the given Headers. - * - * @return $this - */ - public function addSignature(Swift_Mime_SimpleHeaderSet $headers) - { - // Prepare the DomainKey-Signature Header - $params = ['a' => $this->hashAlgorithm, 'b' => chunk_split(base64_encode($this->getEncryptedHash() ?? ''), 73, ' '), 'c' => $this->canon, 'd' => $this->domainName, 'h' => implode(': ', $this->signedHeaders), 'q' => 'dns', 's' => $this->selector]; - $string = ''; - foreach ($params as $k => $v) { - $string .= $k.'='.$v.'; '; - } - $string = trim($string); - $headers->addTextHeader('DomainKey-Signature', $string); + /** + * Add the signature to the given Headers. + * + * @return $this + */ + public function addSignature(Swift_Mime_SimpleHeaderSet $headers) + { + // Prepare the DomainKey-Signature Header + $params = ['a' => $this->hashAlgorithm, 'b' => chunk_split(base64_encode($this->getEncryptedHash() ?? ''), 73, ' '), 'c' => $this->canon, 'd' => $this->domainName, 'h' => implode(': ', $this->signedHeaders), 'q' => 'dns', 's' => $this->selector]; + $string = ''; + foreach ($params as $k => $v) { + $string .= $k.'='.$v.'; '; + } + $string = trim($string); + $headers->addTextHeader('DomainKey-Signature', $string); - return $this; - } + return $this; + } - /* Private helpers */ + /* Private helpers */ - protected function addHeader($header) - { - switch ($this->canon) { - case 'nofws': - // Prepare Header and cascade - $exploded = explode(':', $header, 2); - $name = strtolower(trim($exploded[0])); - $value = str_replace("\r\n", '', $exploded[1]); - $value = preg_replace("/[ \t][ \t]+/", ' ', $value); - $header = $name.':'.trim($value)."\r\n"; - // no break - case 'simple': - // Nothing to do - } - $this->addToHash($header); - } + protected function addHeader($header) + { + switch ($this->canon) { + case 'nofws': + // Prepare Header and cascade + $exploded = explode(':', $header, 2); + $name = strtolower(trim($exploded[0])); + $value = str_replace("\r\n", '', $exploded[1]); + $value = preg_replace("/[ \t][ \t]+/", ' ', $value); + $header = $name.':'.trim($value)."\r\n"; + // no break + case 'simple': + // Nothing to do + } + $this->addToHash($header); + } - protected function endOfHeaders() - { - $this->bodyCanonEmptyCounter = 1; - } + protected function endOfHeaders() + { + $this->bodyCanonEmptyCounter = 1; + } - protected function canonicalizeBody($string) - { - $len = \strlen($string); - $canon = ''; - $nofws = ('nofws' == $this->canon); - for ($i = 0; $i < $len; ++$i) { - if ($this->bodyCanonIgnoreStart > 0) { - --$this->bodyCanonIgnoreStart; - continue; - } - switch ($string[$i]) { - case "\r": - $this->bodyCanonLastChar = "\r"; - break; - case "\n": - if ("\r" == $this->bodyCanonLastChar) { - if ($nofws) { - $this->bodyCanonSpace = false; - } - if ('' == $this->bodyCanonLine) { - ++$this->bodyCanonEmptyCounter; - } else { - $this->bodyCanonLine = ''; - $canon .= "\r\n"; - } - } else { - // Wooops Error - throw new Swift_SwiftException('Invalid new line sequence in mail found \n without preceding \r'); - } - break; - case ' ': - case "\t": - case "\x09": //HTAB - if ($nofws) { - $this->bodyCanonSpace = true; - break; - } - // no break - default: - if ($this->bodyCanonEmptyCounter > 0) { - $canon .= str_repeat("\r\n", $this->bodyCanonEmptyCounter); - $this->bodyCanonEmptyCounter = 0; - } - $this->bodyCanonLine .= $string[$i]; - $canon .= $string[$i]; - } - } - $this->addToHash($canon); - } + protected function canonicalizeBody($string) + { + $len = \strlen($string); + $canon = ''; + $nofws = ('nofws' == $this->canon); + for ($i = 0; $i < $len; ++$i) { + if ($this->bodyCanonIgnoreStart > 0) { + --$this->bodyCanonIgnoreStart; + continue; + } + switch ($string[$i]) { + case "\r": + $this->bodyCanonLastChar = "\r"; + break; + case "\n": + if ("\r" == $this->bodyCanonLastChar) { + if ($nofws) { + $this->bodyCanonSpace = false; + } + if ('' == $this->bodyCanonLine) { + ++$this->bodyCanonEmptyCounter; + } else { + $this->bodyCanonLine = ''; + $canon .= "\r\n"; + } + } else { + // Wooops Error + throw new Swift_SwiftException('Invalid new line sequence in mail found \n without preceding \r'); + } + break; + case ' ': + case "\t": + case "\x09": //HTAB + if ($nofws) { + $this->bodyCanonSpace = true; + break; + } + // no break + default: + if ($this->bodyCanonEmptyCounter > 0) { + $canon .= str_repeat("\r\n", $this->bodyCanonEmptyCounter); + $this->bodyCanonEmptyCounter = 0; + } + $this->bodyCanonLine .= $string[$i]; + $canon .= $string[$i]; + } + } + $this->addToHash($canon); + } - protected function endOfBody() - { - if (\strlen($this->bodyCanonLine) > 0) { - $this->addToHash("\r\n"); - } - } + protected function endOfBody() + { + if (\strlen($this->bodyCanonLine) > 0) { + $this->addToHash("\r\n"); + } + } - private function addToHash($string) - { - $this->canonData .= $string; - hash_update($this->hashHandler, $string); - } + private function addToHash($string) + { + $this->canonData .= $string; + hash_update($this->hashHandler, $string); + } - private function startHash() - { - // Init - switch ($this->hashAlgorithm) { - case 'rsa-sha1': - $this->hashHandler = hash_init('sha1'); - break; - } - $this->bodyCanonLine = ''; - } + private function startHash() + { + // Init + switch ($this->hashAlgorithm) { + case 'rsa-sha1': + $this->hashHandler = hash_init('sha1'); + break; + } + $this->bodyCanonLine = ''; + } - /** - * @throws Swift_SwiftException - * - * @return string - */ - private function getEncryptedHash() - { - $signature = ''; - $pkeyId = openssl_get_privatekey($this->privateKey); - if (!$pkeyId) { - throw new Swift_SwiftException('Unable to load DomainKey Private Key ['.openssl_error_string().']'); - } - if (openssl_sign($this->canonData, $signature, $pkeyId, OPENSSL_ALGO_SHA1)) { - return $signature; - } - throw new Swift_SwiftException('Unable to sign DomainKey Hash ['.openssl_error_string().']'); - } + /** + * @throws Swift_SwiftException + * + * @return string + */ + private function getEncryptedHash() + { + $signature = ''; + $pkeyId = openssl_get_privatekey($this->privateKey); + if (!$pkeyId) { + throw new Swift_SwiftException('Unable to load DomainKey Private Key ['.openssl_error_string().']'); + } + if (openssl_sign($this->canonData, $signature, $pkeyId, OPENSSL_ALGO_SHA1)) { + return $signature; + } + throw new Swift_SwiftException('Unable to sign DomainKey Hash ['.openssl_error_string().']'); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/HeaderSigner.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/HeaderSigner.php index 6f5c20923dc..94136b94d85 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/HeaderSigner.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/HeaderSigner.php @@ -15,47 +15,47 @@ */ interface Swift_Signers_HeaderSigner extends Swift_Signer, Swift_InputByteStream { - /** - * Exclude an header from the signed headers. - * - * @param string $header_name - * - * @return self - */ - public function ignoreHeader($header_name); + /** + * Exclude an header from the signed headers. + * + * @param string $header_name + * + * @return self + */ + public function ignoreHeader($header_name); - /** - * Prepare the Signer to get a new Body. - * - * @return self - */ - public function startBody(); + /** + * Prepare the Signer to get a new Body. + * + * @return self + */ + public function startBody(); - /** - * Give the signal that the body has finished streaming. - * - * @return self - */ - public function endBody(); + /** + * Give the signal that the body has finished streaming. + * + * @return self + */ + public function endBody(); - /** - * Give the headers already given. - * - * @return self - */ - public function setHeaders(Swift_Mime_SimpleHeaderSet $headers); + /** + * Give the headers already given. + * + * @return self + */ + public function setHeaders(Swift_Mime_SimpleHeaderSet $headers); - /** - * Add the header(s) to the headerSet. - * - * @return self - */ - public function addSignature(Swift_Mime_SimpleHeaderSet $headers); + /** + * Add the header(s) to the headerSet. + * + * @return self + */ + public function addSignature(Swift_Mime_SimpleHeaderSet $headers); - /** - * Return the list of header a signer might tamper. - * - * @return array - */ - public function getAlteredHeaders(); + /** + * Return the list of header a signer might tamper. + * + * @return array + */ + public function getAlteredHeaders(); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/OpenDKIMSigner.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/OpenDKIMSigner.php index 520bcc15e8b..fb0504dafa7 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/OpenDKIMSigner.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/OpenDKIMSigner.php @@ -18,166 +18,166 @@ */ class Swift_Signers_OpenDKIMSigner extends Swift_Signers_DKIMSigner { - private $peclLoaded = false; + private $peclLoaded = false; - private $dkimHandler = null; + private $dkimHandler = null; - private $dropFirstLF = true; + private $dropFirstLF = true; - const CANON_RELAXED = 1; - const CANON_SIMPLE = 2; - const SIG_RSA_SHA1 = 3; - const SIG_RSA_SHA256 = 4; + const CANON_RELAXED = 1; + const CANON_SIMPLE = 2; + const SIG_RSA_SHA1 = 3; + const SIG_RSA_SHA256 = 4; - public function __construct($privateKey, $domainName, $selector) - { - if (!\extension_loaded('opendkim')) { - throw new Swift_SwiftException('php-opendkim extension not found'); - } + public function __construct($privateKey, $domainName, $selector) + { + if (!\extension_loaded('opendkim')) { + throw new Swift_SwiftException('php-opendkim extension not found'); + } - $this->peclLoaded = true; + $this->peclLoaded = true; - parent::__construct($privateKey, $domainName, $selector); - } + parent::__construct($privateKey, $domainName, $selector); + } - public function addSignature(Swift_Mime_SimpleHeaderSet $headers) - { - $header = new Swift_Mime_Headers_OpenDKIMHeader('DKIM-Signature'); - $headerVal = $this->dkimHandler->getSignatureHeader(); - if (false === $headerVal || \is_int($headerVal)) { - throw new Swift_SwiftException('OpenDKIM Error: '.$this->dkimHandler->getError()); - } - $header->setValue($headerVal); - $headers->set($header); + public function addSignature(Swift_Mime_SimpleHeaderSet $headers) + { + $header = new Swift_Mime_Headers_OpenDKIMHeader('DKIM-Signature'); + $headerVal = $this->dkimHandler->getSignatureHeader(); + if (false === $headerVal || \is_int($headerVal)) { + throw new Swift_SwiftException('OpenDKIM Error: '.$this->dkimHandler->getError()); + } + $header->setValue($headerVal); + $headers->set($header); - return $this; - } + return $this; + } - public function setHeaders(Swift_Mime_SimpleHeaderSet $headers) - { - $hash = 'rsa-sha1' == $this->hashAlgorithm ? OpenDKIMSign::ALG_RSASHA1 : OpenDKIMSign::ALG_RSASHA256; - $bodyCanon = 'simple' == $this->bodyCanon ? OpenDKIMSign::CANON_SIMPLE : OpenDKIMSign::CANON_RELAXED; - $headerCanon = 'simple' == $this->headerCanon ? OpenDKIMSign::CANON_SIMPLE : OpenDKIMSign::CANON_RELAXED; - $this->dkimHandler = new OpenDKIMSign($this->privateKey, $this->selector, $this->domainName, $headerCanon, $bodyCanon, $hash, -1); - // Hardcode signature Margin for now - $this->dkimHandler->setMargin(78); + public function setHeaders(Swift_Mime_SimpleHeaderSet $headers) + { + $hash = 'rsa-sha1' == $this->hashAlgorithm ? OpenDKIMSign::ALG_RSASHA1 : OpenDKIMSign::ALG_RSASHA256; + $bodyCanon = 'simple' == $this->bodyCanon ? OpenDKIMSign::CANON_SIMPLE : OpenDKIMSign::CANON_RELAXED; + $headerCanon = 'simple' == $this->headerCanon ? OpenDKIMSign::CANON_SIMPLE : OpenDKIMSign::CANON_RELAXED; + $this->dkimHandler = new OpenDKIMSign($this->privateKey, $this->selector, $this->domainName, $headerCanon, $bodyCanon, $hash, -1); + // Hardcode signature Margin for now + $this->dkimHandler->setMargin(78); - if (!is_numeric($this->signatureTimestamp)) { - OpenDKIM::setOption(OpenDKIM::OPTS_FIXEDTIME, time()); - } else { - if (!OpenDKIM::setOption(OpenDKIM::OPTS_FIXEDTIME, $this->signatureTimestamp)) { - throw new Swift_SwiftException('Unable to force signature timestamp ['.openssl_error_string().']'); - } - } - if (isset($this->signerIdentity)) { - $this->dkimHandler->setSigner($this->signerIdentity); - } - $listHeaders = $headers->listAll(); - foreach ($listHeaders as $hName) { - // Check if we need to ignore Header - if (!isset($this->ignoredHeaders[strtolower($hName ?? '')])) { - $tmp = $headers->getAll($hName); - if ($headers->has($hName)) { - foreach ($tmp as $header) { - if ('' != $header->getFieldBody()) { - $htosign = $header->toString(); - $this->dkimHandler->header($htosign); - $this->signedHeaders[] = $header->getFieldName(); - } - } - } - } - } + if (!is_numeric($this->signatureTimestamp)) { + OpenDKIM::setOption(OpenDKIM::OPTS_FIXEDTIME, time()); + } else { + if (!OpenDKIM::setOption(OpenDKIM::OPTS_FIXEDTIME, $this->signatureTimestamp)) { + throw new Swift_SwiftException('Unable to force signature timestamp ['.openssl_error_string().']'); + } + } + if (isset($this->signerIdentity)) { + $this->dkimHandler->setSigner($this->signerIdentity); + } + $listHeaders = $headers->listAll(); + foreach ($listHeaders as $hName) { + // Check if we need to ignore Header + if (!isset($this->ignoredHeaders[strtolower($hName ?? '')])) { + $tmp = $headers->getAll($hName); + if ($headers->has($hName)) { + foreach ($tmp as $header) { + if ('' != $header->getFieldBody()) { + $htosign = $header->toString(); + $this->dkimHandler->header($htosign); + $this->signedHeaders[] = $header->getFieldName(); + } + } + } + } + } - return $this; - } + return $this; + } - public function startBody() - { - if (!$this->peclLoaded) { - return parent::startBody(); - } - $this->dropFirstLF = true; - $this->dkimHandler->eoh(); + public function startBody() + { + if (!$this->peclLoaded) { + return parent::startBody(); + } + $this->dropFirstLF = true; + $this->dkimHandler->eoh(); - return $this; - } + return $this; + } - public function endBody() - { - if (!$this->peclLoaded) { - return parent::endBody(); - } - $this->dkimHandler->eom(); + public function endBody() + { + if (!$this->peclLoaded) { + return parent::endBody(); + } + $this->dkimHandler->eom(); - return $this; - } + return $this; + } - public function reset() - { - $this->dkimHandler = null; - parent::reset(); + public function reset() + { + $this->dkimHandler = null; + parent::reset(); - return $this; - } + return $this; + } - /** - * Set the signature timestamp. - * - * @param int $time - * - * @return $this - */ - public function setSignatureTimestamp($time) - { - $this->signatureTimestamp = $time; + /** + * Set the signature timestamp. + * + * @param int $time + * + * @return $this + */ + public function setSignatureTimestamp($time) + { + $this->signatureTimestamp = $time; - return $this; - } + return $this; + } - /** - * Set the signature expiration timestamp. - * - * @param int $time - * - * @return $this - */ - public function setSignatureExpiration($time) - { - $this->signatureExpiration = $time; + /** + * Set the signature expiration timestamp. + * + * @param int $time + * + * @return $this + */ + public function setSignatureExpiration($time) + { + $this->signatureExpiration = $time; - return $this; - } + return $this; + } - /** - * Enable / disable the DebugHeaders. - * - * @param bool $debug - * - * @return $this - */ - public function setDebugHeaders($debug) - { - $this->debugHeaders = (bool) $debug; + /** + * Enable / disable the DebugHeaders. + * + * @param bool $debug + * + * @return $this + */ + public function setDebugHeaders($debug) + { + $this->debugHeaders = (bool) $debug; - return $this; - } + return $this; + } - // Protected + // Protected - protected function canonicalizeBody($string) - { - if (!$this->peclLoaded) { - return parent::canonicalizeBody($string); - } - if (true === $this->dropFirstLF) { - if ("\r" == $string[0] && "\n" == $string[1]) { - $string = substr($string, 2); - } - } - $this->dropFirstLF = false; - if (\strlen($string)) { - $this->dkimHandler->body($string); - } - } + protected function canonicalizeBody($string) + { + if (!$this->peclLoaded) { + return parent::canonicalizeBody($string); + } + if (true === $this->dropFirstLF) { + if ("\r" == $string[0] && "\n" == $string[1]) { + $string = substr($string, 2); + } + } + $this->dropFirstLF = false; + if (\strlen($string)) { + $this->dkimHandler->body($string); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/SMimeSigner.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/SMimeSigner.php index 3dd3cd05f04..e3a489530af 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/SMimeSigner.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/SMimeSigner.php @@ -17,526 +17,526 @@ */ class Swift_Signers_SMimeSigner implements Swift_Signers_BodySigner { - protected $signCertificate; - protected $signPrivateKey; - protected $encryptCert; - protected $signThenEncrypt = true; - protected $signLevel; - protected $encryptLevel; - protected $signOptions; - protected $encryptOptions; - protected $encryptCipher; - protected $extraCerts = null; - protected $wrapFullMessage = false; - - /** - * @var Swift_StreamFilters_StringReplacementFilterFactory - */ - protected $replacementFactory; - - /** - * @var Swift_Mime_SimpleHeaderFactory - */ - protected $headerFactory; - - /** - * Constructor. - * - * @param string|null $signCertificate - * @param string|null $signPrivateKey - * @param string|null $encryptCertificate - */ - public function __construct($signCertificate = null, $signPrivateKey = null, $encryptCertificate = null) - { - if (null !== $signPrivateKey) { - $this->setSignCertificate($signCertificate, $signPrivateKey); - } - - if (null !== $encryptCertificate) { - $this->setEncryptCertificate($encryptCertificate); - } - - $this->replacementFactory = Swift_DependencyContainer::getInstance() - ->lookup('transport.replacementfactory'); - - $this->signOptions = PKCS7_DETACHED; - $this->encryptCipher = OPENSSL_CIPHER_AES_128_CBC; - } - - /** - * Set the certificate location to use for signing. - * - * @see https://secure.php.net/manual/en/openssl.pkcs7.flags.php - * - * @param string $certificate - * @param string|array $privateKey If the key needs an passphrase use array('file-location', 'passphrase') instead - * @param int $signOptions Bitwise operator options for openssl_pkcs7_sign() - * @param string $extraCerts A file containing intermediate certificates needed by the signing certificate - * - * @return $this - */ - public function setSignCertificate($certificate, $privateKey = null, $signOptions = PKCS7_DETACHED, $extraCerts = null) - { - $this->signCertificate = 'file://'.str_replace('\\', '/', realpath($certificate)); - - if (null !== $privateKey) { - if (\is_array($privateKey)) { - $this->signPrivateKey = $privateKey; - $this->signPrivateKey[0] = 'file://'.str_replace('\\', '/', realpath($privateKey[0])); - } else { - $this->signPrivateKey = 'file://'.str_replace('\\', '/', realpath($privateKey)); - } - } - - $this->signOptions = $signOptions; - $this->extraCerts = $extraCerts ? realpath($extraCerts) : null; - - return $this; - } - - /** - * Set the certificate location to use for encryption. - * - * @see https://secure.php.net/manual/en/openssl.pkcs7.flags.php - * @see https://secure.php.net/manual/en/openssl.ciphers.php - * - * @param string|array $recipientCerts Either an single X.509 certificate, or an assoc array of X.509 certificates. - * @param int $cipher - * - * @return $this - */ - public function setEncryptCertificate($recipientCerts, $cipher = null) - { - if (\is_array($recipientCerts)) { - $this->encryptCert = []; - - foreach ($recipientCerts as $cert) { - $this->encryptCert[] = 'file://'.str_replace('\\', '/', realpath($cert)); - } - } else { - $this->encryptCert = 'file://'.str_replace('\\', '/', realpath($recipientCerts)); - } - - if (null !== $cipher) { - $this->encryptCipher = $cipher; - } - - return $this; - } - - /** - * @return string - */ - public function getSignCertificate() - { - return $this->signCertificate; - } - - /** - * @return string - */ - public function getSignPrivateKey() - { - return $this->signPrivateKey; - } - - /** - * Set perform signing before encryption. - * - * The default is to first sign the message and then encrypt. - * But some older mail clients, namely Microsoft Outlook 2000 will work when the message first encrypted. - * As this goes against the official specs, its recommended to only use 'encryption -> signing' when specifically targeting these 'broken' clients. - * - * @param bool $signThenEncrypt - * - * @return $this - */ - public function setSignThenEncrypt($signThenEncrypt = true) - { - $this->signThenEncrypt = $signThenEncrypt; - - return $this; - } - - /** - * @return bool - */ - public function isSignThenEncrypt() - { - return $this->signThenEncrypt; - } - - /** - * Resets internal states. - * - * @return $this - */ - public function reset() - { - return $this; - } - - /** - * Specify whether to wrap the entire MIME message in the S/MIME message. - * - * According to RFC5751 section 3.1: - * In order to protect outer, non-content-related message header fields - * (for instance, the "Subject", "To", "From", and "Cc" fields), the - * sending client MAY wrap a full MIME message in a message/rfc822 - * wrapper in order to apply S/MIME security services to these header - * fields. It is up to the receiving client to decide how to present - * this "inner" header along with the unprotected "outer" header. - * - * @param bool $wrap - * - * @return $this - */ - public function setWrapFullMessage($wrap) - { - $this->wrapFullMessage = $wrap; - } - - /** - * Change the Swift_Message to apply the signing. - * - * @return $this - */ - public function signMessage(Swift_Message $message) - { - if (null === $this->signCertificate && null === $this->encryptCert) { - return $this; - } - - if ($this->signThenEncrypt) { - $this->smimeSignMessage($message); - $this->smimeEncryptMessage($message); - } else { - $this->smimeEncryptMessage($message); - $this->smimeSignMessage($message); - } - } - - /** - * Return the list of header a signer might tamper. - * - * @return array - */ - public function getAlteredHeaders() - { - return ['Content-Type', 'Content-Transfer-Encoding', 'Content-Disposition']; - } - - /** - * Sign a Swift message. - */ - protected function smimeSignMessage(Swift_Message $message) - { - // If we don't have a certificate we can't sign the message - if (null === $this->signCertificate) { - return; - } - - // Work on a clone of the original message - $signMessage = clone $message; - $signMessage->clearSigners(); - - if ($this->wrapFullMessage) { - // The original message essentially becomes the body of the new - // wrapped message - $signMessage = $this->wrapMimeMessage($signMessage); - } else { - // Only keep header needed to parse the body correctly - $this->clearAllHeaders($signMessage); - $this->copyHeaders( - $message, - $signMessage, - [ - 'Content-Type', - 'Content-Transfer-Encoding', - 'Content-Disposition', - ] - ); - } - - // Copy the cloned message into a temporary file stream - $messageStream = new Swift_ByteStream_TemporaryFileByteStream(); - $signMessage->toByteStream($messageStream); - $messageStream->commit(); - $signedMessageStream = new Swift_ByteStream_TemporaryFileByteStream(); - - // Sign the message using openssl - if (!openssl_pkcs7_sign( - $messageStream->getPath(), - $signedMessageStream->getPath(), - $this->signCertificate, - $this->signPrivateKey, - [], - $this->signOptions, - $this->extraCerts - ) - ) { - throw new Swift_IoException(sprintf('Failed to sign S/Mime message. Error: "%s".', openssl_error_string())); - } - - // Parse the resulting signed message content back into the Swift message - // preserving the original headers - $this->parseSSLOutput($signedMessageStream, $message); - } - - /** - * Encrypt a Swift message. - */ - protected function smimeEncryptMessage(Swift_Message $message) - { - // If we don't have a certificate we can't encrypt the message - if (null === $this->encryptCert) { - return; - } - - // Work on a clone of the original message - $encryptMessage = clone $message; - $encryptMessage->clearSigners(); - - if ($this->wrapFullMessage) { - // The original message essentially becomes the body of the new - // wrapped message - $encryptMessage = $this->wrapMimeMessage($encryptMessage); - } else { - // Only keep header needed to parse the body correctly - $this->clearAllHeaders($encryptMessage); - $this->copyHeaders( - $message, - $encryptMessage, - [ - 'Content-Type', - 'Content-Transfer-Encoding', - 'Content-Disposition', - ] - ); - } - - // Convert the message content (including headers) to a string - // and place it in a temporary file - $messageStream = new Swift_ByteStream_TemporaryFileByteStream(); - $encryptMessage->toByteStream($messageStream); - $messageStream->commit(); - $encryptedMessageStream = new Swift_ByteStream_TemporaryFileByteStream(); - - // Encrypt the message - if (!openssl_pkcs7_encrypt( - $messageStream->getPath(), - $encryptedMessageStream->getPath(), - $this->encryptCert, - [], - 0, - $this->encryptCipher - ) - ) { - throw new Swift_IoException(sprintf('Failed to encrypt S/Mime message. Error: "%s".', openssl_error_string())); - } - - // Parse the resulting signed message content back into the Swift message - // preserving the original headers - $this->parseSSLOutput($encryptedMessageStream, $message); - } - - /** - * Copy named headers from one Swift message to another. - */ - protected function copyHeaders( - Swift_Message $fromMessage, - Swift_Message $toMessage, - array $headers = [] - ) { - foreach ($headers as $header) { - $this->copyHeader($fromMessage, $toMessage, $header); - } - } - - /** - * Copy a single header from one Swift message to another. - * - * @param string $headerName - */ - protected function copyHeader(Swift_Message $fromMessage, Swift_Message $toMessage, $headerName) - { - $header = $fromMessage->getHeaders()->get($headerName); - if (!$header) { - return; - } - $headers = $toMessage->getHeaders(); - switch ($header->getFieldType()) { - case Swift_Mime_Header::TYPE_TEXT: - $headers->addTextHeader($header->getFieldName(), $header->getValue()); - break; - case Swift_Mime_Header::TYPE_PARAMETERIZED: - $headers->addParameterizedHeader( - $header->getFieldName(), - $header->getValue(), - $header->getParameters() - ); - break; - } - } - - /** - * Remove all headers from a Swift message. - */ - protected function clearAllHeaders(Swift_Message $message) - { - $headers = $message->getHeaders(); - foreach ($headers->listAll() as $header) { - $headers->removeAll($header); - } - } - - /** - * Wraps a Swift_Message in a message/rfc822 MIME part. - * - * @return Swift_MimePart - */ - protected function wrapMimeMessage(Swift_Message $message) - { - // Start by copying the original message into a message stream - $messageStream = new Swift_ByteStream_TemporaryFileByteStream(); - $message->toByteStream($messageStream); - $messageStream->commit(); - - // Create a new MIME part that wraps the original stream - $wrappedMessage = new Swift_MimePart($messageStream, 'message/rfc822'); - $wrappedMessage->setEncoder(new Swift_Mime_ContentEncoder_PlainContentEncoder('7bit')); - - return $wrappedMessage; - } - - protected function parseSSLOutput(Swift_InputByteStream $inputStream, Swift_Message $message) - { - $messageStream = new Swift_ByteStream_TemporaryFileByteStream(); - $this->copyFromOpenSSLOutput($inputStream, $messageStream); - - $this->streamToMime($messageStream, $message); - } - - /** - * Merges an OutputByteStream from OpenSSL to a Swift_Message. - */ - protected function streamToMime(Swift_OutputByteStream $fromStream, Swift_Message $message) - { - // Parse the stream into headers and body - list($headers, $messageStream) = $this->parseStream($fromStream); - - // Get the original message headers - $messageHeaders = $message->getHeaders(); - - // Let the stream determine the headers describing the body content, - // since the body of the original message is overwritten by the body - // coming from the stream. - // These are all content-* headers. - - // Default transfer encoding is 7bit if not set - $encoding = ''; - // Remove all existing transfer encoding headers - $messageHeaders->removeAll('Content-Transfer-Encoding'); - // See whether the stream sets the transfer encoding - if (isset($headers['content-transfer-encoding'])) { - $encoding = $headers['content-transfer-encoding']; - } - - // We use the null content encoder, since the body is already encoded - // according to the transfer encoding specified in the stream - $message->setEncoder(new Swift_Mime_ContentEncoder_NullContentEncoder($encoding)); - - // Set the disposition, if present - if (isset($headers['content-disposition'])) { - $messageHeaders->addTextHeader('Content-Disposition', $headers['content-disposition']); - } - - // Copy over the body from the stream using the content type dictated - // by the stream content - $message->setChildren([]); - $message->setBody($messageStream, $headers['content-type']); - } - - /** - * This message will parse the headers of a MIME email byte stream - * and return an array that contains the headers as an associative - * array and the email body as a string. - * - * @return array - */ - protected function parseStream(Swift_OutputByteStream $emailStream) - { - $bufferLength = 78; - $headerData = ''; - $headerBodySeparator = "\r\n\r\n"; - - $emailStream->setReadPointer(0); - - // Read out the headers section from the stream to a string - while (false !== ($buffer = $emailStream->read($bufferLength))) { - $headerData .= $buffer; - - $headersPosEnd = strpos($headerData, $headerBodySeparator); - - // Stop reading if we found the end of the headers - if (false !== $headersPosEnd) { - break; - } - } - - // Split the header data into lines - $headerData = trim(substr($headerData, 0, $headersPosEnd)); - $headerLines = explode("\r\n", $headerData); - unset($headerData); - - $headers = []; - $currentHeaderName = ''; - - // Transform header lines into an associative array - foreach ($headerLines as $headerLine) { - // Handle headers that span multiple lines - if (false === strpos($headerLine, ':')) { - $headers[$currentHeaderName] .= ' '.trim($headerLine ?? ''); - continue; - } - - $header = explode(':', $headerLine, 2); - $currentHeaderName = strtolower($header[0] ?? ''); - $headers[$currentHeaderName] = trim($header[1] ?? ''); - } - - // Read the entire email body into a byte stream - $bodyStream = new Swift_ByteStream_TemporaryFileByteStream(); - - // Skip the header and separator and point to the body - $emailStream->setReadPointer($headersPosEnd + \strlen($headerBodySeparator)); - - while (false !== ($buffer = $emailStream->read($bufferLength))) { - $bodyStream->write($buffer); - } - - $bodyStream->commit(); - - return [$headers, $bodyStream]; - } - - protected function copyFromOpenSSLOutput(Swift_OutputByteStream $fromStream, Swift_InputByteStream $toStream) - { - $bufferLength = 4096; - $filteredStream = new Swift_ByteStream_TemporaryFileByteStream(); - $filteredStream->addFilter($this->replacementFactory->createFilter("\r\n", "\n"), 'CRLF to LF'); - $filteredStream->addFilter($this->replacementFactory->createFilter("\n", "\r\n"), 'LF to CRLF'); - - while (false !== ($buffer = $fromStream->read($bufferLength))) { - $filteredStream->write($buffer); - } - - $filteredStream->flushBuffers(); - - while (false !== ($buffer = $filteredStream->read($bufferLength))) { - $toStream->write($buffer); - } - - $toStream->commit(); - } + protected $signCertificate; + protected $signPrivateKey; + protected $encryptCert; + protected $signThenEncrypt = true; + protected $signLevel; + protected $encryptLevel; + protected $signOptions; + protected $encryptOptions; + protected $encryptCipher; + protected $extraCerts = null; + protected $wrapFullMessage = false; + + /** + * @var Swift_StreamFilters_StringReplacementFilterFactory + */ + protected $replacementFactory; + + /** + * @var Swift_Mime_SimpleHeaderFactory + */ + protected $headerFactory; + + /** + * Constructor. + * + * @param string|null $signCertificate + * @param string|null $signPrivateKey + * @param string|null $encryptCertificate + */ + public function __construct($signCertificate = null, $signPrivateKey = null, $encryptCertificate = null) + { + if (null !== $signPrivateKey) { + $this->setSignCertificate($signCertificate, $signPrivateKey); + } + + if (null !== $encryptCertificate) { + $this->setEncryptCertificate($encryptCertificate); + } + + $this->replacementFactory = Swift_DependencyContainer::getInstance() + ->lookup('transport.replacementfactory'); + + $this->signOptions = PKCS7_DETACHED; + $this->encryptCipher = OPENSSL_CIPHER_AES_128_CBC; + } + + /** + * Set the certificate location to use for signing. + * + * @see https://secure.php.net/manual/en/openssl.pkcs7.flags.php + * + * @param string $certificate + * @param string|array $privateKey If the key needs an passphrase use array('file-location', 'passphrase') instead + * @param int $signOptions Bitwise operator options for openssl_pkcs7_sign() + * @param string $extraCerts A file containing intermediate certificates needed by the signing certificate + * + * @return $this + */ + public function setSignCertificate($certificate, $privateKey = null, $signOptions = PKCS7_DETACHED, $extraCerts = null) + { + $this->signCertificate = 'file://'.str_replace('\\', '/', realpath($certificate)); + + if (null !== $privateKey) { + if (\is_array($privateKey)) { + $this->signPrivateKey = $privateKey; + $this->signPrivateKey[0] = 'file://'.str_replace('\\', '/', realpath($privateKey[0])); + } else { + $this->signPrivateKey = 'file://'.str_replace('\\', '/', realpath($privateKey)); + } + } + + $this->signOptions = $signOptions; + $this->extraCerts = $extraCerts ? realpath($extraCerts) : null; + + return $this; + } + + /** + * Set the certificate location to use for encryption. + * + * @see https://secure.php.net/manual/en/openssl.pkcs7.flags.php + * @see https://secure.php.net/manual/en/openssl.ciphers.php + * + * @param string|array $recipientCerts Either an single X.509 certificate, or an assoc array of X.509 certificates. + * @param int $cipher + * + * @return $this + */ + public function setEncryptCertificate($recipientCerts, $cipher = null) + { + if (\is_array($recipientCerts)) { + $this->encryptCert = []; + + foreach ($recipientCerts as $cert) { + $this->encryptCert[] = 'file://'.str_replace('\\', '/', realpath($cert)); + } + } else { + $this->encryptCert = 'file://'.str_replace('\\', '/', realpath($recipientCerts)); + } + + if (null !== $cipher) { + $this->encryptCipher = $cipher; + } + + return $this; + } + + /** + * @return string + */ + public function getSignCertificate() + { + return $this->signCertificate; + } + + /** + * @return string + */ + public function getSignPrivateKey() + { + return $this->signPrivateKey; + } + + /** + * Set perform signing before encryption. + * + * The default is to first sign the message and then encrypt. + * But some older mail clients, namely Microsoft Outlook 2000 will work when the message first encrypted. + * As this goes against the official specs, its recommended to only use 'encryption -> signing' when specifically targeting these 'broken' clients. + * + * @param bool $signThenEncrypt + * + * @return $this + */ + public function setSignThenEncrypt($signThenEncrypt = true) + { + $this->signThenEncrypt = $signThenEncrypt; + + return $this; + } + + /** + * @return bool + */ + public function isSignThenEncrypt() + { + return $this->signThenEncrypt; + } + + /** + * Resets internal states. + * + * @return $this + */ + public function reset() + { + return $this; + } + + /** + * Specify whether to wrap the entire MIME message in the S/MIME message. + * + * According to RFC5751 section 3.1: + * In order to protect outer, non-content-related message header fields + * (for instance, the "Subject", "To", "From", and "Cc" fields), the + * sending client MAY wrap a full MIME message in a message/rfc822 + * wrapper in order to apply S/MIME security services to these header + * fields. It is up to the receiving client to decide how to present + * this "inner" header along with the unprotected "outer" header. + * + * @param bool $wrap + * + * @return $this + */ + public function setWrapFullMessage($wrap) + { + $this->wrapFullMessage = $wrap; + } + + /** + * Change the Swift_Message to apply the signing. + * + * @return $this + */ + public function signMessage(Swift_Message $message) + { + if (null === $this->signCertificate && null === $this->encryptCert) { + return $this; + } + + if ($this->signThenEncrypt) { + $this->smimeSignMessage($message); + $this->smimeEncryptMessage($message); + } else { + $this->smimeEncryptMessage($message); + $this->smimeSignMessage($message); + } + } + + /** + * Return the list of header a signer might tamper. + * + * @return array + */ + public function getAlteredHeaders() + { + return ['Content-Type', 'Content-Transfer-Encoding', 'Content-Disposition']; + } + + /** + * Sign a Swift message. + */ + protected function smimeSignMessage(Swift_Message $message) + { + // If we don't have a certificate we can't sign the message + if (null === $this->signCertificate) { + return; + } + + // Work on a clone of the original message + $signMessage = clone $message; + $signMessage->clearSigners(); + + if ($this->wrapFullMessage) { + // The original message essentially becomes the body of the new + // wrapped message + $signMessage = $this->wrapMimeMessage($signMessage); + } else { + // Only keep header needed to parse the body correctly + $this->clearAllHeaders($signMessage); + $this->copyHeaders( + $message, + $signMessage, + [ + 'Content-Type', + 'Content-Transfer-Encoding', + 'Content-Disposition', + ] + ); + } + + // Copy the cloned message into a temporary file stream + $messageStream = new Swift_ByteStream_TemporaryFileByteStream(); + $signMessage->toByteStream($messageStream); + $messageStream->commit(); + $signedMessageStream = new Swift_ByteStream_TemporaryFileByteStream(); + + // Sign the message using openssl + if (!openssl_pkcs7_sign( + $messageStream->getPath(), + $signedMessageStream->getPath(), + $this->signCertificate, + $this->signPrivateKey, + [], + $this->signOptions, + $this->extraCerts + ) + ) { + throw new Swift_IoException(sprintf('Failed to sign S/Mime message. Error: "%s".', openssl_error_string())); + } + + // Parse the resulting signed message content back into the Swift message + // preserving the original headers + $this->parseSSLOutput($signedMessageStream, $message); + } + + /** + * Encrypt a Swift message. + */ + protected function smimeEncryptMessage(Swift_Message $message) + { + // If we don't have a certificate we can't encrypt the message + if (null === $this->encryptCert) { + return; + } + + // Work on a clone of the original message + $encryptMessage = clone $message; + $encryptMessage->clearSigners(); + + if ($this->wrapFullMessage) { + // The original message essentially becomes the body of the new + // wrapped message + $encryptMessage = $this->wrapMimeMessage($encryptMessage); + } else { + // Only keep header needed to parse the body correctly + $this->clearAllHeaders($encryptMessage); + $this->copyHeaders( + $message, + $encryptMessage, + [ + 'Content-Type', + 'Content-Transfer-Encoding', + 'Content-Disposition', + ] + ); + } + + // Convert the message content (including headers) to a string + // and place it in a temporary file + $messageStream = new Swift_ByteStream_TemporaryFileByteStream(); + $encryptMessage->toByteStream($messageStream); + $messageStream->commit(); + $encryptedMessageStream = new Swift_ByteStream_TemporaryFileByteStream(); + + // Encrypt the message + if (!openssl_pkcs7_encrypt( + $messageStream->getPath(), + $encryptedMessageStream->getPath(), + $this->encryptCert, + [], + 0, + $this->encryptCipher + ) + ) { + throw new Swift_IoException(sprintf('Failed to encrypt S/Mime message. Error: "%s".', openssl_error_string())); + } + + // Parse the resulting signed message content back into the Swift message + // preserving the original headers + $this->parseSSLOutput($encryptedMessageStream, $message); + } + + /** + * Copy named headers from one Swift message to another. + */ + protected function copyHeaders( + Swift_Message $fromMessage, + Swift_Message $toMessage, + array $headers = [] + ) { + foreach ($headers as $header) { + $this->copyHeader($fromMessage, $toMessage, $header); + } + } + + /** + * Copy a single header from one Swift message to another. + * + * @param string $headerName + */ + protected function copyHeader(Swift_Message $fromMessage, Swift_Message $toMessage, $headerName) + { + $header = $fromMessage->getHeaders()->get($headerName); + if (!$header) { + return; + } + $headers = $toMessage->getHeaders(); + switch ($header->getFieldType()) { + case Swift_Mime_Header::TYPE_TEXT: + $headers->addTextHeader($header->getFieldName(), $header->getValue()); + break; + case Swift_Mime_Header::TYPE_PARAMETERIZED: + $headers->addParameterizedHeader( + $header->getFieldName(), + $header->getValue(), + $header->getParameters() + ); + break; + } + } + + /** + * Remove all headers from a Swift message. + */ + protected function clearAllHeaders(Swift_Message $message) + { + $headers = $message->getHeaders(); + foreach ($headers->listAll() as $header) { + $headers->removeAll($header); + } + } + + /** + * Wraps a Swift_Message in a message/rfc822 MIME part. + * + * @return Swift_MimePart + */ + protected function wrapMimeMessage(Swift_Message $message) + { + // Start by copying the original message into a message stream + $messageStream = new Swift_ByteStream_TemporaryFileByteStream(); + $message->toByteStream($messageStream); + $messageStream->commit(); + + // Create a new MIME part that wraps the original stream + $wrappedMessage = new Swift_MimePart($messageStream, 'message/rfc822'); + $wrappedMessage->setEncoder(new Swift_Mime_ContentEncoder_PlainContentEncoder('7bit')); + + return $wrappedMessage; + } + + protected function parseSSLOutput(Swift_InputByteStream $inputStream, Swift_Message $message) + { + $messageStream = new Swift_ByteStream_TemporaryFileByteStream(); + $this->copyFromOpenSSLOutput($inputStream, $messageStream); + + $this->streamToMime($messageStream, $message); + } + + /** + * Merges an OutputByteStream from OpenSSL to a Swift_Message. + */ + protected function streamToMime(Swift_OutputByteStream $fromStream, Swift_Message $message) + { + // Parse the stream into headers and body + list($headers, $messageStream) = $this->parseStream($fromStream); + + // Get the original message headers + $messageHeaders = $message->getHeaders(); + + // Let the stream determine the headers describing the body content, + // since the body of the original message is overwritten by the body + // coming from the stream. + // These are all content-* headers. + + // Default transfer encoding is 7bit if not set + $encoding = ''; + // Remove all existing transfer encoding headers + $messageHeaders->removeAll('Content-Transfer-Encoding'); + // See whether the stream sets the transfer encoding + if (isset($headers['content-transfer-encoding'])) { + $encoding = $headers['content-transfer-encoding']; + } + + // We use the null content encoder, since the body is already encoded + // according to the transfer encoding specified in the stream + $message->setEncoder(new Swift_Mime_ContentEncoder_NullContentEncoder($encoding)); + + // Set the disposition, if present + if (isset($headers['content-disposition'])) { + $messageHeaders->addTextHeader('Content-Disposition', $headers['content-disposition']); + } + + // Copy over the body from the stream using the content type dictated + // by the stream content + $message->setChildren([]); + $message->setBody($messageStream, $headers['content-type']); + } + + /** + * This message will parse the headers of a MIME email byte stream + * and return an array that contains the headers as an associative + * array and the email body as a string. + * + * @return array + */ + protected function parseStream(Swift_OutputByteStream $emailStream) + { + $bufferLength = 78; + $headerData = ''; + $headerBodySeparator = "\r\n\r\n"; + + $emailStream->setReadPointer(0); + + // Read out the headers section from the stream to a string + while (false !== ($buffer = $emailStream->read($bufferLength))) { + $headerData .= $buffer; + + $headersPosEnd = strpos($headerData, $headerBodySeparator); + + // Stop reading if we found the end of the headers + if (false !== $headersPosEnd) { + break; + } + } + + // Split the header data into lines + $headerData = trim(substr($headerData, 0, $headersPosEnd)); + $headerLines = explode("\r\n", $headerData); + unset($headerData); + + $headers = []; + $currentHeaderName = ''; + + // Transform header lines into an associative array + foreach ($headerLines as $headerLine) { + // Handle headers that span multiple lines + if (false === strpos($headerLine, ':')) { + $headers[$currentHeaderName] .= ' '.trim($headerLine ?? ''); + continue; + } + + $header = explode(':', $headerLine, 2); + $currentHeaderName = strtolower($header[0] ?? ''); + $headers[$currentHeaderName] = trim($header[1] ?? ''); + } + + // Read the entire email body into a byte stream + $bodyStream = new Swift_ByteStream_TemporaryFileByteStream(); + + // Skip the header and separator and point to the body + $emailStream->setReadPointer($headersPosEnd + \strlen($headerBodySeparator)); + + while (false !== ($buffer = $emailStream->read($bufferLength))) { + $bodyStream->write($buffer); + } + + $bodyStream->commit(); + + return [$headers, $bodyStream]; + } + + protected function copyFromOpenSSLOutput(Swift_OutputByteStream $fromStream, Swift_InputByteStream $toStream) + { + $bufferLength = 4096; + $filteredStream = new Swift_ByteStream_TemporaryFileByteStream(); + $filteredStream->addFilter($this->replacementFactory->createFilter("\r\n", "\n"), 'CRLF to LF'); + $filteredStream->addFilter($this->replacementFactory->createFilter("\n", "\r\n"), 'LF to CRLF'); + + while (false !== ($buffer = $fromStream->read($bufferLength))) { + $filteredStream->write($buffer); + } + + $filteredStream->flushBuffers(); + + while (false !== ($buffer = $filteredStream->read($bufferLength))) { + $toStream->write($buffer); + } + + $toStream->commit(); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/SmtpTransport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/SmtpTransport.php index 56b62323ad7..625a470e09c 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/SmtpTransport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/SmtpTransport.php @@ -22,24 +22,24 @@ */ class Swift_SmtpTransport extends Swift_Transport_EsmtpTransport { - /** - * @param string $host - * @param int $port - * @param string|null $encryption SMTP encryption mode: - * - null for plain SMTP (no encryption), - * - 'tls' for SMTP with STARTTLS (best effort encryption), - * - 'ssl' for SMTPS = SMTP over TLS (always encrypted). - */ - public function __construct($host = 'localhost', $port = 25, $encryption = null) - { - \call_user_func_array( - [$this, 'Swift_Transport_EsmtpTransport::__construct'], - Swift_DependencyContainer::getInstance() - ->createDependenciesFor('transport.smtp') - ); + /** + * @param string $host + * @param int $port + * @param string|null $encryption SMTP encryption mode: + * - null for plain SMTP (no encryption), + * - 'tls' for SMTP with STARTTLS (best effort encryption), + * - 'ssl' for SMTPS = SMTP over TLS (always encrypted). + */ + public function __construct($host = 'localhost', $port = 25, $encryption = null) + { + \call_user_func_array( + [$this, 'Swift_Transport_EsmtpTransport::__construct'], + Swift_DependencyContainer::getInstance() + ->createDependenciesFor('transport.smtp') + ); - $this->setHost($host); - $this->setPort($port); - $this->setEncryption($encryption); - } + $this->setHost($host); + $this->setPort($port); + $this->setEncryption($encryption); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/SpoolTransport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/SpoolTransport.php index c08e0fb17d5..ac30065048a 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/SpoolTransport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/SpoolTransport.php @@ -15,19 +15,19 @@ */ class Swift_SpoolTransport extends Swift_Transport_SpoolTransport { - /** - * Create a new SpoolTransport. - */ - public function __construct(Swift_Spool $spool) - { - $arguments = Swift_DependencyContainer::getInstance() - ->createDependenciesFor('transport.spool'); + /** + * Create a new SpoolTransport. + */ + public function __construct(Swift_Spool $spool) + { + $arguments = Swift_DependencyContainer::getInstance() + ->createDependenciesFor('transport.spool'); - $arguments[] = $spool; + $arguments[] = $spool; - \call_user_func_array( - [$this, 'Swift_Transport_SpoolTransport::__construct'], - $arguments - ); - } + \call_user_func_array( + [$this, 'Swift_Transport_SpoolTransport::__construct'], + $arguments + ); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/StreamFilters/ByteArrayReplacementFilter.php b/htdocs/includes/swiftmailer/lib/classes/Swift/StreamFilters/ByteArrayReplacementFilter.php index 7e5ddf1b7da..2e68f95e3e7 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/StreamFilters/ByteArrayReplacementFilter.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/StreamFilters/ByteArrayReplacementFilter.php @@ -17,150 +17,150 @@ */ class Swift_StreamFilters_ByteArrayReplacementFilter implements Swift_StreamFilter { - /** The replacement(s) to make */ - private $replace; + /** The replacement(s) to make */ + private $replace; - /** The Index for searching */ - private $index; + /** The Index for searching */ + private $index; - /** The Search Tree */ - private $tree = []; + /** The Search Tree */ + private $tree = []; - /** Gives the size of the largest search */ - private $treeMaxLen = 0; + /** Gives the size of the largest search */ + private $treeMaxLen = 0; - private $repSize; + private $repSize; - /** - * Create a new ByteArrayReplacementFilter with $search and $replace. - * - * @param array $search - * @param array $replace - */ - public function __construct($search, $replace) - { - $this->index = []; - $this->tree = []; - $this->replace = []; - $this->repSize = []; + /** + * Create a new ByteArrayReplacementFilter with $search and $replace. + * + * @param array $search + * @param array $replace + */ + public function __construct($search, $replace) + { + $this->index = []; + $this->tree = []; + $this->replace = []; + $this->repSize = []; - $tree = null; - $i = null; - $last_size = $size = 0; - foreach ($search as $i => $search_element) { - if (null !== $tree) { - $tree[-1] = min(\count($replace) - 1, $i - 1); - $tree[-2] = $last_size; - } - $tree = &$this->tree; - if (\is_array($search_element)) { - foreach ($search_element as $k => $char) { - $this->index[$char] = true; - if (!isset($tree[$char])) { - $tree[$char] = []; - } - $tree = &$tree[$char]; - } - $last_size = $k + 1; - $size = max($size, $last_size); - } else { - $last_size = 1; - if (!isset($tree[$search_element])) { - $tree[$search_element] = []; - } - $tree = &$tree[$search_element]; - $size = max($last_size, $size); - $this->index[$search_element] = true; - } - } - if (null !== $i) { - $tree[-1] = min(\count($replace) - 1, $i); - $tree[-2] = $last_size; - $this->treeMaxLen = $size; - } - foreach ($replace as $rep) { - if (!\is_array($rep)) { - $rep = [$rep]; - } - $this->replace[] = $rep; - } - for ($i = \count($this->replace) - 1; $i >= 0; --$i) { - $this->replace[$i] = $rep = $this->filter($this->replace[$i], $i); - $this->repSize[$i] = \count($rep); - } - } + $tree = null; + $i = null; + $last_size = $size = 0; + foreach ($search as $i => $search_element) { + if (null !== $tree) { + $tree[-1] = min(\count($replace) - 1, $i - 1); + $tree[-2] = $last_size; + } + $tree = &$this->tree; + if (\is_array($search_element)) { + foreach ($search_element as $k => $char) { + $this->index[$char] = true; + if (!isset($tree[$char])) { + $tree[$char] = []; + } + $tree = &$tree[$char]; + } + $last_size = $k + 1; + $size = max($size, $last_size); + } else { + $last_size = 1; + if (!isset($tree[$search_element])) { + $tree[$search_element] = []; + } + $tree = &$tree[$search_element]; + $size = max($last_size, $size); + $this->index[$search_element] = true; + } + } + if (null !== $i) { + $tree[-1] = min(\count($replace) - 1, $i); + $tree[-2] = $last_size; + $this->treeMaxLen = $size; + } + foreach ($replace as $rep) { + if (!\is_array($rep)) { + $rep = [$rep]; + } + $this->replace[] = $rep; + } + for ($i = \count($this->replace) - 1; $i >= 0; --$i) { + $this->replace[$i] = $rep = $this->filter($this->replace[$i], $i); + $this->repSize[$i] = \count($rep); + } + } - /** - * Returns true if based on the buffer passed more bytes should be buffered. - * - * @param array $buffer - * - * @return bool - */ - public function shouldBuffer($buffer) - { - $endOfBuffer = end($buffer); + /** + * Returns true if based on the buffer passed more bytes should be buffered. + * + * @param array $buffer + * + * @return bool + */ + public function shouldBuffer($buffer) + { + $endOfBuffer = end($buffer); - return isset($this->index[$endOfBuffer]); - } + return isset($this->index[$endOfBuffer]); + } - /** - * Perform the actual replacements on $buffer and return the result. - * - * @param array $buffer - * @param int $minReplaces - * - * @return array - */ - public function filter($buffer, $minReplaces = -1) - { - if (0 == $this->treeMaxLen) { - return $buffer; - } + /** + * Perform the actual replacements on $buffer and return the result. + * + * @param array $buffer + * @param int $minReplaces + * + * @return array + */ + public function filter($buffer, $minReplaces = -1) + { + if (0 == $this->treeMaxLen) { + return $buffer; + } - $newBuffer = []; - $buf_size = \count($buffer); - $last_size = 0; - for ($i = 0; $i < $buf_size; ++$i) { - $search_pos = $this->tree; - $last_found = PHP_INT_MAX; - // We try to find if the next byte is part of a search pattern - for ($j = 0; $j <= $this->treeMaxLen; ++$j) { - // We have a new byte for a search pattern - if (isset($buffer[$p = $i + $j]) && isset($search_pos[$buffer[$p]])) { - $search_pos = $search_pos[$buffer[$p]]; - // We have a complete pattern, save, in case we don't find a better match later - if (isset($search_pos[-1]) && $search_pos[-1] < $last_found - && $search_pos[-1] > $minReplaces) { - $last_found = $search_pos[-1]; - $last_size = $search_pos[-2]; - } - } - // We got a complete pattern - elseif (PHP_INT_MAX !== $last_found) { - // Adding replacement datas to output buffer - $rep_size = $this->repSize[$last_found]; - for ($j = 0; $j < $rep_size; ++$j) { - $newBuffer[] = $this->replace[$last_found][$j]; - } - // We Move cursor forward - $i += $last_size - 1; - // Edge Case, last position in buffer - if ($i >= $buf_size) { - $newBuffer[] = $buffer[$i]; - } + $newBuffer = []; + $buf_size = \count($buffer); + $last_size = 0; + for ($i = 0; $i < $buf_size; ++$i) { + $search_pos = $this->tree; + $last_found = PHP_INT_MAX; + // We try to find if the next byte is part of a search pattern + for ($j = 0; $j <= $this->treeMaxLen; ++$j) { + // We have a new byte for a search pattern + if (isset($buffer[$p = $i + $j]) && isset($search_pos[$buffer[$p]])) { + $search_pos = $search_pos[$buffer[$p]]; + // We have a complete pattern, save, in case we don't find a better match later + if (isset($search_pos[-1]) && $search_pos[-1] < $last_found + && $search_pos[-1] > $minReplaces) { + $last_found = $search_pos[-1]; + $last_size = $search_pos[-2]; + } + } + // We got a complete pattern + elseif (PHP_INT_MAX !== $last_found) { + // Adding replacement datas to output buffer + $rep_size = $this->repSize[$last_found]; + for ($j = 0; $j < $rep_size; ++$j) { + $newBuffer[] = $this->replace[$last_found][$j]; + } + // We Move cursor forward + $i += $last_size - 1; + // Edge Case, last position in buffer + if ($i >= $buf_size) { + $newBuffer[] = $buffer[$i]; + } - // We start the next loop - continue 2; - } else { - // this byte is not in a pattern and we haven't found another pattern - break; - } - } - // Normal byte, move it to output buffer - $newBuffer[] = $buffer[$i]; - } + // We start the next loop + continue 2; + } else { + // this byte is not in a pattern and we haven't found another pattern + break; + } + } + // Normal byte, move it to output buffer + $newBuffer[] = $buffer[$i]; + } - return $newBuffer; - } + return $newBuffer; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/StreamFilters/StringReplacementFilterFactory.php b/htdocs/includes/swiftmailer/lib/classes/Swift/StreamFilters/StringReplacementFilterFactory.php index 783b8896dd7..965e9f69cda 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/StreamFilters/StringReplacementFilterFactory.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/StreamFilters/StringReplacementFilterFactory.php @@ -15,31 +15,31 @@ */ class Swift_StreamFilters_StringReplacementFilterFactory implements Swift_ReplacementFilterFactory { - /** Lazy-loaded filters */ - private $filters = []; + /** Lazy-loaded filters */ + private $filters = []; - /** - * Create a new StreamFilter to replace $search with $replace in a string. - * - * @param string $search - * @param string $replace - * - * @return Swift_StreamFilter - */ - public function createFilter($search, $replace) - { - if (!isset($this->filters[$search][$replace])) { - if (!isset($this->filters[$search])) { - $this->filters[$search] = []; - } + /** + * Create a new StreamFilter to replace $search with $replace in a string. + * + * @param string $search + * @param string $replace + * + * @return Swift_StreamFilter + */ + public function createFilter($search, $replace) + { + if (!isset($this->filters[$search][$replace])) { + if (!isset($this->filters[$search])) { + $this->filters[$search] = []; + } - if (!isset($this->filters[$search][$replace])) { - $this->filters[$search][$replace] = []; - } + if (!isset($this->filters[$search][$replace])) { + $this->filters[$search][$replace] = []; + } - $this->filters[$search][$replace] = new Swift_StreamFilters_StringReplacementFilter($search, $replace); - } + $this->filters[$search][$replace] = new Swift_StreamFilters_StringReplacementFilter($search, $replace); + } - return $this->filters[$search][$replace]; - } + return $this->filters[$search][$replace]; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/SwiftException.php b/htdocs/includes/swiftmailer/lib/classes/Swift/SwiftException.php index 15e68b18e79..44cbfc779e5 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/SwiftException.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/SwiftException.php @@ -15,14 +15,14 @@ */ class Swift_SwiftException extends Exception { - /** - * Create a new SwiftException with $message. - * - * @param string $message - * @param int $code - */ - public function __construct($message, $code = 0, Exception $previous = null) - { - parent::__construct($message, $code, $previous); - } + /** + * Create a new SwiftException with $message. + * + * @param string $message + * @param int $code + */ + public function __construct($message, $code = 0, Exception $previous = null) + { + parent::__construct($message, $code, $previous); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport.php index bc324e8685a..f3d4c4fe31e 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport.php @@ -15,62 +15,62 @@ */ interface Swift_Transport { - /** - * Test if this Transport mechanism has started. - * - * @return bool - */ - public function isStarted(); + /** + * Test if this Transport mechanism has started. + * + * @return bool + */ + public function isStarted(); - /** - * Start this Transport mechanism. - */ - public function start(); + /** + * Start this Transport mechanism. + */ + public function start(); - /** - * Stop this Transport mechanism. - */ - public function stop(); + /** + * Stop this Transport mechanism. + */ + public function stop(); - /** - * Check if this Transport mechanism is alive. - * - * If a Transport mechanism session is no longer functional, the method - * returns FALSE. It is the responsibility of the developer to handle this - * case and restart the Transport mechanism manually. - * - * @example - * - * if (!$transport->ping()) { - * $transport->stop(); - * $transport->start(); - * } - * - * The Transport mechanism will be started, if it is not already. - * - * It is undefined if the Transport mechanism attempts to restart as long as - * the return value reflects whether the mechanism is now functional. - * - * @return bool TRUE if the transport is alive - */ - public function ping(); + /** + * Check if this Transport mechanism is alive. + * + * If a Transport mechanism session is no longer functional, the method + * returns FALSE. It is the responsibility of the developer to handle this + * case and restart the Transport mechanism manually. + * + * @example + * + * if (!$transport->ping()) { + * $transport->stop(); + * $transport->start(); + * } + * + * The Transport mechanism will be started, if it is not already. + * + * It is undefined if the Transport mechanism attempts to restart as long as + * the return value reflects whether the mechanism is now functional. + * + * @return bool TRUE if the transport is alive + */ + public function ping(); - /** - * Send the given Message. - * - * Recipient/sender data will be retrieved from the Message API. - * The return value is the number of recipients who were accepted for delivery. - * - * This is the responsibility of the send method to start the transport if needed. - * - * @param string[] $failedRecipients An array of failures by-reference - * - * @return int - */ - public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null); + /** + * Send the given Message. + * + * Recipient/sender data will be retrieved from the Message API. + * The return value is the number of recipients who were accepted for delivery. + * + * This is the responsibility of the send method to start the transport if needed. + * + * @param string[] $failedRecipients An array of failures by-reference + * + * @return int + */ + public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null); - /** - * Register a plugin in the Transport. - */ - public function registerPlugin(Swift_Events_EventListener $plugin); + /** + * Register a plugin in the Transport. + */ + public function registerPlugin(Swift_Events_EventListener $plugin); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/AbstractSmtpTransport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/AbstractSmtpTransport.php index d2dbd7a66a0..d761677db7e 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/AbstractSmtpTransport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/AbstractSmtpTransport.php @@ -15,527 +15,527 @@ */ abstract class Swift_Transport_AbstractSmtpTransport implements Swift_Transport { - /** Input-Output buffer for sending/receiving SMTP commands and responses */ - protected $buffer; - - /** Connection status */ - protected $started = false; - - /** The domain name to use in HELO command */ - protected $domain = '[127.0.0.1]'; - - /** The event dispatching layer */ - protected $eventDispatcher; - - protected $addressEncoder; - - /** Whether the PIPELINING SMTP extension is enabled (RFC 2920) */ - protected $pipelining = null; - - /** The pipelined commands waiting for response */ - protected $pipeline = []; - - /** Source Ip */ - protected $sourceIp; - - /** Return an array of params for the Buffer */ - abstract protected function getBufferParams(); - - /** - * Creates a new EsmtpTransport using the given I/O buffer. - * - * @param string $localDomain - */ - public function __construct(Swift_Transport_IoBuffer $buf, Swift_Events_EventDispatcher $dispatcher, $localDomain = '127.0.0.1', Swift_AddressEncoder $addressEncoder = null) - { - $this->buffer = $buf; - $this->eventDispatcher = $dispatcher; - $this->addressEncoder = $addressEncoder ?? new Swift_AddressEncoder_IdnAddressEncoder(); - $this->setLocalDomain($localDomain); - } - - /** - * Set the name of the local domain which Swift will identify itself as. - * - * This should be a fully-qualified domain name and should be truly the domain - * you're using. - * - * If your server does not have a domain name, use the IP address. This will - * automatically be wrapped in square brackets as described in RFC 5321, - * section 4.1.3. - * - * @param string $domain - * - * @return $this - */ - public function setLocalDomain($domain) - { - if ('[' !== substr($domain, 0, 1)) { - if (filter_var($domain, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { - $domain = '['.$domain.']'; - } elseif (filter_var($domain, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { - $domain = '[IPv6:'.$domain.']'; - } - } - - $this->domain = $domain; - - return $this; - } - - /** - * Get the name of the domain Swift will identify as. - * - * If an IP address was specified, this will be returned wrapped in square - * brackets as described in RFC 5321, section 4.1.3. - * - * @return string - */ - public function getLocalDomain() - { - return $this->domain; - } - - /** - * Sets the source IP. - * - * @param string $source - */ - public function setSourceIp($source) - { - $this->sourceIp = $source; - } - - /** - * Returns the IP used to connect to the destination. - * - * @return string - */ - public function getSourceIp() - { - return $this->sourceIp; - } - - public function setAddressEncoder(Swift_AddressEncoder $addressEncoder) - { - $this->addressEncoder = $addressEncoder; - } - - public function getAddressEncoder() - { - return $this->addressEncoder; - } - - /** - * Start the SMTP connection. - */ - public function start() - { - if (!$this->started) { - if ($evt = $this->eventDispatcher->createTransportChangeEvent($this)) { - $this->eventDispatcher->dispatchEvent($evt, 'beforeTransportStarted'); - if ($evt->bubbleCancelled()) { - return; - } - } - - try { - $this->buffer->initialize($this->getBufferParams()); - } catch (Swift_TransportException $e) { - $this->throwException($e); - } - $this->readGreeting(); - $this->doHeloCommand(); - - if ($evt) { - $this->eventDispatcher->dispatchEvent($evt, 'transportStarted'); - } - - $this->started = true; - } - } - - /** - * Test if an SMTP connection has been established. - * - * @return bool - */ - public function isStarted() - { - return $this->started; - } - - /** - * Send the given Message. - * - * Recipient/sender data will be retrieved from the Message API. - * The return value is the number of recipients who were accepted for delivery. - * - * @param string[] $failedRecipients An array of failures by-reference - * - * @return int - */ - public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) - { - if (!$this->isStarted()) { - $this->start(); - } - - $sent = 0; - $failedRecipients = (array) $failedRecipients; - - if ($evt = $this->eventDispatcher->createSendEvent($this, $message)) { - $this->eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed'); - if ($evt->bubbleCancelled()) { - return 0; - } - } - - if (!$reversePath = $this->getReversePath($message)) { - $this->throwException(new Swift_TransportException('Cannot send message without a sender address')); - } - - $to = (array) $message->getTo(); - $cc = (array) $message->getCc(); - $bcc = (array) $message->getBcc(); - $tos = array_merge($to, $cc, $bcc); - - $message->setBcc([]); - - try { - $sent += $this->sendTo($message, $reversePath, $tos, $failedRecipients); - } finally { - $message->setBcc($bcc); - } - - if ($evt) { - if ($sent == \count($to) + \count($cc) + \count($bcc)) { - $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS); - } elseif ($sent > 0) { - $evt->setResult(Swift_Events_SendEvent::RESULT_TENTATIVE); - } else { - $evt->setResult(Swift_Events_SendEvent::RESULT_FAILED); - } - $evt->setFailedRecipients($failedRecipients); - $this->eventDispatcher->dispatchEvent($evt, 'sendPerformed'); - } - - $message->generateId(); //Make sure a new Message ID is used - - return $sent; - } - - /** - * Stop the SMTP connection. - */ - public function stop() - { - if ($this->started) { - if ($evt = $this->eventDispatcher->createTransportChangeEvent($this)) { - $this->eventDispatcher->dispatchEvent($evt, 'beforeTransportStopped'); - if ($evt->bubbleCancelled()) { - return; - } - } - - try { - $this->executeCommand("QUIT\r\n", [221]); - } catch (Swift_TransportException $e) { - } - - try { - $this->buffer->terminate(); - - if ($evt) { - $this->eventDispatcher->dispatchEvent($evt, 'transportStopped'); - } - } catch (Swift_TransportException $e) { - $this->throwException($e); - } - } - $this->started = false; - } - - /** - * {@inheritdoc} - */ - public function ping() - { - try { - if (!$this->isStarted()) { - $this->start(); - } - - $this->executeCommand("NOOP\r\n", [250]); - } catch (Swift_TransportException $e) { - try { - $this->stop(); - } catch (Swift_TransportException $e) { - } - - return false; - } - - return true; - } - - /** - * Register a plugin. - */ - public function registerPlugin(Swift_Events_EventListener $plugin) - { - $this->eventDispatcher->bindEventListener($plugin); - } - - /** - * Reset the current mail transaction. - */ - public function reset() - { - $this->executeCommand("RSET\r\n", [250], $failures, true); - } - - /** - * Get the IoBuffer where read/writes are occurring. - * - * @return Swift_Transport_IoBuffer - */ - public function getBuffer() - { - return $this->buffer; - } - - /** - * Run a command against the buffer, expecting the given response codes. - * - * If no response codes are given, the response will not be validated. - * If codes are given, an exception will be thrown on an invalid response. - * If the command is RCPT TO, and the pipeline is non-empty, no exception - * will be thrown; instead the failing address is added to $failures. - * - * @param string $command - * @param int[] $codes - * @param string[] $failures An array of failures by-reference - * @param bool $pipeline Do not wait for response - * @param string $address the address, if command is RCPT TO - * - * @return string|null The server response, or null if pipelining is enabled - */ - public function executeCommand($command, $codes = [], &$failures = null, $pipeline = false, $address = null) - { - $failures = (array) $failures; - $seq = $this->buffer->write($command); - if ($evt = $this->eventDispatcher->createCommandEvent($this, $command, $codes)) { - $this->eventDispatcher->dispatchEvent($evt, 'commandSent'); - } - - $this->pipeline[] = [$command, $seq, $codes, $address]; - - if ($pipeline && $this->pipelining) { - return null; - } - - $response = null; - - while ($this->pipeline) { - list($command, $seq, $codes, $address) = array_shift($this->pipeline); - $response = $this->getFullResponse($seq); - try { - $this->assertResponseCode($response, $codes); - } catch (Swift_TransportException $e) { - if ($this->pipeline && $address) { - $failures[] = $address; - } else { - $this->throwException($e); - } - } - } - - return $response; - } - - /** Read the opening SMTP greeting */ - protected function readGreeting() - { - $this->assertResponseCode($this->getFullResponse(0), [220]); - } - - /** Send the HELO welcome */ - protected function doHeloCommand() - { - $this->executeCommand( - sprintf("HELO %s\r\n", $this->domain), [250] - ); - } - - /** Send the MAIL FROM command */ - protected function doMailFromCommand($address) - { - $address = $this->addressEncoder->encodeString($address); - $this->executeCommand( - sprintf("MAIL FROM:<%s>\r\n", $address), [250], $failures, true - ); - } - - /** Send the RCPT TO command */ - protected function doRcptToCommand($address) - { - $address = $this->addressEncoder->encodeString($address); - $this->executeCommand( - sprintf("RCPT TO:<%s>\r\n", $address), [250, 251, 252], $failures, true, $address - ); - } - - /** Send the DATA command */ - protected function doDataCommand(&$failedRecipients) - { - $this->executeCommand("DATA\r\n", [354], $failedRecipients); - } - - /** Stream the contents of the message over the buffer */ - protected function streamMessage(Swift_Mime_SimpleMessage $message) - { - $this->buffer->setWriteTranslations(["\r\n." => "\r\n.."]); - try { - $message->toByteStream($this->buffer); - $this->buffer->flushBuffers(); - } catch (Swift_TransportException $e) { - $this->throwException($e); - } - $this->buffer->setWriteTranslations([]); - $this->executeCommand("\r\n.\r\n", [250]); - } - - /** Determine the best-use reverse path for this message */ - protected function getReversePath(Swift_Mime_SimpleMessage $message) - { - $return = $message->getReturnPath(); - $sender = $message->getSender(); - $from = $message->getFrom(); - $path = null; - if (!empty($return)) { - $path = $return; - } elseif (!empty($sender)) { - // Don't use array_keys - reset($sender); // Reset Pointer to first pos - $path = key($sender); // Get key - } elseif (!empty($from)) { - reset($from); // Reset Pointer to first pos - $path = key($from); // Get key - } - - return $path; - } - - /** Throw a TransportException, first sending it to any listeners */ - protected function throwException(Swift_TransportException $e) - { - if ($evt = $this->eventDispatcher->createTransportExceptionEvent($this, $e)) { - $this->eventDispatcher->dispatchEvent($evt, 'exceptionThrown'); - if (!$evt->bubbleCancelled()) { - throw $e; - } - } else { - throw $e; - } - } - - /** Throws an Exception if a response code is incorrect */ - protected function assertResponseCode($response, $wanted) - { - if (!$response) { - $this->throwException(new Swift_TransportException('Expected response code '.implode('/', $wanted).' but got an empty response')); - } - - list($code) = sscanf($response, '%3d'); - $valid = (empty($wanted) || \in_array($code, $wanted)); - - if ($evt = $this->eventDispatcher->createResponseEvent($this, $response, - $valid)) { - $this->eventDispatcher->dispatchEvent($evt, 'responseReceived'); - } - - if (!$valid) { - $this->throwException(new Swift_TransportException('Expected response code '.implode('/', $wanted).' but got code "'.$code.'", with message "'.$response.'"', $code)); - } - } - - /** Get an entire multi-line response using its sequence number */ - protected function getFullResponse($seq) - { - $response = ''; - try { - do { - $line = $this->buffer->readLine($seq); - $response .= $line; - } while (null !== $line && false !== $line && ' ' != $line[3]); - } catch (Swift_TransportException $e) { - $this->throwException($e); - } catch (Swift_IoException $e) { - $this->throwException(new Swift_TransportException($e->getMessage(), 0, $e)); - } - - return $response; - } - - /** Send an email to the given recipients from the given reverse path */ - private function doMailTransaction($message, $reversePath, array $recipients, array &$failedRecipients) - { - $sent = 0; - $this->doMailFromCommand($reversePath); - foreach ($recipients as $forwardPath) { - try { - $this->doRcptToCommand($forwardPath); - ++$sent; - } catch (Swift_TransportException $e) { - $failedRecipients[] = $forwardPath; - } catch (Swift_AddressEncoderException $e) { - $failedRecipients[] = $forwardPath; - } - } - - if (0 != $sent) { - $sent += \count($failedRecipients); - $this->doDataCommand($failedRecipients); - $sent -= \count($failedRecipients); - - $this->streamMessage($message); - } else { - $this->reset(); - } - - return $sent; - } - - /** Send a message to the given To: recipients */ - private function sendTo(Swift_Mime_SimpleMessage $message, $reversePath, array $to, array &$failedRecipients) - { - if (empty($to)) { - return 0; - } - - return $this->doMailTransaction($message, $reversePath, array_keys($to), - $failedRecipients); - } - - /** - * Destructor. - */ - public function __destruct() - { - try { - $this->stop(); - } catch (Exception $e) { - } - } - - public function __sleep() - { - throw new \BadMethodCallException('Cannot serialize '.__CLASS__); - } - - public function __wakeup() - { - throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); - } + /** Input-Output buffer for sending/receiving SMTP commands and responses */ + protected $buffer; + + /** Connection status */ + protected $started = false; + + /** The domain name to use in HELO command */ + protected $domain = '[127.0.0.1]'; + + /** The event dispatching layer */ + protected $eventDispatcher; + + protected $addressEncoder; + + /** Whether the PIPELINING SMTP extension is enabled (RFC 2920) */ + protected $pipelining = null; + + /** The pipelined commands waiting for response */ + protected $pipeline = []; + + /** Source Ip */ + protected $sourceIp; + + /** Return an array of params for the Buffer */ + abstract protected function getBufferParams(); + + /** + * Creates a new EsmtpTransport using the given I/O buffer. + * + * @param string $localDomain + */ + public function __construct(Swift_Transport_IoBuffer $buf, Swift_Events_EventDispatcher $dispatcher, $localDomain = '127.0.0.1', Swift_AddressEncoder $addressEncoder = null) + { + $this->buffer = $buf; + $this->eventDispatcher = $dispatcher; + $this->addressEncoder = $addressEncoder ?? new Swift_AddressEncoder_IdnAddressEncoder(); + $this->setLocalDomain($localDomain); + } + + /** + * Set the name of the local domain which Swift will identify itself as. + * + * This should be a fully-qualified domain name and should be truly the domain + * you're using. + * + * If your server does not have a domain name, use the IP address. This will + * automatically be wrapped in square brackets as described in RFC 5321, + * section 4.1.3. + * + * @param string $domain + * + * @return $this + */ + public function setLocalDomain($domain) + { + if ('[' !== substr($domain, 0, 1)) { + if (filter_var($domain, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { + $domain = '['.$domain.']'; + } elseif (filter_var($domain, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { + $domain = '[IPv6:'.$domain.']'; + } + } + + $this->domain = $domain; + + return $this; + } + + /** + * Get the name of the domain Swift will identify as. + * + * If an IP address was specified, this will be returned wrapped in square + * brackets as described in RFC 5321, section 4.1.3. + * + * @return string + */ + public function getLocalDomain() + { + return $this->domain; + } + + /** + * Sets the source IP. + * + * @param string $source + */ + public function setSourceIp($source) + { + $this->sourceIp = $source; + } + + /** + * Returns the IP used to connect to the destination. + * + * @return string + */ + public function getSourceIp() + { + return $this->sourceIp; + } + + public function setAddressEncoder(Swift_AddressEncoder $addressEncoder) + { + $this->addressEncoder = $addressEncoder; + } + + public function getAddressEncoder() + { + return $this->addressEncoder; + } + + /** + * Start the SMTP connection. + */ + public function start() + { + if (!$this->started) { + if ($evt = $this->eventDispatcher->createTransportChangeEvent($this)) { + $this->eventDispatcher->dispatchEvent($evt, 'beforeTransportStarted'); + if ($evt->bubbleCancelled()) { + return; + } + } + + try { + $this->buffer->initialize($this->getBufferParams()); + } catch (Swift_TransportException $e) { + $this->throwException($e); + } + $this->readGreeting(); + $this->doHeloCommand(); + + if ($evt) { + $this->eventDispatcher->dispatchEvent($evt, 'transportStarted'); + } + + $this->started = true; + } + } + + /** + * Test if an SMTP connection has been established. + * + * @return bool + */ + public function isStarted() + { + return $this->started; + } + + /** + * Send the given Message. + * + * Recipient/sender data will be retrieved from the Message API. + * The return value is the number of recipients who were accepted for delivery. + * + * @param string[] $failedRecipients An array of failures by-reference + * + * @return int + */ + public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) + { + if (!$this->isStarted()) { + $this->start(); + } + + $sent = 0; + $failedRecipients = (array) $failedRecipients; + + if ($evt = $this->eventDispatcher->createSendEvent($this, $message)) { + $this->eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed'); + if ($evt->bubbleCancelled()) { + return 0; + } + } + + if (!$reversePath = $this->getReversePath($message)) { + $this->throwException(new Swift_TransportException('Cannot send message without a sender address')); + } + + $to = (array) $message->getTo(); + $cc = (array) $message->getCc(); + $bcc = (array) $message->getBcc(); + $tos = array_merge($to, $cc, $bcc); + + $message->setBcc([]); + + try { + $sent += $this->sendTo($message, $reversePath, $tos, $failedRecipients); + } finally { + $message->setBcc($bcc); + } + + if ($evt) { + if ($sent == \count($to) + \count($cc) + \count($bcc)) { + $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS); + } elseif ($sent > 0) { + $evt->setResult(Swift_Events_SendEvent::RESULT_TENTATIVE); + } else { + $evt->setResult(Swift_Events_SendEvent::RESULT_FAILED); + } + $evt->setFailedRecipients($failedRecipients); + $this->eventDispatcher->dispatchEvent($evt, 'sendPerformed'); + } + + $message->generateId(); //Make sure a new Message ID is used + + return $sent; + } + + /** + * Stop the SMTP connection. + */ + public function stop() + { + if ($this->started) { + if ($evt = $this->eventDispatcher->createTransportChangeEvent($this)) { + $this->eventDispatcher->dispatchEvent($evt, 'beforeTransportStopped'); + if ($evt->bubbleCancelled()) { + return; + } + } + + try { + $this->executeCommand("QUIT\r\n", [221]); + } catch (Swift_TransportException $e) { + } + + try { + $this->buffer->terminate(); + + if ($evt) { + $this->eventDispatcher->dispatchEvent($evt, 'transportStopped'); + } + } catch (Swift_TransportException $e) { + $this->throwException($e); + } + } + $this->started = false; + } + + /** + * {@inheritdoc} + */ + public function ping() + { + try { + if (!$this->isStarted()) { + $this->start(); + } + + $this->executeCommand("NOOP\r\n", [250]); + } catch (Swift_TransportException $e) { + try { + $this->stop(); + } catch (Swift_TransportException $e) { + } + + return false; + } + + return true; + } + + /** + * Register a plugin. + */ + public function registerPlugin(Swift_Events_EventListener $plugin) + { + $this->eventDispatcher->bindEventListener($plugin); + } + + /** + * Reset the current mail transaction. + */ + public function reset() + { + $this->executeCommand("RSET\r\n", [250], $failures, true); + } + + /** + * Get the IoBuffer where read/writes are occurring. + * + * @return Swift_Transport_IoBuffer + */ + public function getBuffer() + { + return $this->buffer; + } + + /** + * Run a command against the buffer, expecting the given response codes. + * + * If no response codes are given, the response will not be validated. + * If codes are given, an exception will be thrown on an invalid response. + * If the command is RCPT TO, and the pipeline is non-empty, no exception + * will be thrown; instead the failing address is added to $failures. + * + * @param string $command + * @param int[] $codes + * @param string[] $failures An array of failures by-reference + * @param bool $pipeline Do not wait for response + * @param string $address the address, if command is RCPT TO + * + * @return string|null The server response, or null if pipelining is enabled + */ + public function executeCommand($command, $codes = [], &$failures = null, $pipeline = false, $address = null) + { + $failures = (array) $failures; + $seq = $this->buffer->write($command); + if ($evt = $this->eventDispatcher->createCommandEvent($this, $command, $codes)) { + $this->eventDispatcher->dispatchEvent($evt, 'commandSent'); + } + + $this->pipeline[] = [$command, $seq, $codes, $address]; + + if ($pipeline && $this->pipelining) { + return null; + } + + $response = null; + + while ($this->pipeline) { + list($command, $seq, $codes, $address) = array_shift($this->pipeline); + $response = $this->getFullResponse($seq); + try { + $this->assertResponseCode($response, $codes); + } catch (Swift_TransportException $e) { + if ($this->pipeline && $address) { + $failures[] = $address; + } else { + $this->throwException($e); + } + } + } + + return $response; + } + + /** Read the opening SMTP greeting */ + protected function readGreeting() + { + $this->assertResponseCode($this->getFullResponse(0), [220]); + } + + /** Send the HELO welcome */ + protected function doHeloCommand() + { + $this->executeCommand( + sprintf("HELO %s\r\n", $this->domain), [250] + ); + } + + /** Send the MAIL FROM command */ + protected function doMailFromCommand($address) + { + $address = $this->addressEncoder->encodeString($address); + $this->executeCommand( + sprintf("MAIL FROM:<%s>\r\n", $address), [250], $failures, true + ); + } + + /** Send the RCPT TO command */ + protected function doRcptToCommand($address) + { + $address = $this->addressEncoder->encodeString($address); + $this->executeCommand( + sprintf("RCPT TO:<%s>\r\n", $address), [250, 251, 252], $failures, true, $address + ); + } + + /** Send the DATA command */ + protected function doDataCommand(&$failedRecipients) + { + $this->executeCommand("DATA\r\n", [354], $failedRecipients); + } + + /** Stream the contents of the message over the buffer */ + protected function streamMessage(Swift_Mime_SimpleMessage $message) + { + $this->buffer->setWriteTranslations(["\r\n." => "\r\n.."]); + try { + $message->toByteStream($this->buffer); + $this->buffer->flushBuffers(); + } catch (Swift_TransportException $e) { + $this->throwException($e); + } + $this->buffer->setWriteTranslations([]); + $this->executeCommand("\r\n.\r\n", [250]); + } + + /** Determine the best-use reverse path for this message */ + protected function getReversePath(Swift_Mime_SimpleMessage $message) + { + $return = $message->getReturnPath(); + $sender = $message->getSender(); + $from = $message->getFrom(); + $path = null; + if (!empty($return)) { + $path = $return; + } elseif (!empty($sender)) { + // Don't use array_keys + reset($sender); // Reset Pointer to first pos + $path = key($sender); // Get key + } elseif (!empty($from)) { + reset($from); // Reset Pointer to first pos + $path = key($from); // Get key + } + + return $path; + } + + /** Throw a TransportException, first sending it to any listeners */ + protected function throwException(Swift_TransportException $e) + { + if ($evt = $this->eventDispatcher->createTransportExceptionEvent($this, $e)) { + $this->eventDispatcher->dispatchEvent($evt, 'exceptionThrown'); + if (!$evt->bubbleCancelled()) { + throw $e; + } + } else { + throw $e; + } + } + + /** Throws an Exception if a response code is incorrect */ + protected function assertResponseCode($response, $wanted) + { + if (!$response) { + $this->throwException(new Swift_TransportException('Expected response code '.implode('/', $wanted).' but got an empty response')); + } + + list($code) = sscanf($response, '%3d'); + $valid = (empty($wanted) || \in_array($code, $wanted)); + + if ($evt = $this->eventDispatcher->createResponseEvent($this, $response, + $valid)) { + $this->eventDispatcher->dispatchEvent($evt, 'responseReceived'); + } + + if (!$valid) { + $this->throwException(new Swift_TransportException('Expected response code '.implode('/', $wanted).' but got code "'.$code.'", with message "'.$response.'"', $code)); + } + } + + /** Get an entire multi-line response using its sequence number */ + protected function getFullResponse($seq) + { + $response = ''; + try { + do { + $line = $this->buffer->readLine($seq); + $response .= $line; + } while (null !== $line && false !== $line && ' ' != $line[3]); + } catch (Swift_TransportException $e) { + $this->throwException($e); + } catch (Swift_IoException $e) { + $this->throwException(new Swift_TransportException($e->getMessage(), 0, $e)); + } + + return $response; + } + + /** Send an email to the given recipients from the given reverse path */ + private function doMailTransaction($message, $reversePath, array $recipients, array &$failedRecipients) + { + $sent = 0; + $this->doMailFromCommand($reversePath); + foreach ($recipients as $forwardPath) { + try { + $this->doRcptToCommand($forwardPath); + ++$sent; + } catch (Swift_TransportException $e) { + $failedRecipients[] = $forwardPath; + } catch (Swift_AddressEncoderException $e) { + $failedRecipients[] = $forwardPath; + } + } + + if (0 != $sent) { + $sent += \count($failedRecipients); + $this->doDataCommand($failedRecipients); + $sent -= \count($failedRecipients); + + $this->streamMessage($message); + } else { + $this->reset(); + } + + return $sent; + } + + /** Send a message to the given To: recipients */ + private function sendTo(Swift_Mime_SimpleMessage $message, $reversePath, array $to, array &$failedRecipients) + { + if (empty($to)) { + return 0; + } + + return $this->doMailTransaction($message, $reversePath, array_keys($to), + $failedRecipients); + } + + /** + * Destructor. + */ + public function __destruct() + { + try { + $this->stop(); + } catch (Exception $e) { + } + } + + public function __sleep() + { + throw new \BadMethodCallException('Cannot serialize '.__CLASS__); + } + + public function __wakeup() + { + throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/CramMd5Authenticator.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/CramMd5Authenticator.php index bb3a1615096..1c577324ced 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/CramMd5Authenticator.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/CramMd5Authenticator.php @@ -15,61 +15,61 @@ */ class Swift_Transport_Esmtp_Auth_CramMd5Authenticator implements Swift_Transport_Esmtp_Authenticator { - /** - * Get the name of the AUTH mechanism this Authenticator handles. - * - * @return string - */ - public function getAuthKeyword() - { - return 'CRAM-MD5'; - } + /** + * Get the name of the AUTH mechanism this Authenticator handles. + * + * @return string + */ + public function getAuthKeyword() + { + return 'CRAM-MD5'; + } - /** - * {@inheritdoc} - */ - public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password) - { - try { - $challenge = $agent->executeCommand("AUTH CRAM-MD5\r\n", [334]); - $challenge = base64_decode(substr($challenge, 4)); - $message = base64_encode( - $username.' '.$this->getResponse($password, $challenge) - ); - $agent->executeCommand(sprintf("%s\r\n", $message), [235]); + /** + * {@inheritdoc} + */ + public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password) + { + try { + $challenge = $agent->executeCommand("AUTH CRAM-MD5\r\n", [334]); + $challenge = base64_decode(substr($challenge, 4)); + $message = base64_encode( + $username.' '.$this->getResponse($password, $challenge) + ); + $agent->executeCommand(sprintf("%s\r\n", $message), [235]); - return true; - } catch (Swift_TransportException $e) { - $agent->executeCommand("RSET\r\n", [250]); + return true; + } catch (Swift_TransportException $e) { + $agent->executeCommand("RSET\r\n", [250]); - throw $e; - } - } + throw $e; + } + } - /** - * Generate a CRAM-MD5 response from a server challenge. - * - * @param string $secret - * @param string $challenge - * - * @return string - */ - private function getResponse($secret, $challenge) - { - if (\strlen($secret) > 64) { - $secret = pack('H32', md5($secret)); - } + /** + * Generate a CRAM-MD5 response from a server challenge. + * + * @param string $secret + * @param string $challenge + * + * @return string + */ + private function getResponse($secret, $challenge) + { + if (\strlen($secret) > 64) { + $secret = pack('H32', md5($secret)); + } - if (\strlen($secret) < 64) { - $secret = str_pad($secret, 64, \chr(0)); - } + if (\strlen($secret) < 64) { + $secret = str_pad($secret, 64, \chr(0)); + } - $k_ipad = substr($secret, 0, 64) ^ str_repeat(\chr(0x36), 64); - $k_opad = substr($secret, 0, 64) ^ str_repeat(\chr(0x5C), 64); + $k_ipad = substr($secret, 0, 64) ^ str_repeat(\chr(0x36), 64); + $k_opad = substr($secret, 0, 64) ^ str_repeat(\chr(0x5C), 64); - $inner = pack('H32', md5($k_ipad.$challenge)); - $digest = md5($k_opad.$inner); + $inner = pack('H32', md5($k_ipad.$challenge)); + $digest = md5($k_opad.$inner); - return $digest; - } + return $digest; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/LoginAuthenticator.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/LoginAuthenticator.php index 0b9d81b8ad6..22e9ac723fd 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/LoginAuthenticator.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/LoginAuthenticator.php @@ -15,31 +15,31 @@ */ class Swift_Transport_Esmtp_Auth_LoginAuthenticator implements Swift_Transport_Esmtp_Authenticator { - /** - * Get the name of the AUTH mechanism this Authenticator handles. - * - * @return string - */ - public function getAuthKeyword() - { - return 'LOGIN'; - } + /** + * Get the name of the AUTH mechanism this Authenticator handles. + * + * @return string + */ + public function getAuthKeyword() + { + return 'LOGIN'; + } - /** - * {@inheritdoc} - */ - public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password) - { - try { - $agent->executeCommand("AUTH LOGIN\r\n", [334]); - $agent->executeCommand(sprintf("%s\r\n", base64_encode($username ?? '')), [334]); - $agent->executeCommand(sprintf("%s\r\n", base64_encode($password ?? '')), [235]); + /** + * {@inheritdoc} + */ + public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password) + { + try { + $agent->executeCommand("AUTH LOGIN\r\n", [334]); + $agent->executeCommand(sprintf("%s\r\n", base64_encode($username ?? '')), [334]); + $agent->executeCommand(sprintf("%s\r\n", base64_encode($password ?? '')), [235]); - return true; - } catch (Swift_TransportException $e) { - $agent->executeCommand("RSET\r\n", [250]); + return true; + } catch (Swift_TransportException $e) { + $agent->executeCommand("RSET\r\n", [250]); - throw $e; - } - } + throw $e; + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/NTLMAuthenticator.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/NTLMAuthenticator.php index 41931fdd226..dfccdecf200 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/NTLMAuthenticator.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/NTLMAuthenticator.php @@ -17,665 +17,665 @@ */ class Swift_Transport_Esmtp_Auth_NTLMAuthenticator implements Swift_Transport_Esmtp_Authenticator { - const NTLMSIG = "NTLMSSP\x00"; - const DESCONST = 'KGS!@#$%'; - - /** - * Get the name of the AUTH mechanism this Authenticator handles. - * - * @return string - */ - public function getAuthKeyword() - { - return 'NTLM'; - } - - /** - * {@inheritdoc} - * - * @throws \LogicException - */ - public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password) - { - if (!\function_exists('openssl_encrypt')) { - throw new LogicException('The OpenSSL extension must be enabled to use the NTLM authenticator.'); - } - - if (!\function_exists('bcmul')) { - throw new LogicException('The BCMath functions must be enabled to use the NTLM authenticator.'); - } - - try { - // execute AUTH command and filter out the code at the beginning - // AUTH NTLM xxxx - $response = base64_decode(substr(trim($this->sendMessage1($agent) ?? ''), 4)); - - // extra parameters for our unit cases - $timestamp = \func_num_args() > 3 ? func_get_arg(3) : $this->getCorrectTimestamp(bcmul(microtime(true), '1000')); - $client = \func_num_args() > 4 ? func_get_arg(4) : random_bytes(8); - - // Message 3 response - $this->sendMessage3($response, $username, $password, $timestamp, $client, $agent); - - return true; - } catch (Swift_TransportException $e) { - $agent->executeCommand("RSET\r\n", [250]); - - throw $e; - } - } - - protected function si2bin($si, $bits = 32) - { - $bin = null; - if ($si >= -2 ** ($bits - 1) && ($si <= 2 ** ($bits - 1))) { - // positive or zero - if ($si >= 0) { - $bin = base_convert($si, 10, 2); - // pad to $bits bit - $bin_length = \strlen($bin); - if ($bin_length < $bits) { - $bin = str_repeat('0', $bits - $bin_length).$bin; - } - } else { - // negative - $si = -$si - 2 ** $bits; - $bin = base_convert($si, 10, 2); - $bin_length = \strlen($bin); - if ($bin_length > $bits) { - $bin = str_repeat('1', $bits - $bin_length).$bin; - } - } - } - - return $bin; - } - - /** - * Send our auth message and returns the response. - * - * @return string SMTP Response - */ - protected function sendMessage1(Swift_Transport_SmtpAgent $agent) - { - $message = $this->createMessage1(); - - return $agent->executeCommand(sprintf("AUTH %s %s\r\n", $this->getAuthKeyword(), base64_encode($message)), [334]); - } - - /** - * Fetch all details of our response (message 2). - * - * @param string $response - * - * @return array our response parsed - */ - protected function parseMessage2($response) - { - $responseHex = bin2hex($response); - $length = floor(hexdec(substr($responseHex, 28, 4)) / 256) * 2; - $offset = floor(hexdec(substr($responseHex, 32, 4)) / 256) * 2; - $challenge = hex2bin(substr($responseHex, 48, 16)); - $context = hex2bin(substr($responseHex, 64, 16)); - $targetInfoH = hex2bin(substr($responseHex, 80, 16)); - $targetName = hex2bin(substr($responseHex, $offset, $length)); - $offset = floor(hexdec(substr($responseHex, 88, 4)) / 256) * 2; - $targetInfoBlock = substr($responseHex, $offset); - list($domainName, $serverName, $DNSDomainName, $DNSServerName, $terminatorByte) = $this->readSubBlock($targetInfoBlock); - - return [ - $challenge, - $context, - $targetInfoH, - $targetName, - $domainName, - $serverName, - $DNSDomainName, - $DNSServerName, - hex2bin($targetInfoBlock), - $terminatorByte, - ]; - } - - /** - * Read the blob information in from message2. - * - * @return array - */ - protected function readSubBlock($block) - { - // remove terminatorByte cause it's always the same - $block = substr($block, 0, -8); - - $length = \strlen($block); - $offset = 0; - $data = []; - while ($offset < $length) { - $blockLength = hexdec(substr(substr($block, $offset, 8), -4)) / 256; - $offset += 8; - $data[] = hex2bin(substr($block, $offset, $blockLength * 2)); - $offset += $blockLength * 2; - } - - if (3 == \count($data)) { - $data[] = $data[2]; - $data[2] = ''; - } - - $data[] = $this->createByte('00'); - - return $data; - } - - /** - * Send our final message with all our data. - * - * @param string $response Message 1 response (message 2) - * @param string $username - * @param string $password - * @param string $timestamp - * @param string $client - * @param bool $v2 Use version2 of the protocol - * - * @return string - */ - protected function sendMessage3($response, $username, $password, $timestamp, $client, Swift_Transport_SmtpAgent $agent, $v2 = true) - { - list($domain, $username) = $this->getDomainAndUsername($username); - //$challenge, $context, $targetInfoH, $targetName, $domainName, $workstation, $DNSDomainName, $DNSServerName, $blob, $ter - list($challenge, , , , , $workstation, , , $blob) = $this->parseMessage2($response); - - if (!$v2) { - // LMv1 - $lmResponse = $this->createLMPassword($password, $challenge); - // NTLMv1 - $ntlmResponse = $this->createNTLMPassword($password, $challenge); - } else { - // LMv2 - $lmResponse = $this->createLMv2Password($password, $username, $domain, $challenge, $client); - // NTLMv2 - $ntlmResponse = $this->createNTLMv2Hash($password, $username, $domain, $challenge, $blob, $timestamp, $client); - } - - $message = $this->createMessage3($domain, $username, $workstation, $lmResponse, $ntlmResponse); - - return $agent->executeCommand(sprintf("%s\r\n", base64_encode($message)), [235]); - } - - /** - * Create our message 1. - * - * @return string - */ - protected function createMessage1() - { - return self::NTLMSIG - .$this->createByte('01') // Message 1 -.$this->createByte('0702'); // Flags - } - - /** - * Create our message 3. - * - * @param string $domain - * @param string $username - * @param string $workstation - * @param string $lmResponse - * @param string $ntlmResponse - * - * @return string - */ - protected function createMessage3($domain, $username, $workstation, $lmResponse, $ntlmResponse) - { - // Create security buffers - $domainSec = $this->createSecurityBuffer($domain, 64); - $domainInfo = $this->readSecurityBuffer(bin2hex($domainSec)); - $userSec = $this->createSecurityBuffer($username, ($domainInfo[0] + $domainInfo[1]) / 2); - $userInfo = $this->readSecurityBuffer(bin2hex($userSec)); - $workSec = $this->createSecurityBuffer($workstation, ($userInfo[0] + $userInfo[1]) / 2); - $workInfo = $this->readSecurityBuffer(bin2hex($workSec)); - $lmSec = $this->createSecurityBuffer($lmResponse, ($workInfo[0] + $workInfo[1]) / 2, true); - $lmInfo = $this->readSecurityBuffer(bin2hex($lmSec)); - $ntlmSec = $this->createSecurityBuffer($ntlmResponse, ($lmInfo[0] + $lmInfo[1]) / 2, true); - - return self::NTLMSIG - .$this->createByte('03') // TYPE 3 message -.$lmSec // LM response header -.$ntlmSec // NTLM response header -.$domainSec // Domain header -.$userSec // User header -.$workSec // Workstation header -.$this->createByte('000000009a', 8) // session key header (empty) -.$this->createByte('01020000') // FLAGS -.$this->convertTo16bit($domain) // domain name -.$this->convertTo16bit($username) // username -.$this->convertTo16bit($workstation) // workstation -.$lmResponse - .$ntlmResponse; - } - - /** - * @param string $timestamp Epoch timestamp in microseconds - * @param string $client Random bytes - * @param string $targetInfo - * - * @return string - */ - protected function createBlob($timestamp, $client, $targetInfo) - { - return $this->createByte('0101') - .$this->createByte('00') - .$timestamp - .$client - .$this->createByte('00') - .$targetInfo - .$this->createByte('00'); - } - - /** - * Get domain and username from our username. - * - * @example DOMAIN\username - * - * @param string $name - * - * @return array - */ - protected function getDomainAndUsername($name) - { - if (false !== strpos($name, '\\')) { - return explode('\\', $name); - } - - if (false !== strpos($name, '@')) { - list($user, $domain) = explode('@', $name); - - return [$domain, $user]; - } - - // no domain passed - return ['', $name]; - } - - /** - * Create LMv1 response. - * - * @param string $password - * @param string $challenge - * - * @return string - */ - protected function createLMPassword($password, $challenge) - { - // FIRST PART - $password = $this->createByte(strtoupper($password), 14, false); - list($key1, $key2) = str_split($password, 7); - - $desKey1 = $this->createDesKey($key1); - $desKey2 = $this->createDesKey($key2); - - $constantDecrypt = $this->createByte($this->desEncrypt(self::DESCONST, $desKey1).$this->desEncrypt(self::DESCONST, $desKey2), 21, false); - - // SECOND PART - list($key1, $key2, $key3) = str_split($constantDecrypt, 7); - - $desKey1 = $this->createDesKey($key1); - $desKey2 = $this->createDesKey($key2); - $desKey3 = $this->createDesKey($key3); - - return $this->desEncrypt($challenge, $desKey1).$this->desEncrypt($challenge, $desKey2).$this->desEncrypt($challenge, $desKey3); - } - - /** - * Create NTLMv1 response. - * - * @param string $password - * @param string $challenge - * - * @return string - */ - protected function createNTLMPassword($password, $challenge) - { - // FIRST PART - $ntlmHash = $this->createByte($this->md4Encrypt($password), 21, false); - list($key1, $key2, $key3) = str_split($ntlmHash, 7); - - $desKey1 = $this->createDesKey($key1); - $desKey2 = $this->createDesKey($key2); - $desKey3 = $this->createDesKey($key3); - - return $this->desEncrypt($challenge, $desKey1).$this->desEncrypt($challenge, $desKey2).$this->desEncrypt($challenge, $desKey3); - } - - /** - * Convert a normal timestamp to a tenth of a microtime epoch time. - * - * @param string $time - * - * @return string - */ - protected function getCorrectTimestamp($time) - { - // Get our timestamp (tricky!) - $time = number_format($time, 0, '.', ''); // save microtime to string - $time = bcadd($time, '11644473600000', 0); // add epoch time - $time = bcmul($time, 10000, 0); // tenths of a microsecond. - - $binary = $this->si2bin($time, 64); // create 64 bit binary string - $timestamp = ''; - for ($i = 0; $i < 8; ++$i) { - $timestamp .= \chr(bindec(substr($binary, -(($i + 1) * 8), 8))); - } - - return $timestamp; - } - - /** - * Create LMv2 response. - * - * @param string $password - * @param string $username - * @param string $domain - * @param string $challenge NTLM Challenge - * @param string $client Random string - * - * @return string - */ - protected function createLMv2Password($password, $username, $domain, $challenge, $client) - { - $lmPass = '00'; // by default 00 - // if $password > 15 than we can't use this method - if (\strlen($password) <= 15) { - $ntlmHash = $this->md4Encrypt($password); - $ntml2Hash = $this->md5Encrypt($ntlmHash, $this->convertTo16bit(strtoupper($username).$domain)); - - $lmPass = bin2hex($this->md5Encrypt($ntml2Hash, $challenge.$client).$client); - } - - return $this->createByte($lmPass, 24); - } - - /** - * Create NTLMv2 response. - * - * @param string $password - * @param string $username - * @param string $domain - * @param string $challenge Hex values - * @param string $targetInfo Hex values - * @param string $timestamp - * @param string $client Random bytes - * - * @return string - * - * @see http://davenport.sourceforge.net/ntlm.html#theNtlmResponse - */ - protected function createNTLMv2Hash($password, $username, $domain, $challenge, $targetInfo, $timestamp, $client) - { - $ntlmHash = $this->md4Encrypt($password); - $ntml2Hash = $this->md5Encrypt($ntlmHash, $this->convertTo16bit(strtoupper($username).$domain)); - - // create blob - $blob = $this->createBlob($timestamp, $client, $targetInfo); - - $ntlmv2Response = $this->md5Encrypt($ntml2Hash, $challenge.$blob); - - return $ntlmv2Response.$blob; - } - - protected function createDesKey($key) - { - $material = [bin2hex($key[0])]; - $len = \strlen($key); - for ($i = 1; $i < $len; ++$i) { - list($high, $low) = str_split(bin2hex($key[$i])); - $v = $this->castToByte(\ord($key[$i - 1]) << (7 + 1 - $i) | $this->uRShift(hexdec(dechex(hexdec($high) & 0xf).dechex(hexdec($low) & 0xf)), $i)); - $material[] = str_pad(substr(dechex($v), -2), 2, '0', STR_PAD_LEFT); // cast to byte - } - $material[] = str_pad(substr(dechex($this->castToByte(\ord($key[6]) << 1)), -2), 2, '0'); - - // odd parity - foreach ($material as $k => $v) { - $b = $this->castToByte(hexdec($v)); - $needsParity = 0 == (($this->uRShift($b, 7) ^ $this->uRShift($b, 6) ^ $this->uRShift($b, 5) - ^ $this->uRShift($b, 4) ^ $this->uRShift($b, 3) ^ $this->uRShift($b, 2) - ^ $this->uRShift($b, 1)) & 0x01); - - list($high, $low) = str_split($v); - if ($needsParity) { - $material[$k] = dechex(hexdec($high) | 0x0).dechex(hexdec($low) | 0x1); - } else { - $material[$k] = dechex(hexdec($high) & 0xf).dechex(hexdec($low) & 0xe); - } - } - - return hex2bin(implode('', $material)); - } - - /** HELPER FUNCTIONS */ - - /** - * Create our security buffer depending on length and offset. - * - * @param string $value Value we want to put in - * @param int $offset start of value - * @param bool $is16 Do we 16bit string or not? - * - * @return string - */ - protected function createSecurityBuffer($value, $offset, $is16 = false) - { - $length = \strlen(bin2hex($value)); - $length = $is16 ? $length / 2 : $length; - $length = $this->createByte(str_pad(dechex($length), 2, '0', STR_PAD_LEFT), 2); - - return $length.$length.$this->createByte(dechex($offset), 4); - } - - /** - * Read our security buffer to fetch length and offset of our value. - * - * @param string $value Securitybuffer in hex - * - * @return array array with length and offset - */ - protected function readSecurityBuffer($value) - { - $length = floor(hexdec(substr($value, 0, 4)) / 256) * 2; - $offset = floor(hexdec(substr($value, 8, 4)) / 256) * 2; - - return [$length, $offset]; - } - - /** - * Cast to byte java equivalent to (byte). - * - * @param int $v - * - * @return int - */ - protected function castToByte($v) - { - return (($v + 128) % 256) - 128; - } - - /** - * Java unsigned right bitwise - * $a >>> $b. - * - * @param int $a - * @param int $b - * - * @return int - */ - protected function uRShift($a, $b) - { - if (0 == $b) { - return $a; - } - - return ($a >> $b) & ~(1 << (8 * PHP_INT_SIZE - 1) >> ($b - 1)); - } - - /** - * Right padding with 0 to certain length. - * - * @param string $input - * @param int $bytes Length of bytes - * @param bool $isHex Did we provided hex value - * - * @return string - */ - protected function createByte($input, $bytes = 4, $isHex = true) - { - if ($isHex) { - $byte = hex2bin(str_pad($input, $bytes * 2, '00')); - } else { - $byte = str_pad($input, $bytes, "\x00"); - } - - return $byte; - } - - /** ENCRYPTION ALGORITHMS */ - - /** - * DES Encryption. - * - * @param string $value An 8-byte string - * @param string $key - * - * @return string - */ - protected function desEncrypt($value, $key) - { - return substr(openssl_encrypt($value, 'DES-ECB', $key, \OPENSSL_RAW_DATA), 0, 8); - } - - /** - * MD5 Encryption. - * - * @param string $key Encryption key - * @param string $msg Message to encrypt - * - * @return string - */ - protected function md5Encrypt($key, $msg) - { - $blocksize = 64; - if (\strlen($key) > $blocksize) { - $key = pack('H*', md5($key)); - } - - $key = str_pad($key, $blocksize, "\0"); - $ipadk = $key ^ str_repeat("\x36", $blocksize); - $opadk = $key ^ str_repeat("\x5c", $blocksize); - - return pack('H*', md5($opadk.pack('H*', md5($ipadk.$msg)))); - } - - /** - * MD4 Encryption. - * - * @param string $input - * - * @return string - * - * @see https://secure.php.net/manual/en/ref.hash.php - */ - protected function md4Encrypt($input) - { - $input = $this->convertTo16bit($input); - - return \function_exists('hash') ? hex2bin(hash('md4', $input)) : mhash(MHASH_MD4, $input); - } - - /** - * Convert UTF-8 to UTF-16. - * - * @param string $input - * - * @return string - */ - protected function convertTo16bit($input) - { - return iconv('UTF-8', 'UTF-16LE', $input); - } - - /** - * @param string $message - */ - protected function debug($message) - { - $message = bin2hex($message); - $messageId = substr($message, 16, 8); - echo substr($message, 0, 16)." NTLMSSP Signature
\n"; - echo $messageId." Type Indicator
\n"; - - if ('02000000' == $messageId) { - $map = [ - 'Challenge', - 'Context', - 'Target Information Security Buffer', - 'Target Name Data', - 'NetBIOS Domain Name', - 'NetBIOS Server Name', - 'DNS Domain Name', - 'DNS Server Name', - 'BLOB', - 'Target Information Terminator', - ]; - - $data = $this->parseMessage2(hex2bin($message)); - - foreach ($map as $key => $value) { - echo bin2hex($data[$key]).' - '.$data[$key].' ||| '.$value."
\n"; - } - } elseif ('03000000' == $messageId) { - $i = 0; - $data[$i++] = substr($message, 24, 16); - list($lmLength, $lmOffset) = $this->readSecurityBuffer($data[$i - 1]); - - $data[$i++] = substr($message, 40, 16); - list($ntmlLength, $ntmlOffset) = $this->readSecurityBuffer($data[$i - 1]); - - $data[$i++] = substr($message, 56, 16); - list($targetLength, $targetOffset) = $this->readSecurityBuffer($data[$i - 1]); - - $data[$i++] = substr($message, 72, 16); - list($userLength, $userOffset) = $this->readSecurityBuffer($data[$i - 1]); - - $data[$i++] = substr($message, 88, 16); - list($workLength, $workOffset) = $this->readSecurityBuffer($data[$i - 1]); - - $data[$i++] = substr($message, 104, 16); - $data[$i++] = substr($message, 120, 8); - $data[$i++] = substr($message, $targetOffset, $targetLength); - $data[$i++] = substr($message, $userOffset, $userLength); - $data[$i++] = substr($message, $workOffset, $workLength); - $data[$i++] = substr($message, $lmOffset, $lmLength); - $data[$i] = substr($message, $ntmlOffset, $ntmlLength); - - $map = [ - 'LM Response Security Buffer', - 'NTLM Response Security Buffer', - 'Target Name Security Buffer', - 'User Name Security Buffer', - 'Workstation Name Security Buffer', - 'Session Key Security Buffer', - 'Flags', - 'Target Name Data', - 'User Name Data', - 'Workstation Name Data', - 'LM Response Data', - 'NTLM Response Data', - ]; - - foreach ($map as $key => $value) { - echo $data[$key].' - '.hex2bin($data[$key]).' ||| '.$value."
\n"; - } - } - - echo '

'; - } + const NTLMSIG = "NTLMSSP\x00"; + const DESCONST = 'KGS!@#$%'; + + /** + * Get the name of the AUTH mechanism this Authenticator handles. + * + * @return string + */ + public function getAuthKeyword() + { + return 'NTLM'; + } + + /** + * {@inheritdoc} + * + * @throws \LogicException + */ + public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password) + { + if (!\function_exists('openssl_encrypt')) { + throw new LogicException('The OpenSSL extension must be enabled to use the NTLM authenticator.'); + } + + if (!\function_exists('bcmul')) { + throw new LogicException('The BCMath functions must be enabled to use the NTLM authenticator.'); + } + + try { + // execute AUTH command and filter out the code at the beginning + // AUTH NTLM xxxx + $response = base64_decode(substr(trim($this->sendMessage1($agent) ?? ''), 4)); + + // extra parameters for our unit cases + $timestamp = \func_num_args() > 3 ? func_get_arg(3) : $this->getCorrectTimestamp(bcmul(microtime(true), '1000')); + $client = \func_num_args() > 4 ? func_get_arg(4) : random_bytes(8); + + // Message 3 response + $this->sendMessage3($response, $username, $password, $timestamp, $client, $agent); + + return true; + } catch (Swift_TransportException $e) { + $agent->executeCommand("RSET\r\n", [250]); + + throw $e; + } + } + + protected function si2bin($si, $bits = 32) + { + $bin = null; + if ($si >= -2 ** ($bits - 1) && ($si <= 2 ** ($bits - 1))) { + // positive or zero + if ($si >= 0) { + $bin = base_convert($si, 10, 2); + // pad to $bits bit + $bin_length = \strlen($bin); + if ($bin_length < $bits) { + $bin = str_repeat('0', $bits - $bin_length).$bin; + } + } else { + // negative + $si = -$si - 2 ** $bits; + $bin = base_convert($si, 10, 2); + $bin_length = \strlen($bin); + if ($bin_length > $bits) { + $bin = str_repeat('1', $bits - $bin_length).$bin; + } + } + } + + return $bin; + } + + /** + * Send our auth message and returns the response. + * + * @return string SMTP Response + */ + protected function sendMessage1(Swift_Transport_SmtpAgent $agent) + { + $message = $this->createMessage1(); + + return $agent->executeCommand(sprintf("AUTH %s %s\r\n", $this->getAuthKeyword(), base64_encode($message)), [334]); + } + + /** + * Fetch all details of our response (message 2). + * + * @param string $response + * + * @return array our response parsed + */ + protected function parseMessage2($response) + { + $responseHex = bin2hex($response); + $length = floor(hexdec(substr($responseHex, 28, 4)) / 256) * 2; + $offset = floor(hexdec(substr($responseHex, 32, 4)) / 256) * 2; + $challenge = hex2bin(substr($responseHex, 48, 16)); + $context = hex2bin(substr($responseHex, 64, 16)); + $targetInfoH = hex2bin(substr($responseHex, 80, 16)); + $targetName = hex2bin(substr($responseHex, $offset, $length)); + $offset = floor(hexdec(substr($responseHex, 88, 4)) / 256) * 2; + $targetInfoBlock = substr($responseHex, $offset); + list($domainName, $serverName, $DNSDomainName, $DNSServerName, $terminatorByte) = $this->readSubBlock($targetInfoBlock); + + return [ + $challenge, + $context, + $targetInfoH, + $targetName, + $domainName, + $serverName, + $DNSDomainName, + $DNSServerName, + hex2bin($targetInfoBlock), + $terminatorByte, + ]; + } + + /** + * Read the blob information in from message2. + * + * @return array + */ + protected function readSubBlock($block) + { + // remove terminatorByte cause it's always the same + $block = substr($block, 0, -8); + + $length = \strlen($block); + $offset = 0; + $data = []; + while ($offset < $length) { + $blockLength = hexdec(substr(substr($block, $offset, 8), -4)) / 256; + $offset += 8; + $data[] = hex2bin(substr($block, $offset, $blockLength * 2)); + $offset += $blockLength * 2; + } + + if (3 == \count($data)) { + $data[] = $data[2]; + $data[2] = ''; + } + + $data[] = $this->createByte('00'); + + return $data; + } + + /** + * Send our final message with all our data. + * + * @param string $response Message 1 response (message 2) + * @param string $username + * @param string $password + * @param string $timestamp + * @param string $client + * @param bool $v2 Use version2 of the protocol + * + * @return string + */ + protected function sendMessage3($response, $username, $password, $timestamp, $client, Swift_Transport_SmtpAgent $agent, $v2 = true) + { + list($domain, $username) = $this->getDomainAndUsername($username); + //$challenge, $context, $targetInfoH, $targetName, $domainName, $workstation, $DNSDomainName, $DNSServerName, $blob, $ter + list($challenge, , , , , $workstation, , , $blob) = $this->parseMessage2($response); + + if (!$v2) { + // LMv1 + $lmResponse = $this->createLMPassword($password, $challenge); + // NTLMv1 + $ntlmResponse = $this->createNTLMPassword($password, $challenge); + } else { + // LMv2 + $lmResponse = $this->createLMv2Password($password, $username, $domain, $challenge, $client); + // NTLMv2 + $ntlmResponse = $this->createNTLMv2Hash($password, $username, $domain, $challenge, $blob, $timestamp, $client); + } + + $message = $this->createMessage3($domain, $username, $workstation, $lmResponse, $ntlmResponse); + + return $agent->executeCommand(sprintf("%s\r\n", base64_encode($message)), [235]); + } + + /** + * Create our message 1. + * + * @return string + */ + protected function createMessage1() + { + return self::NTLMSIG + .$this->createByte('01') // Message 1 + .$this->createByte('0702'); // Flags + } + + /** + * Create our message 3. + * + * @param string $domain + * @param string $username + * @param string $workstation + * @param string $lmResponse + * @param string $ntlmResponse + * + * @return string + */ + protected function createMessage3($domain, $username, $workstation, $lmResponse, $ntlmResponse) + { + // Create security buffers + $domainSec = $this->createSecurityBuffer($domain, 64); + $domainInfo = $this->readSecurityBuffer(bin2hex($domainSec)); + $userSec = $this->createSecurityBuffer($username, ($domainInfo[0] + $domainInfo[1]) / 2); + $userInfo = $this->readSecurityBuffer(bin2hex($userSec)); + $workSec = $this->createSecurityBuffer($workstation, ($userInfo[0] + $userInfo[1]) / 2); + $workInfo = $this->readSecurityBuffer(bin2hex($workSec)); + $lmSec = $this->createSecurityBuffer($lmResponse, ($workInfo[0] + $workInfo[1]) / 2, true); + $lmInfo = $this->readSecurityBuffer(bin2hex($lmSec)); + $ntlmSec = $this->createSecurityBuffer($ntlmResponse, ($lmInfo[0] + $lmInfo[1]) / 2, true); + + return self::NTLMSIG + .$this->createByte('03') // TYPE 3 message + .$lmSec // LM response header + .$ntlmSec // NTLM response header + .$domainSec // Domain header + .$userSec // User header + .$workSec // Workstation header + .$this->createByte('000000009a', 8) // session key header (empty) + .$this->createByte('01020000') // FLAGS + .$this->convertTo16bit($domain) // domain name + .$this->convertTo16bit($username) // username + .$this->convertTo16bit($workstation) // workstation + .$lmResponse + .$ntlmResponse; + } + + /** + * @param string $timestamp Epoch timestamp in microseconds + * @param string $client Random bytes + * @param string $targetInfo + * + * @return string + */ + protected function createBlob($timestamp, $client, $targetInfo) + { + return $this->createByte('0101') + .$this->createByte('00') + .$timestamp + .$client + .$this->createByte('00') + .$targetInfo + .$this->createByte('00'); + } + + /** + * Get domain and username from our username. + * + * @example DOMAIN\username + * + * @param string $name + * + * @return array + */ + protected function getDomainAndUsername($name) + { + if (false !== strpos($name, '\\')) { + return explode('\\', $name); + } + + if (false !== strpos($name, '@')) { + list($user, $domain) = explode('@', $name); + + return [$domain, $user]; + } + + // no domain passed + return ['', $name]; + } + + /** + * Create LMv1 response. + * + * @param string $password + * @param string $challenge + * + * @return string + */ + protected function createLMPassword($password, $challenge) + { + // FIRST PART + $password = $this->createByte(strtoupper($password), 14, false); + list($key1, $key2) = str_split($password, 7); + + $desKey1 = $this->createDesKey($key1); + $desKey2 = $this->createDesKey($key2); + + $constantDecrypt = $this->createByte($this->desEncrypt(self::DESCONST, $desKey1).$this->desEncrypt(self::DESCONST, $desKey2), 21, false); + + // SECOND PART + list($key1, $key2, $key3) = str_split($constantDecrypt, 7); + + $desKey1 = $this->createDesKey($key1); + $desKey2 = $this->createDesKey($key2); + $desKey3 = $this->createDesKey($key3); + + return $this->desEncrypt($challenge, $desKey1).$this->desEncrypt($challenge, $desKey2).$this->desEncrypt($challenge, $desKey3); + } + + /** + * Create NTLMv1 response. + * + * @param string $password + * @param string $challenge + * + * @return string + */ + protected function createNTLMPassword($password, $challenge) + { + // FIRST PART + $ntlmHash = $this->createByte($this->md4Encrypt($password), 21, false); + list($key1, $key2, $key3) = str_split($ntlmHash, 7); + + $desKey1 = $this->createDesKey($key1); + $desKey2 = $this->createDesKey($key2); + $desKey3 = $this->createDesKey($key3); + + return $this->desEncrypt($challenge, $desKey1).$this->desEncrypt($challenge, $desKey2).$this->desEncrypt($challenge, $desKey3); + } + + /** + * Convert a normal timestamp to a tenth of a microtime epoch time. + * + * @param string $time + * + * @return string + */ + protected function getCorrectTimestamp($time) + { + // Get our timestamp (tricky!) + $time = number_format($time, 0, '.', ''); // save microtime to string + $time = bcadd($time, '11644473600000', 0); // add epoch time + $time = bcmul($time, 10000, 0); // tenths of a microsecond. + + $binary = $this->si2bin($time, 64); // create 64 bit binary string + $timestamp = ''; + for ($i = 0; $i < 8; ++$i) { + $timestamp .= \chr(bindec(substr($binary, -(($i + 1) * 8), 8))); + } + + return $timestamp; + } + + /** + * Create LMv2 response. + * + * @param string $password + * @param string $username + * @param string $domain + * @param string $challenge NTLM Challenge + * @param string $client Random string + * + * @return string + */ + protected function createLMv2Password($password, $username, $domain, $challenge, $client) + { + $lmPass = '00'; // by default 00 + // if $password > 15 than we can't use this method + if (\strlen($password) <= 15) { + $ntlmHash = $this->md4Encrypt($password); + $ntml2Hash = $this->md5Encrypt($ntlmHash, $this->convertTo16bit(strtoupper($username).$domain)); + + $lmPass = bin2hex($this->md5Encrypt($ntml2Hash, $challenge.$client).$client); + } + + return $this->createByte($lmPass, 24); + } + + /** + * Create NTLMv2 response. + * + * @param string $password + * @param string $username + * @param string $domain + * @param string $challenge Hex values + * @param string $targetInfo Hex values + * @param string $timestamp + * @param string $client Random bytes + * + * @return string + * + * @see http://davenport.sourceforge.net/ntlm.html#theNtlmResponse + */ + protected function createNTLMv2Hash($password, $username, $domain, $challenge, $targetInfo, $timestamp, $client) + { + $ntlmHash = $this->md4Encrypt($password); + $ntml2Hash = $this->md5Encrypt($ntlmHash, $this->convertTo16bit(strtoupper($username).$domain)); + + // create blob + $blob = $this->createBlob($timestamp, $client, $targetInfo); + + $ntlmv2Response = $this->md5Encrypt($ntml2Hash, $challenge.$blob); + + return $ntlmv2Response.$blob; + } + + protected function createDesKey($key) + { + $material = [bin2hex($key[0])]; + $len = \strlen($key); + for ($i = 1; $i < $len; ++$i) { + list($high, $low) = str_split(bin2hex($key[$i])); + $v = $this->castToByte(\ord($key[$i - 1]) << (7 + 1 - $i) | $this->uRShift(hexdec(dechex(hexdec($high) & 0xf).dechex(hexdec($low) & 0xf)), $i)); + $material[] = str_pad(substr(dechex($v), -2), 2, '0', STR_PAD_LEFT); // cast to byte + } + $material[] = str_pad(substr(dechex($this->castToByte(\ord($key[6]) << 1)), -2), 2, '0'); + + // odd parity + foreach ($material as $k => $v) { + $b = $this->castToByte(hexdec($v)); + $needsParity = 0 == (($this->uRShift($b, 7) ^ $this->uRShift($b, 6) ^ $this->uRShift($b, 5) + ^ $this->uRShift($b, 4) ^ $this->uRShift($b, 3) ^ $this->uRShift($b, 2) + ^ $this->uRShift($b, 1)) & 0x01); + + list($high, $low) = str_split($v); + if ($needsParity) { + $material[$k] = dechex(hexdec($high) | 0x0).dechex(hexdec($low) | 0x1); + } else { + $material[$k] = dechex(hexdec($high) & 0xf).dechex(hexdec($low) & 0xe); + } + } + + return hex2bin(implode('', $material)); + } + + /** HELPER FUNCTIONS */ + + /** + * Create our security buffer depending on length and offset. + * + * @param string $value Value we want to put in + * @param int $offset start of value + * @param bool $is16 Do we 16bit string or not? + * + * @return string + */ + protected function createSecurityBuffer($value, $offset, $is16 = false) + { + $length = \strlen(bin2hex($value)); + $length = $is16 ? $length / 2 : $length; + $length = $this->createByte(str_pad(dechex($length), 2, '0', STR_PAD_LEFT), 2); + + return $length.$length.$this->createByte(dechex($offset), 4); + } + + /** + * Read our security buffer to fetch length and offset of our value. + * + * @param string $value Securitybuffer in hex + * + * @return array array with length and offset + */ + protected function readSecurityBuffer($value) + { + $length = floor(hexdec(substr($value, 0, 4)) / 256) * 2; + $offset = floor(hexdec(substr($value, 8, 4)) / 256) * 2; + + return [$length, $offset]; + } + + /** + * Cast to byte java equivalent to (byte). + * + * @param int $v + * + * @return int + */ + protected function castToByte($v) + { + return (($v + 128) % 256) - 128; + } + + /** + * Java unsigned right bitwise + * $a >>> $b. + * + * @param int $a + * @param int $b + * + * @return int + */ + protected function uRShift($a, $b) + { + if (0 == $b) { + return $a; + } + + return ($a >> $b) & ~(1 << (8 * PHP_INT_SIZE - 1) >> ($b - 1)); + } + + /** + * Right padding with 0 to certain length. + * + * @param string $input + * @param int $bytes Length of bytes + * @param bool $isHex Did we provided hex value + * + * @return string + */ + protected function createByte($input, $bytes = 4, $isHex = true) + { + if ($isHex) { + $byte = hex2bin(str_pad($input, $bytes * 2, '00')); + } else { + $byte = str_pad($input, $bytes, "\x00"); + } + + return $byte; + } + + /** ENCRYPTION ALGORITHMS */ + + /** + * DES Encryption. + * + * @param string $value An 8-byte string + * @param string $key + * + * @return string + */ + protected function desEncrypt($value, $key) + { + return substr(openssl_encrypt($value, 'DES-ECB', $key, \OPENSSL_RAW_DATA), 0, 8); + } + + /** + * MD5 Encryption. + * + * @param string $key Encryption key + * @param string $msg Message to encrypt + * + * @return string + */ + protected function md5Encrypt($key, $msg) + { + $blocksize = 64; + if (\strlen($key) > $blocksize) { + $key = pack('H*', md5($key)); + } + + $key = str_pad($key, $blocksize, "\0"); + $ipadk = $key ^ str_repeat("\x36", $blocksize); + $opadk = $key ^ str_repeat("\x5c", $blocksize); + + return pack('H*', md5($opadk.pack('H*', md5($ipadk.$msg)))); + } + + /** + * MD4 Encryption. + * + * @param string $input + * + * @return string + * + * @see https://secure.php.net/manual/en/ref.hash.php + */ + protected function md4Encrypt($input) + { + $input = $this->convertTo16bit($input); + + return \function_exists('hash') ? hex2bin(hash('md4', $input)) : mhash(MHASH_MD4, $input); + } + + /** + * Convert UTF-8 to UTF-16. + * + * @param string $input + * + * @return string + */ + protected function convertTo16bit($input) + { + return iconv('UTF-8', 'UTF-16LE', $input); + } + + /** + * @param string $message + */ + protected function debug($message) + { + $message = bin2hex($message); + $messageId = substr($message, 16, 8); + echo substr($message, 0, 16)." NTLMSSP Signature
\n"; + echo $messageId." Type Indicator
\n"; + + if ('02000000' == $messageId) { + $map = [ + 'Challenge', + 'Context', + 'Target Information Security Buffer', + 'Target Name Data', + 'NetBIOS Domain Name', + 'NetBIOS Server Name', + 'DNS Domain Name', + 'DNS Server Name', + 'BLOB', + 'Target Information Terminator', + ]; + + $data = $this->parseMessage2(hex2bin($message)); + + foreach ($map as $key => $value) { + echo bin2hex($data[$key]).' - '.$data[$key].' ||| '.$value."
\n"; + } + } elseif ('03000000' == $messageId) { + $i = 0; + $data[$i++] = substr($message, 24, 16); + list($lmLength, $lmOffset) = $this->readSecurityBuffer($data[$i - 1]); + + $data[$i++] = substr($message, 40, 16); + list($ntmlLength, $ntmlOffset) = $this->readSecurityBuffer($data[$i - 1]); + + $data[$i++] = substr($message, 56, 16); + list($targetLength, $targetOffset) = $this->readSecurityBuffer($data[$i - 1]); + + $data[$i++] = substr($message, 72, 16); + list($userLength, $userOffset) = $this->readSecurityBuffer($data[$i - 1]); + + $data[$i++] = substr($message, 88, 16); + list($workLength, $workOffset) = $this->readSecurityBuffer($data[$i - 1]); + + $data[$i++] = substr($message, 104, 16); + $data[$i++] = substr($message, 120, 8); + $data[$i++] = substr($message, $targetOffset, $targetLength); + $data[$i++] = substr($message, $userOffset, $userLength); + $data[$i++] = substr($message, $workOffset, $workLength); + $data[$i++] = substr($message, $lmOffset, $lmLength); + $data[$i] = substr($message, $ntmlOffset, $ntmlLength); + + $map = [ + 'LM Response Security Buffer', + 'NTLM Response Security Buffer', + 'Target Name Security Buffer', + 'User Name Security Buffer', + 'Workstation Name Security Buffer', + 'Session Key Security Buffer', + 'Flags', + 'Target Name Data', + 'User Name Data', + 'Workstation Name Data', + 'LM Response Data', + 'NTLM Response Data', + ]; + + foreach ($map as $key => $value) { + echo $data[$key].' - '.hex2bin($data[$key]).' ||| '.$value."
\n"; + } + } + + echo '

'; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/PlainAuthenticator.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/PlainAuthenticator.php index 41d0a50a82b..cd1a2831e82 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/PlainAuthenticator.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/PlainAuthenticator.php @@ -15,30 +15,30 @@ */ class Swift_Transport_Esmtp_Auth_PlainAuthenticator implements Swift_Transport_Esmtp_Authenticator { - /** - * Get the name of the AUTH mechanism this Authenticator handles. - * - * @return string - */ - public function getAuthKeyword() - { - return 'PLAIN'; - } + /** + * Get the name of the AUTH mechanism this Authenticator handles. + * + * @return string + */ + public function getAuthKeyword() + { + return 'PLAIN'; + } - /** - * {@inheritdoc} - */ - public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password) - { - try { - $message = base64_encode($username.\chr(0).$username.\chr(0).$password); - $agent->executeCommand(sprintf("AUTH PLAIN %s\r\n", $message), [235]); + /** + * {@inheritdoc} + */ + public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password) + { + try { + $message = base64_encode($username.\chr(0).$username.\chr(0).$password); + $agent->executeCommand(sprintf("AUTH PLAIN %s\r\n", $message), [235]); - return true; - } catch (Swift_TransportException $e) { - $agent->executeCommand("RSET\r\n", [250]); + return true; + } catch (Swift_TransportException $e) { + $agent->executeCommand("RSET\r\n", [250]); - throw $e; - } - } + throw $e; + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/XOAuth2Authenticator.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/XOAuth2Authenticator.php index 859f22f3d5e..c541b0ca952 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/XOAuth2Authenticator.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/XOAuth2Authenticator.php @@ -25,40 +25,40 @@ */ class Swift_Transport_Esmtp_Auth_XOAuth2Authenticator implements Swift_Transport_Esmtp_Authenticator { - /** - * Get the name of the AUTH mechanism this Authenticator handles. - * - * @return string - */ - public function getAuthKeyword() - { - return 'XOAUTH2'; - } + /** + * Get the name of the AUTH mechanism this Authenticator handles. + * + * @return string + */ + public function getAuthKeyword() + { + return 'XOAUTH2'; + } - /** - * {@inheritdoc} - */ - public function authenticate(Swift_Transport_SmtpAgent $agent, $email, $token) - { - try { - $param = $this->constructXOAuth2Params($email, $token); - $agent->executeCommand('AUTH XOAUTH2 '.$param."\r\n", [235]); + /** + * {@inheritdoc} + */ + public function authenticate(Swift_Transport_SmtpAgent $agent, $email, $token) + { + try { + $param = $this->constructXOAuth2Params($email, $token); + $agent->executeCommand('AUTH XOAUTH2 '.$param."\r\n", [235]); - return true; - } catch (Swift_TransportException $e) { - $agent->executeCommand("RSET\r\n", [250]); + return true; + } catch (Swift_TransportException $e) { + $agent->executeCommand("RSET\r\n", [250]); - throw $e; - } - } + throw $e; + } + } - /** - * Construct the auth parameter. - * - * @see https://developers.google.com/google-apps/gmail/xoauth2_protocol#the_sasl_xoauth2_mechanism - */ - protected function constructXOAuth2Params($email, $token) - { - return base64_encode("user=$email\1auth=Bearer $token\1\1"); - } + /** + * Construct the auth parameter. + * + * @see https://developers.google.com/google-apps/gmail/xoauth2_protocol#the_sasl_xoauth2_mechanism + */ + protected function constructXOAuth2Params($email, $token) + { + return base64_encode("user=$email\1auth=Bearer $token\1\1"); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/AuthHandler.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/AuthHandler.php index 53a90a87383..26ac6086fdf 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/AuthHandler.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/AuthHandler.php @@ -15,254 +15,254 @@ */ class Swift_Transport_Esmtp_AuthHandler implements Swift_Transport_EsmtpHandler { - /** - * Authenticators available to process the request. - * - * @var Swift_Transport_Esmtp_Authenticator[] - */ - private $authenticators = []; + /** + * Authenticators available to process the request. + * + * @var Swift_Transport_Esmtp_Authenticator[] + */ + private $authenticators = []; - /** - * The username for authentication. - * - * @var string - */ - private $username; + /** + * The username for authentication. + * + * @var string + */ + private $username; - /** - * The password for authentication. - * - * @var string - */ - private $password; + /** + * The password for authentication. + * + * @var string + */ + private $password; - /** - * The auth mode for authentication. - * - * @var string - */ - private $auth_mode; + /** + * The auth mode for authentication. + * + * @var string + */ + private $auth_mode; - /** - * The ESMTP AUTH parameters available. - * - * @var string[] - */ - private $esmtpParams = []; + /** + * The ESMTP AUTH parameters available. + * + * @var string[] + */ + private $esmtpParams = []; - /** - * Create a new AuthHandler with $authenticators for support. - * - * @param Swift_Transport_Esmtp_Authenticator[] $authenticators - */ - public function __construct(array $authenticators) - { - $this->setAuthenticators($authenticators); - } + /** + * Create a new AuthHandler with $authenticators for support. + * + * @param Swift_Transport_Esmtp_Authenticator[] $authenticators + */ + public function __construct(array $authenticators) + { + $this->setAuthenticators($authenticators); + } - /** - * Set the Authenticators which can process a login request. - * - * @param Swift_Transport_Esmtp_Authenticator[] $authenticators - */ - public function setAuthenticators(array $authenticators) - { - $this->authenticators = $authenticators; - } + /** + * Set the Authenticators which can process a login request. + * + * @param Swift_Transport_Esmtp_Authenticator[] $authenticators + */ + public function setAuthenticators(array $authenticators) + { + $this->authenticators = $authenticators; + } - /** - * Get the Authenticators which can process a login request. - * - * @return Swift_Transport_Esmtp_Authenticator[] - */ - public function getAuthenticators() - { - return $this->authenticators; - } + /** + * Get the Authenticators which can process a login request. + * + * @return Swift_Transport_Esmtp_Authenticator[] + */ + public function getAuthenticators() + { + return $this->authenticators; + } - /** - * Set the username to authenticate with. - * - * @param string $username - */ - public function setUsername($username) - { - $this->username = $username; - } + /** + * Set the username to authenticate with. + * + * @param string $username + */ + public function setUsername($username) + { + $this->username = $username; + } - /** - * Get the username to authenticate with. - * - * @return string - */ - public function getUsername() - { - return $this->username; - } + /** + * Get the username to authenticate with. + * + * @return string + */ + public function getUsername() + { + return $this->username; + } - /** - * Set the password to authenticate with. - * - * @param string $password - */ - public function setPassword($password) - { - $this->password = $password; - } + /** + * Set the password to authenticate with. + * + * @param string $password + */ + public function setPassword($password) + { + $this->password = $password; + } - /** - * Get the password to authenticate with. - * - * @return string - */ - public function getPassword() - { - return $this->password; - } + /** + * Get the password to authenticate with. + * + * @return string + */ + public function getPassword() + { + return $this->password; + } - /** - * Set the auth mode to use to authenticate. - * - * @param string $mode - */ - public function setAuthMode($mode) - { - $this->auth_mode = $mode; - } + /** + * Set the auth mode to use to authenticate. + * + * @param string $mode + */ + public function setAuthMode($mode) + { + $this->auth_mode = $mode; + } - /** - * Get the auth mode to use to authenticate. - * - * @return string - */ - public function getAuthMode() - { - return $this->auth_mode; - } + /** + * Get the auth mode to use to authenticate. + * + * @return string + */ + public function getAuthMode() + { + return $this->auth_mode; + } - /** - * Get the name of the ESMTP extension this handles. - * - * @return string - */ - public function getHandledKeyword() - { - return 'AUTH'; - } + /** + * Get the name of the ESMTP extension this handles. + * + * @return string + */ + public function getHandledKeyword() + { + return 'AUTH'; + } - /** - * Set the parameters which the EHLO greeting indicated. - * - * @param string[] $parameters - */ - public function setKeywordParams(array $parameters) - { - $this->esmtpParams = $parameters; - } + /** + * Set the parameters which the EHLO greeting indicated. + * + * @param string[] $parameters + */ + public function setKeywordParams(array $parameters) + { + $this->esmtpParams = $parameters; + } - /** - * Runs immediately after a EHLO has been issued. - * - * @param Swift_Transport_SmtpAgent $agent to read/write - */ - public function afterEhlo(Swift_Transport_SmtpAgent $agent) - { - if ($this->username) { - $count = 0; - $errors = []; - foreach ($this->getAuthenticatorsForAgent() as $authenticator) { - if (\in_array(strtolower($authenticator->getAuthKeyword() ?? ''), array_map('strtolower', $this->esmtpParams))) { - ++$count; - try { - if ($authenticator->authenticate($agent, $this->username, $this->password)) { - return; - } - } catch (Swift_TransportException $e) { - // keep the error message, but tries the other authenticators - $errors[] = [$authenticator->getAuthKeyword(), $e->getMessage()]; - } - } - } + /** + * Runs immediately after a EHLO has been issued. + * + * @param Swift_Transport_SmtpAgent $agent to read/write + */ + public function afterEhlo(Swift_Transport_SmtpAgent $agent) + { + if ($this->username) { + $count = 0; + $errors = []; + foreach ($this->getAuthenticatorsForAgent() as $authenticator) { + if (\in_array(strtolower($authenticator->getAuthKeyword() ?? ''), array_map('strtolower', $this->esmtpParams))) { + ++$count; + try { + if ($authenticator->authenticate($agent, $this->username, $this->password)) { + return; + } + } catch (Swift_TransportException $e) { + // keep the error message, but tries the other authenticators + $errors[] = [$authenticator->getAuthKeyword(), $e->getMessage()]; + } + } + } - $message = 'Failed to authenticate on SMTP server with username "'.$this->username.'" using '.$count.' possible authenticators.'; - foreach ($errors as $error) { - $message .= ' Authenticator '.$error[0].' returned '.$error[1].'.'; - } - throw new Swift_TransportException($message); - } - } + $message = 'Failed to authenticate on SMTP server with username "'.$this->username.'" using '.$count.' possible authenticators.'; + foreach ($errors as $error) { + $message .= ' Authenticator '.$error[0].' returned '.$error[1].'.'; + } + throw new Swift_TransportException($message); + } + } - /** - * Not used. - */ - public function getMailParams() - { - return []; - } + /** + * Not used. + */ + public function getMailParams() + { + return []; + } - /** - * Not used. - */ - public function getRcptParams() - { - return []; - } + /** + * Not used. + */ + public function getRcptParams() + { + return []; + } - /** - * Not used. - */ - public function onCommand(Swift_Transport_SmtpAgent $agent, $command, $codes = [], &$failedRecipients = null, &$stop = false) - { - } + /** + * Not used. + */ + public function onCommand(Swift_Transport_SmtpAgent $agent, $command, $codes = [], &$failedRecipients = null, &$stop = false) + { + } - /** - * Returns +1, -1 or 0 according to the rules for usort(). - * - * This method is called to ensure extensions can be execute in an appropriate order. - * - * @param string $esmtpKeyword to compare with - * - * @return int - */ - public function getPriorityOver($esmtpKeyword) - { - return 0; - } + /** + * Returns +1, -1 or 0 according to the rules for usort(). + * + * This method is called to ensure extensions can be execute in an appropriate order. + * + * @param string $esmtpKeyword to compare with + * + * @return int + */ + public function getPriorityOver($esmtpKeyword) + { + return 0; + } - /** - * Returns an array of method names which are exposed to the Esmtp class. - * - * @return string[] - */ - public function exposeMixinMethods() - { - return ['setUsername', 'getUsername', 'setPassword', 'getPassword', 'setAuthMode', 'getAuthMode']; - } + /** + * Returns an array of method names which are exposed to the Esmtp class. + * + * @return string[] + */ + public function exposeMixinMethods() + { + return ['setUsername', 'getUsername', 'setPassword', 'getPassword', 'setAuthMode', 'getAuthMode']; + } - /** - * Not used. - */ - public function resetState() - { - } + /** + * Not used. + */ + public function resetState() + { + } - /** - * Returns the authenticator list for the given agent. - * - * @return array - */ - protected function getAuthenticatorsForAgent() - { - if (!$mode = strtolower($this->auth_mode ?? '')) { - return $this->authenticators; - } + /** + * Returns the authenticator list for the given agent. + * + * @return array + */ + protected function getAuthenticatorsForAgent() + { + if (!$mode = strtolower($this->auth_mode ?? '')) { + return $this->authenticators; + } - foreach ($this->authenticators as $authenticator) { - if (strtolower($authenticator->getAuthKeyword() ?? '') == $mode) { - return [$authenticator]; - } - } + foreach ($this->authenticators as $authenticator) { + if (strtolower($authenticator->getAuthKeyword() ?? '') == $mode) { + return [$authenticator]; + } + } - throw new Swift_TransportException('Auth mode '.$mode.' is invalid'); - } + throw new Swift_TransportException('Auth mode '.$mode.' is invalid'); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Authenticator.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Authenticator.php index f692a6fe40d..40aeb1a65cc 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Authenticator.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Authenticator.php @@ -15,22 +15,22 @@ */ interface Swift_Transport_Esmtp_Authenticator { - /** - * Get the name of the AUTH mechanism this Authenticator handles. - * - * @return string - */ - public function getAuthKeyword(); + /** + * Get the name of the AUTH mechanism this Authenticator handles. + * + * @return string + */ + public function getAuthKeyword(); - /** - * Try to authenticate the user with $username and $password. - * - * @param string $username - * @param string $password - * - * @return bool true if authentication worked (returning false is deprecated, throw a Swift_TransportException instead) - * - * @throws Swift_TransportException Allows the message to bubble up when authentication was not successful - */ - public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password); + /** + * Try to authenticate the user with $username and $password. + * + * @param string $username + * @param string $password + * + * @return bool true if authentication worked (returning false is deprecated, throw a Swift_TransportException instead) + * + * @throws Swift_TransportException Allows the message to bubble up when authentication was not successful + */ + public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/EightBitMimeHandler.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/EightBitMimeHandler.php index 63f70866939..f2ab8d2e3cc 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/EightBitMimeHandler.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/EightBitMimeHandler.php @@ -22,92 +22,92 @@ */ class Swift_Transport_Esmtp_EightBitMimeHandler implements Swift_Transport_EsmtpHandler { - protected $encoding; + protected $encoding; - /** - * @param string $encoding The parameter so send with the MAIL FROM command; - * either "8BITMIME" or "7BIT" - */ - public function __construct(string $encoding = '8BITMIME') - { - $this->encoding = $encoding; - } + /** + * @param string $encoding The parameter so send with the MAIL FROM command; + * either "8BITMIME" or "7BIT" + */ + public function __construct(string $encoding = '8BITMIME') + { + $this->encoding = $encoding; + } - /** - * Get the name of the ESMTP extension this handles. - * - * @return string - */ - public function getHandledKeyword() - { - return '8BITMIME'; - } + /** + * Get the name of the ESMTP extension this handles. + * + * @return string + */ + public function getHandledKeyword() + { + return '8BITMIME'; + } - /** - * Not used. - */ - public function setKeywordParams(array $parameters) - { - } + /** + * Not used. + */ + public function setKeywordParams(array $parameters) + { + } - /** - * Not used. - */ - public function afterEhlo(Swift_Transport_SmtpAgent $agent) - { - } + /** + * Not used. + */ + public function afterEhlo(Swift_Transport_SmtpAgent $agent) + { + } - /** - * Get params which are appended to MAIL FROM:<>. - * - * @return string[] - */ - public function getMailParams() - { - return ['BODY='.$this->encoding]; - } + /** + * Get params which are appended to MAIL FROM:<>. + * + * @return string[] + */ + public function getMailParams() + { + return ['BODY='.$this->encoding]; + } - /** - * Not used. - */ - public function getRcptParams() - { - return []; - } + /** + * Not used. + */ + public function getRcptParams() + { + return []; + } - /** - * Not used. - */ - public function onCommand(Swift_Transport_SmtpAgent $agent, $command, $codes = [], &$failedRecipients = null, &$stop = false) - { - } + /** + * Not used. + */ + public function onCommand(Swift_Transport_SmtpAgent $agent, $command, $codes = [], &$failedRecipients = null, &$stop = false) + { + } - /** - * Returns +1, -1 or 0 according to the rules for usort(). - * - * This method is called to ensure extensions can be execute in an appropriate order. - * - * @param string $esmtpKeyword to compare with - * - * @return int - */ - public function getPriorityOver($esmtpKeyword) - { - return 0; - } + /** + * Returns +1, -1 or 0 according to the rules for usort(). + * + * This method is called to ensure extensions can be execute in an appropriate order. + * + * @param string $esmtpKeyword to compare with + * + * @return int + */ + public function getPriorityOver($esmtpKeyword) + { + return 0; + } - /** - * Not used. - */ - public function exposeMixinMethods() - { - return []; - } + /** + * Not used. + */ + public function exposeMixinMethods() + { + return []; + } - /** - * Not used. - */ - public function resetState() - { - } + /** + * Not used. + */ + public function resetState() + { + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/SmtpUtf8Handler.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/SmtpUtf8Handler.php index 7d0252a01bf..e9b4b69ea6a 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/SmtpUtf8Handler.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/SmtpUtf8Handler.php @@ -23,85 +23,85 @@ */ class Swift_Transport_Esmtp_SmtpUtf8Handler implements Swift_Transport_EsmtpHandler { - public function __construct() - { - } + public function __construct() + { + } - /** - * Get the name of the ESMTP extension this handles. - * - * @return string - */ - public function getHandledKeyword() - { - return 'SMTPUTF8'; - } + /** + * Get the name of the ESMTP extension this handles. + * + * @return string + */ + public function getHandledKeyword() + { + return 'SMTPUTF8'; + } - /** - * Not used. - */ - public function setKeywordParams(array $parameters) - { - } + /** + * Not used. + */ + public function setKeywordParams(array $parameters) + { + } - /** - * Not used. - */ - public function afterEhlo(Swift_Transport_SmtpAgent $agent) - { - } + /** + * Not used. + */ + public function afterEhlo(Swift_Transport_SmtpAgent $agent) + { + } - /** - * Get params which are appended to MAIL FROM:<>. - * - * @return string[] - */ - public function getMailParams() - { - return ['SMTPUTF8']; - } + /** + * Get params which are appended to MAIL FROM:<>. + * + * @return string[] + */ + public function getMailParams() + { + return ['SMTPUTF8']; + } - /** - * Not used. - */ - public function getRcptParams() - { - return []; - } + /** + * Not used. + */ + public function getRcptParams() + { + return []; + } - /** - * Not used. - */ - public function onCommand(Swift_Transport_SmtpAgent $agent, $command, $codes = [], &$failedRecipients = null, &$stop = false) - { - } + /** + * Not used. + */ + public function onCommand(Swift_Transport_SmtpAgent $agent, $command, $codes = [], &$failedRecipients = null, &$stop = false) + { + } - /** - * Returns +1, -1 or 0 according to the rules for usort(). - * - * This method is called to ensure extensions can be execute in an appropriate order. - * - * @param string $esmtpKeyword to compare with - * - * @return int - */ - public function getPriorityOver($esmtpKeyword) - { - return 0; - } + /** + * Returns +1, -1 or 0 according to the rules for usort(). + * + * This method is called to ensure extensions can be execute in an appropriate order. + * + * @param string $esmtpKeyword to compare with + * + * @return int + */ + public function getPriorityOver($esmtpKeyword) + { + return 0; + } - /** - * Not used. - */ - public function exposeMixinMethods() - { - return []; - } + /** + * Not used. + */ + public function exposeMixinMethods() + { + return []; + } - /** - * Not used. - */ - public function resetState() - { - } + /** + * Not used. + */ + public function resetState() + { + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/EsmtpHandler.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/EsmtpHandler.php index b8ea36e2fa8..7dad692f12a 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/EsmtpHandler.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/EsmtpHandler.php @@ -15,72 +15,72 @@ */ interface Swift_Transport_EsmtpHandler { - /** - * Get the name of the ESMTP extension this handles. - * - * @return string - */ - public function getHandledKeyword(); + /** + * Get the name of the ESMTP extension this handles. + * + * @return string + */ + public function getHandledKeyword(); - /** - * Set the parameters which the EHLO greeting indicated. - * - * @param string[] $parameters - */ - public function setKeywordParams(array $parameters); + /** + * Set the parameters which the EHLO greeting indicated. + * + * @param string[] $parameters + */ + public function setKeywordParams(array $parameters); - /** - * Runs immediately after a EHLO has been issued. - * - * @param Swift_Transport_SmtpAgent $agent to read/write - */ - public function afterEhlo(Swift_Transport_SmtpAgent $agent); + /** + * Runs immediately after a EHLO has been issued. + * + * @param Swift_Transport_SmtpAgent $agent to read/write + */ + public function afterEhlo(Swift_Transport_SmtpAgent $agent); - /** - * Get params which are appended to MAIL FROM:<>. - * - * @return string[] - */ - public function getMailParams(); + /** + * Get params which are appended to MAIL FROM:<>. + * + * @return string[] + */ + public function getMailParams(); - /** - * Get params which are appended to RCPT TO:<>. - * - * @return string[] - */ - public function getRcptParams(); + /** + * Get params which are appended to RCPT TO:<>. + * + * @return string[] + */ + public function getRcptParams(); - /** - * Runs when a command is due to be sent. - * - * @param Swift_Transport_SmtpAgent $agent to read/write - * @param string $command to send - * @param int[] $codes expected in response - * @param string[] $failedRecipients to collect failures - * @param bool $stop to be set true by-reference if the command is now sent - */ - public function onCommand(Swift_Transport_SmtpAgent $agent, $command, $codes = [], &$failedRecipients = null, &$stop = false); + /** + * Runs when a command is due to be sent. + * + * @param Swift_Transport_SmtpAgent $agent to read/write + * @param string $command to send + * @param int[] $codes expected in response + * @param string[] $failedRecipients to collect failures + * @param bool $stop to be set true by-reference if the command is now sent + */ + public function onCommand(Swift_Transport_SmtpAgent $agent, $command, $codes = [], &$failedRecipients = null, &$stop = false); - /** - * Returns +1, -1 or 0 according to the rules for usort(). - * - * This method is called to ensure extensions can be execute in an appropriate order. - * - * @param string $esmtpKeyword to compare with - * - * @return int - */ - public function getPriorityOver($esmtpKeyword); + /** + * Returns +1, -1 or 0 according to the rules for usort(). + * + * This method is called to ensure extensions can be execute in an appropriate order. + * + * @param string $esmtpKeyword to compare with + * + * @return int + */ + public function getPriorityOver($esmtpKeyword); - /** - * Returns an array of method names which are exposed to the Esmtp class. - * - * @return string[] - */ - public function exposeMixinMethods(); + /** + * Returns an array of method names which are exposed to the Esmtp class. + * + * @return string[] + */ + public function exposeMixinMethods(); - /** - * Tells this handler to clear any buffers and reset its state. - */ - public function resetState(); + /** + * Tells this handler to clear any buffers and reset its state. + */ + public function resetState(); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/EsmtpTransport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/EsmtpTransport.php index 36545f51feb..281337ee855 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/EsmtpTransport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/EsmtpTransport.php @@ -15,432 +15,432 @@ */ class Swift_Transport_EsmtpTransport extends Swift_Transport_AbstractSmtpTransport implements Swift_Transport_SmtpAgent { - /** - * ESMTP extension handlers. - * - * @var Swift_Transport_EsmtpHandler[] - */ - private $handlers = []; + /** + * ESMTP extension handlers. + * + * @var Swift_Transport_EsmtpHandler[] + */ + private $handlers = []; - /** - * ESMTP capabilities. - * - * @var string[] - */ - private $capabilities = []; + /** + * ESMTP capabilities. + * + * @var string[] + */ + private $capabilities = []; - /** - * Connection buffer parameters. - * - * @var array - */ - private $params = [ - 'protocol' => 'tcp', - 'host' => 'localhost', - 'port' => 25, - 'timeout' => 30, - 'blocking' => 1, - 'tls' => false, - 'type' => Swift_Transport_IoBuffer::TYPE_SOCKET, - 'stream_context_options' => [], - ]; + /** + * Connection buffer parameters. + * + * @var array + */ + private $params = [ + 'protocol' => 'tcp', + 'host' => 'localhost', + 'port' => 25, + 'timeout' => 30, + 'blocking' => 1, + 'tls' => false, + 'type' => Swift_Transport_IoBuffer::TYPE_SOCKET, + 'stream_context_options' => [], + ]; - /** - * Creates a new EsmtpTransport using the given I/O buffer. - * - * @param Swift_Transport_EsmtpHandler[] $extensionHandlers - * @param string $localDomain - */ - public function __construct(Swift_Transport_IoBuffer $buf, array $extensionHandlers, Swift_Events_EventDispatcher $dispatcher, $localDomain = '127.0.0.1', Swift_AddressEncoder $addressEncoder = null) - { - parent::__construct($buf, $dispatcher, $localDomain, $addressEncoder); - $this->setExtensionHandlers($extensionHandlers); - } + /** + * Creates a new EsmtpTransport using the given I/O buffer. + * + * @param Swift_Transport_EsmtpHandler[] $extensionHandlers + * @param string $localDomain + */ + public function __construct(Swift_Transport_IoBuffer $buf, array $extensionHandlers, Swift_Events_EventDispatcher $dispatcher, $localDomain = '127.0.0.1', Swift_AddressEncoder $addressEncoder = null) + { + parent::__construct($buf, $dispatcher, $localDomain, $addressEncoder); + $this->setExtensionHandlers($extensionHandlers); + } - /** - * Set the host to connect to. - * - * Literal IPv6 addresses should be wrapped in square brackets. - * - * @param string $host - * - * @return $this - */ - public function setHost($host) - { - $this->params['host'] = $host; + /** + * Set the host to connect to. + * + * Literal IPv6 addresses should be wrapped in square brackets. + * + * @param string $host + * + * @return $this + */ + public function setHost($host) + { + $this->params['host'] = $host; - return $this; - } + return $this; + } - /** - * Get the host to connect to. - * - * @return string - */ - public function getHost() - { - return $this->params['host']; - } + /** + * Get the host to connect to. + * + * @return string + */ + public function getHost() + { + return $this->params['host']; + } - /** - * Set the port to connect to. - * - * @param int $port - * - * @return $this - */ - public function setPort($port) - { - $this->params['port'] = (int) $port; + /** + * Set the port to connect to. + * + * @param int $port + * + * @return $this + */ + public function setPort($port) + { + $this->params['port'] = (int) $port; - return $this; - } + return $this; + } - /** - * Get the port to connect to. - * - * @return int - */ - public function getPort() - { - return $this->params['port']; - } + /** + * Get the port to connect to. + * + * @return int + */ + public function getPort() + { + return $this->params['port']; + } - /** - * Set the connection timeout. - * - * @param int $timeout seconds - * - * @return $this - */ - public function setTimeout($timeout) - { - $this->params['timeout'] = (int) $timeout; - $this->buffer->setParam('timeout', (int) $timeout); + /** + * Set the connection timeout. + * + * @param int $timeout seconds + * + * @return $this + */ + public function setTimeout($timeout) + { + $this->params['timeout'] = (int) $timeout; + $this->buffer->setParam('timeout', (int) $timeout); - return $this; - } + return $this; + } - /** - * Get the connection timeout. - * - * @return int - */ - public function getTimeout() - { - return $this->params['timeout']; - } + /** + * Get the connection timeout. + * + * @return int + */ + public function getTimeout() + { + return $this->params['timeout']; + } - /** - * Set the encryption type (tls or ssl). - * - * @param string $encryption - * - * @return $this - */ - public function setEncryption($encryption) - { - $encryption = strtolower($encryption ?? ''); - if ('tls' == $encryption) { - $this->params['protocol'] = 'tcp'; - $this->params['tls'] = true; - } else { - $this->params['protocol'] = $encryption; - $this->params['tls'] = false; - } + /** + * Set the encryption type (tls or ssl). + * + * @param string $encryption + * + * @return $this + */ + public function setEncryption($encryption) + { + $encryption = strtolower($encryption ?? ''); + if ('tls' == $encryption) { + $this->params['protocol'] = 'tcp'; + $this->params['tls'] = true; + } else { + $this->params['protocol'] = $encryption; + $this->params['tls'] = false; + } - return $this; - } + return $this; + } - /** - * Get the encryption type. - * - * @return string - */ - public function getEncryption() - { - return $this->params['tls'] ? 'tls' : $this->params['protocol']; - } + /** + * Get the encryption type. + * + * @return string + */ + public function getEncryption() + { + return $this->params['tls'] ? 'tls' : $this->params['protocol']; + } - /** - * Sets the stream context options. - * - * @param array $options - * - * @return $this - */ - public function setStreamOptions($options) - { - $this->params['stream_context_options'] = $options; + /** + * Sets the stream context options. + * + * @param array $options + * + * @return $this + */ + public function setStreamOptions($options) + { + $this->params['stream_context_options'] = $options; - return $this; - } + return $this; + } - /** - * Returns the stream context options. - * - * @return array - */ - public function getStreamOptions() - { - return $this->params['stream_context_options']; - } + /** + * Returns the stream context options. + * + * @return array + */ + public function getStreamOptions() + { + return $this->params['stream_context_options']; + } - /** - * Sets the source IP. - * - * IPv6 addresses should be wrapped in square brackets. - * - * @param string $source - * - * @return $this - */ - public function setSourceIp($source) - { - $this->params['sourceIp'] = $source; + /** + * Sets the source IP. + * + * IPv6 addresses should be wrapped in square brackets. + * + * @param string $source + * + * @return $this + */ + public function setSourceIp($source) + { + $this->params['sourceIp'] = $source; - return $this; - } + return $this; + } - /** - * Returns the IP used to connect to the destination. - * - * @return string - */ - public function getSourceIp() - { - return $this->params['sourceIp'] ?? null; - } + /** + * Returns the IP used to connect to the destination. + * + * @return string + */ + public function getSourceIp() + { + return $this->params['sourceIp'] ?? null; + } - /** - * Sets whether SMTP pipelining is enabled. - * - * By default, support is auto-detected using the PIPELINING SMTP extension. - * Use this function to override that in the unlikely event of compatibility - * issues. - * - * @param bool $enabled - * - * @return $this - */ - public function setPipelining($enabled) - { - $this->pipelining = $enabled; + /** + * Sets whether SMTP pipelining is enabled. + * + * By default, support is auto-detected using the PIPELINING SMTP extension. + * Use this function to override that in the unlikely event of compatibility + * issues. + * + * @param bool $enabled + * + * @return $this + */ + public function setPipelining($enabled) + { + $this->pipelining = $enabled; - return $this; - } + return $this; + } - /** - * Returns whether SMTP pipelining is enabled. - * - * @return bool|null a boolean if pipelining is explicitly enabled or disabled, - * or null if support is auto-detected - */ - public function getPipelining() - { - return $this->pipelining; - } + /** + * Returns whether SMTP pipelining is enabled. + * + * @return bool|null a boolean if pipelining is explicitly enabled or disabled, + * or null if support is auto-detected + */ + public function getPipelining() + { + return $this->pipelining; + } - /** - * Set ESMTP extension handlers. - * - * @param Swift_Transport_EsmtpHandler[] $handlers - * - * @return $this - */ - public function setExtensionHandlers(array $handlers) - { - $assoc = []; - foreach ($handlers as $handler) { - $assoc[$handler->getHandledKeyword()] = $handler; - } - uasort($assoc, function ($a, $b) { - return $a->getPriorityOver($b->getHandledKeyword()); - }); - $this->handlers = $assoc; - $this->setHandlerParams(); + /** + * Set ESMTP extension handlers. + * + * @param Swift_Transport_EsmtpHandler[] $handlers + * + * @return $this + */ + public function setExtensionHandlers(array $handlers) + { + $assoc = []; + foreach ($handlers as $handler) { + $assoc[$handler->getHandledKeyword()] = $handler; + } + uasort($assoc, function ($a, $b) { + return $a->getPriorityOver($b->getHandledKeyword()); + }); + $this->handlers = $assoc; + $this->setHandlerParams(); - return $this; - } + return $this; + } - /** - * Get ESMTP extension handlers. - * - * @return Swift_Transport_EsmtpHandler[] - */ - public function getExtensionHandlers() - { - return array_values($this->handlers); - } + /** + * Get ESMTP extension handlers. + * + * @return Swift_Transport_EsmtpHandler[] + */ + public function getExtensionHandlers() + { + return array_values($this->handlers); + } - /** - * Run a command against the buffer, expecting the given response codes. - * - * If no response codes are given, the response will not be validated. - * If codes are given, an exception will be thrown on an invalid response. - * - * @param string $command - * @param int[] $codes - * @param string[] $failures An array of failures by-reference - * @param bool $pipeline Do not wait for response - * @param string $address the address, if command is RCPT TO - * - * @return string|null The server response, or null if pipelining is enabled - */ - public function executeCommand($command, $codes = [], &$failures = null, $pipeline = false, $address = null) - { - $failures = (array) $failures; - $stopSignal = false; - $response = null; - foreach ($this->getActiveHandlers() as $handler) { - $response = $handler->onCommand( - $this, $command, $codes, $failures, $stopSignal - ); - if ($stopSignal) { - return $response; - } - } + /** + * Run a command against the buffer, expecting the given response codes. + * + * If no response codes are given, the response will not be validated. + * If codes are given, an exception will be thrown on an invalid response. + * + * @param string $command + * @param int[] $codes + * @param string[] $failures An array of failures by-reference + * @param bool $pipeline Do not wait for response + * @param string $address the address, if command is RCPT TO + * + * @return string|null The server response, or null if pipelining is enabled + */ + public function executeCommand($command, $codes = [], &$failures = null, $pipeline = false, $address = null) + { + $failures = (array) $failures; + $stopSignal = false; + $response = null; + foreach ($this->getActiveHandlers() as $handler) { + $response = $handler->onCommand( + $this, $command, $codes, $failures, $stopSignal + ); + if ($stopSignal) { + return $response; + } + } - return parent::executeCommand($command, $codes, $failures, $pipeline, $address); - } + return parent::executeCommand($command, $codes, $failures, $pipeline, $address); + } - /** Mixin handling method for ESMTP handlers */ - public function __call($method, $args) - { - foreach ($this->handlers as $handler) { - if (\in_array(strtolower($method), - array_map('strtolower', (array) $handler->exposeMixinMethods()) - )) { - $return = \call_user_func_array([$handler, $method], $args); - // Allow fluid method calls - if (null === $return && 'set' == substr($method, 0, 3)) { - return $this; - } else { - return $return; - } - } - } - trigger_error('Call to undefined method '.$method, E_USER_ERROR); - } + /** Mixin handling method for ESMTP handlers */ + public function __call($method, $args) + { + foreach ($this->handlers as $handler) { + if (\in_array(strtolower($method), + array_map('strtolower', (array) $handler->exposeMixinMethods()) + )) { + $return = \call_user_func_array([$handler, $method], $args); + // Allow fluid method calls + if (null === $return && 'set' == substr($method, 0, 3)) { + return $this; + } else { + return $return; + } + } + } + trigger_error('Call to undefined method '.$method, E_USER_ERROR); + } - /** Get the params to initialize the buffer */ - protected function getBufferParams() - { - return $this->params; - } + /** Get the params to initialize the buffer */ + protected function getBufferParams() + { + return $this->params; + } - /** Overridden to perform EHLO instead */ - protected function doHeloCommand() - { - try { - $response = $this->executeCommand( - sprintf("EHLO %s\r\n", $this->domain), [250] - ); - } catch (Swift_TransportException $e) { - return parent::doHeloCommand(); - } + /** Overridden to perform EHLO instead */ + protected function doHeloCommand() + { + try { + $response = $this->executeCommand( + sprintf("EHLO %s\r\n", $this->domain), [250] + ); + } catch (Swift_TransportException $e) { + return parent::doHeloCommand(); + } - if ($this->params['tls']) { - try { - $this->executeCommand("STARTTLS\r\n", [220]); + if ($this->params['tls']) { + try { + $this->executeCommand("STARTTLS\r\n", [220]); - if (!$this->buffer->startTLS()) { - throw new Swift_TransportException('Unable to connect with TLS encryption'); - } + if (!$this->buffer->startTLS()) { + throw new Swift_TransportException('Unable to connect with TLS encryption'); + } - try { - $response = $this->executeCommand( - sprintf("EHLO %s\r\n", $this->domain), [250] - ); - } catch (Swift_TransportException $e) { - return parent::doHeloCommand(); - } - } catch (Swift_TransportException $e) { - $this->throwException($e); - } - } + try { + $response = $this->executeCommand( + sprintf("EHLO %s\r\n", $this->domain), [250] + ); + } catch (Swift_TransportException $e) { + return parent::doHeloCommand(); + } + } catch (Swift_TransportException $e) { + $this->throwException($e); + } + } - $this->capabilities = $this->getCapabilities($response); - if (!isset($this->pipelining)) { - $this->pipelining = isset($this->capabilities['PIPELINING']); - } + $this->capabilities = $this->getCapabilities($response); + if (!isset($this->pipelining)) { + $this->pipelining = isset($this->capabilities['PIPELINING']); + } - $this->setHandlerParams(); - foreach ($this->getActiveHandlers() as $handler) { - $handler->afterEhlo($this); - } - } + $this->setHandlerParams(); + foreach ($this->getActiveHandlers() as $handler) { + $handler->afterEhlo($this); + } + } - /** Overridden to add Extension support */ - protected function doMailFromCommand($address) - { - $address = $this->addressEncoder->encodeString($address); - $handlers = $this->getActiveHandlers(); - $params = []; - foreach ($handlers as $handler) { - $params = array_merge($params, (array) $handler->getMailParams()); - } - $paramStr = !empty($params) ? ' '.implode(' ', $params) : ''; - $this->executeCommand( - sprintf("MAIL FROM:<%s>%s\r\n", $address, $paramStr), [250], $failures, true - ); - } + /** Overridden to add Extension support */ + protected function doMailFromCommand($address) + { + $address = $this->addressEncoder->encodeString($address); + $handlers = $this->getActiveHandlers(); + $params = []; + foreach ($handlers as $handler) { + $params = array_merge($params, (array) $handler->getMailParams()); + } + $paramStr = !empty($params) ? ' '.implode(' ', $params) : ''; + $this->executeCommand( + sprintf("MAIL FROM:<%s>%s\r\n", $address, $paramStr), [250], $failures, true + ); + } - /** Overridden to add Extension support */ - protected function doRcptToCommand($address) - { - $address = $this->addressEncoder->encodeString($address); - $handlers = $this->getActiveHandlers(); - $params = []; - foreach ($handlers as $handler) { - $params = array_merge($params, (array) $handler->getRcptParams()); - } - $paramStr = !empty($params) ? ' '.implode(' ', $params) : ''; - $this->executeCommand( - sprintf("RCPT TO:<%s>%s\r\n", $address, $paramStr), [250, 251, 252], $failures, true, $address - ); - } + /** Overridden to add Extension support */ + protected function doRcptToCommand($address) + { + $address = $this->addressEncoder->encodeString($address); + $handlers = $this->getActiveHandlers(); + $params = []; + foreach ($handlers as $handler) { + $params = array_merge($params, (array) $handler->getRcptParams()); + } + $paramStr = !empty($params) ? ' '.implode(' ', $params) : ''; + $this->executeCommand( + sprintf("RCPT TO:<%s>%s\r\n", $address, $paramStr), [250, 251, 252], $failures, true, $address + ); + } - /** Determine ESMTP capabilities by function group */ - private function getCapabilities($ehloResponse) - { - $capabilities = []; - $ehloResponse = trim($ehloResponse ?? ''); - $lines = explode("\r\n", $ehloResponse); - array_shift($lines); - foreach ($lines as $line) { - if (preg_match('/^[0-9]{3}[ -]([A-Z0-9-]+)((?:[ =].*)?)$/Di', $line, $matches)) { - $keyword = strtoupper($matches[1]); - $paramStr = strtoupper(ltrim($matches[2], ' =')); - $params = !empty($paramStr) ? explode(' ', $paramStr) : []; - $capabilities[$keyword] = $params; - } - } + /** Determine ESMTP capabilities by function group */ + private function getCapabilities($ehloResponse) + { + $capabilities = []; + $ehloResponse = trim($ehloResponse ?? ''); + $lines = explode("\r\n", $ehloResponse); + array_shift($lines); + foreach ($lines as $line) { + if (preg_match('/^[0-9]{3}[ -]([A-Z0-9-]+)((?:[ =].*)?)$/Di', $line, $matches)) { + $keyword = strtoupper($matches[1]); + $paramStr = strtoupper(ltrim($matches[2], ' =')); + $params = !empty($paramStr) ? explode(' ', $paramStr) : []; + $capabilities[$keyword] = $params; + } + } - return $capabilities; - } + return $capabilities; + } - /** Set parameters which are used by each extension handler */ - private function setHandlerParams() - { - foreach ($this->handlers as $keyword => $handler) { - if (\array_key_exists($keyword, $this->capabilities)) { - $handler->setKeywordParams($this->capabilities[$keyword]); - } - } - } + /** Set parameters which are used by each extension handler */ + private function setHandlerParams() + { + foreach ($this->handlers as $keyword => $handler) { + if (\array_key_exists($keyword, $this->capabilities)) { + $handler->setKeywordParams($this->capabilities[$keyword]); + } + } + } - /** Get ESMTP handlers which are currently ok to use */ - private function getActiveHandlers() - { - $handlers = []; - foreach ($this->handlers as $keyword => $handler) { - if (\array_key_exists($keyword, $this->capabilities)) { - $handlers[] = $handler; - } - } + /** Get ESMTP handlers which are currently ok to use */ + private function getActiveHandlers() + { + $handlers = []; + foreach ($this->handlers as $keyword => $handler) { + if (\array_key_exists($keyword, $this->capabilities)) { + $handlers[] = $handler; + } + } - return $handlers; - } + return $handlers; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/FailoverTransport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/FailoverTransport.php index 1a4b4754f07..1e007b00201 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/FailoverTransport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/FailoverTransport.php @@ -15,89 +15,89 @@ */ class Swift_Transport_FailoverTransport extends Swift_Transport_LoadBalancedTransport { - /** - * Registered transport currently used. - * - * @var Swift_Transport - */ - private $currentTransport; + /** + * Registered transport currently used. + * + * @var Swift_Transport + */ + private $currentTransport; - // needed as __construct is called from elsewhere explicitly - public function __construct() - { - parent::__construct(); - } + // needed as __construct is called from elsewhere explicitly + public function __construct() + { + parent::__construct(); + } - /** - * {@inheritdoc} - */ - public function ping() - { - $maxTransports = \count($this->transports); - for ($i = 0; $i < $maxTransports - && $transport = $this->getNextTransport(); ++$i) { - if ($transport->ping()) { - return true; - } else { - $this->killCurrentTransport(); - } - } + /** + * {@inheritdoc} + */ + public function ping() + { + $maxTransports = \count($this->transports); + for ($i = 0; $i < $maxTransports + && $transport = $this->getNextTransport(); ++$i) { + if ($transport->ping()) { + return true; + } else { + $this->killCurrentTransport(); + } + } - return \count($this->transports) > 0; - } + return \count($this->transports) > 0; + } - /** - * Send the given Message. - * - * Recipient/sender data will be retrieved from the Message API. - * The return value is the number of recipients who were accepted for delivery. - * - * @param string[] $failedRecipients An array of failures by-reference - * - * @return int - */ - public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) - { - $maxTransports = \count($this->transports); - $sent = 0; - $this->lastUsedTransport = null; + /** + * Send the given Message. + * + * Recipient/sender data will be retrieved from the Message API. + * The return value is the number of recipients who were accepted for delivery. + * + * @param string[] $failedRecipients An array of failures by-reference + * + * @return int + */ + public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) + { + $maxTransports = \count($this->transports); + $sent = 0; + $this->lastUsedTransport = null; - for ($i = 0; $i < $maxTransports - && $transport = $this->getNextTransport(); ++$i) { - try { - if (!$transport->isStarted()) { - $transport->start(); - } + for ($i = 0; $i < $maxTransports + && $transport = $this->getNextTransport(); ++$i) { + try { + if (!$transport->isStarted()) { + $transport->start(); + } - if ($sent = $transport->send($message, $failedRecipients)) { - $this->lastUsedTransport = $transport; + if ($sent = $transport->send($message, $failedRecipients)) { + $this->lastUsedTransport = $transport; - return $sent; - } - } catch (Swift_TransportException $e) { - $this->killCurrentTransport(); - } - } + return $sent; + } + } catch (Swift_TransportException $e) { + $this->killCurrentTransport(); + } + } - if (0 == \count($this->transports)) { - throw new Swift_TransportException('All Transports in FailoverTransport failed, or no Transports available'); - } + if (0 == \count($this->transports)) { + throw new Swift_TransportException('All Transports in FailoverTransport failed, or no Transports available'); + } - return $sent; - } + return $sent; + } - protected function getNextTransport() - { - if (!isset($this->currentTransport)) { - $this->currentTransport = parent::getNextTransport(); - } + protected function getNextTransport() + { + if (!isset($this->currentTransport)) { + $this->currentTransport = parent::getNextTransport(); + } - return $this->currentTransport; - } + return $this->currentTransport; + } - protected function killCurrentTransport() - { - $this->currentTransport = null; - parent::killCurrentTransport(); - } + protected function killCurrentTransport() + { + $this->currentTransport = null; + parent::killCurrentTransport(); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/IoBuffer.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/IoBuffer.php index 50f1e5e403c..799ad8ae085 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/IoBuffer.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/IoBuffer.php @@ -15,51 +15,51 @@ */ interface Swift_Transport_IoBuffer extends Swift_InputByteStream, Swift_OutputByteStream { - /** A socket buffer over TCP */ - const TYPE_SOCKET = 0x0001; + /** A socket buffer over TCP */ + const TYPE_SOCKET = 0x0001; - /** A process buffer with I/O support */ - const TYPE_PROCESS = 0x0010; + /** A process buffer with I/O support */ + const TYPE_PROCESS = 0x0010; - /** - * Perform any initialization needed, using the given $params. - * - * Parameters will vary depending upon the type of IoBuffer used. - */ - public function initialize(array $params); + /** + * Perform any initialization needed, using the given $params. + * + * Parameters will vary depending upon the type of IoBuffer used. + */ + public function initialize(array $params); - /** - * Set an individual param on the buffer (e.g. switching to SSL). - * - * @param string $param - * @param mixed $value - */ - public function setParam($param, $value); + /** + * Set an individual param on the buffer (e.g. switching to SSL). + * + * @param string $param + * @param mixed $value + */ + public function setParam($param, $value); - /** - * Perform any shutdown logic needed. - */ - public function terminate(); + /** + * Perform any shutdown logic needed. + */ + public function terminate(); - /** - * Set an array of string replacements which should be made on data written - * to the buffer. - * - * This could replace LF with CRLF for example. - * - * @param string[] $replacements - */ - public function setWriteTranslations(array $replacements); + /** + * Set an array of string replacements which should be made on data written + * to the buffer. + * + * This could replace LF with CRLF for example. + * + * @param string[] $replacements + */ + public function setWriteTranslations(array $replacements); - /** - * Get a line of output (including any CRLF). - * - * The $sequence number comes from any writes and may or may not be used - * depending upon the implementation. - * - * @param int $sequence of last write to scan from - * - * @return string - */ - public function readLine($sequence); + /** + * Get a line of output (including any CRLF). + * + * The $sequence number comes from any writes and may or may not be used + * depending upon the implementation. + * + * @param int $sequence of last write to scan from + * + * @return string + */ + public function readLine($sequence); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/LoadBalancedTransport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/LoadBalancedTransport.php index 0b5ba9d304e..e4262069ffb 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/LoadBalancedTransport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/LoadBalancedTransport.php @@ -15,178 +15,178 @@ */ class Swift_Transport_LoadBalancedTransport implements Swift_Transport { - /** - * Transports which are deemed useless. - * - * @var Swift_Transport[] - */ - private $deadTransports = []; + /** + * Transports which are deemed useless. + * + * @var Swift_Transport[] + */ + private $deadTransports = []; - /** - * The Transports which are used in rotation. - * - * @var Swift_Transport[] - */ - protected $transports = []; + /** + * The Transports which are used in rotation. + * + * @var Swift_Transport[] + */ + protected $transports = []; - /** - * The Transport used in the last successful send operation. - * - * @var Swift_Transport - */ - protected $lastUsedTransport = null; + /** + * The Transport used in the last successful send operation. + * + * @var Swift_Transport + */ + protected $lastUsedTransport = null; - // needed as __construct is called from elsewhere explicitly - public function __construct() - { - } + // needed as __construct is called from elsewhere explicitly + public function __construct() + { + } - /** - * Set $transports to delegate to. - * - * @param Swift_Transport[] $transports - */ - public function setTransports(array $transports) - { - $this->transports = $transports; - $this->deadTransports = []; - } + /** + * Set $transports to delegate to. + * + * @param Swift_Transport[] $transports + */ + public function setTransports(array $transports) + { + $this->transports = $transports; + $this->deadTransports = []; + } - /** - * Get $transports to delegate to. - * - * @return Swift_Transport[] - */ - public function getTransports() - { - return array_merge($this->transports, $this->deadTransports); - } + /** + * Get $transports to delegate to. + * + * @return Swift_Transport[] + */ + public function getTransports() + { + return array_merge($this->transports, $this->deadTransports); + } - /** - * Get the Transport used in the last successful send operation. - * - * @return Swift_Transport - */ - public function getLastUsedTransport() - { - return $this->lastUsedTransport; - } + /** + * Get the Transport used in the last successful send operation. + * + * @return Swift_Transport + */ + public function getLastUsedTransport() + { + return $this->lastUsedTransport; + } - /** - * Test if this Transport mechanism has started. - * - * @return bool - */ - public function isStarted() - { - return \count($this->transports) > 0; - } + /** + * Test if this Transport mechanism has started. + * + * @return bool + */ + public function isStarted() + { + return \count($this->transports) > 0; + } - /** - * Start this Transport mechanism. - */ - public function start() - { - $this->transports = array_merge($this->transports, $this->deadTransports); - } + /** + * Start this Transport mechanism. + */ + public function start() + { + $this->transports = array_merge($this->transports, $this->deadTransports); + } - /** - * Stop this Transport mechanism. - */ - public function stop() - { - foreach ($this->transports as $transport) { - $transport->stop(); - } - } + /** + * Stop this Transport mechanism. + */ + public function stop() + { + foreach ($this->transports as $transport) { + $transport->stop(); + } + } - /** - * {@inheritdoc} - */ - public function ping() - { - foreach ($this->transports as $transport) { - if (!$transport->ping()) { - $this->killCurrentTransport(); - } - } + /** + * {@inheritdoc} + */ + public function ping() + { + foreach ($this->transports as $transport) { + if (!$transport->ping()) { + $this->killCurrentTransport(); + } + } - return \count($this->transports) > 0; - } + return \count($this->transports) > 0; + } - /** - * Send the given Message. - * - * Recipient/sender data will be retrieved from the Message API. - * The return value is the number of recipients who were accepted for delivery. - * - * @param string[] $failedRecipients An array of failures by-reference - * - * @return int - */ - public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) - { - $maxTransports = \count($this->transports); - $sent = 0; - $this->lastUsedTransport = null; + /** + * Send the given Message. + * + * Recipient/sender data will be retrieved from the Message API. + * The return value is the number of recipients who were accepted for delivery. + * + * @param string[] $failedRecipients An array of failures by-reference + * + * @return int + */ + public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) + { + $maxTransports = \count($this->transports); + $sent = 0; + $this->lastUsedTransport = null; - for ($i = 0; $i < $maxTransports - && $transport = $this->getNextTransport(); ++$i) { - try { - if (!$transport->isStarted()) { - $transport->start(); - } - if ($sent = $transport->send($message, $failedRecipients)) { - $this->lastUsedTransport = $transport; - break; - } - } catch (Swift_TransportException $e) { - $this->killCurrentTransport(); - } - } + for ($i = 0; $i < $maxTransports + && $transport = $this->getNextTransport(); ++$i) { + try { + if (!$transport->isStarted()) { + $transport->start(); + } + if ($sent = $transport->send($message, $failedRecipients)) { + $this->lastUsedTransport = $transport; + break; + } + } catch (Swift_TransportException $e) { + $this->killCurrentTransport(); + } + } - if (0 == \count($this->transports)) { - throw new Swift_TransportException('All Transports in LoadBalancedTransport failed, or no Transports available'); - } + if (0 == \count($this->transports)) { + throw new Swift_TransportException('All Transports in LoadBalancedTransport failed, or no Transports available'); + } - return $sent; - } + return $sent; + } - /** - * Register a plugin. - */ - public function registerPlugin(Swift_Events_EventListener $plugin) - { - foreach ($this->transports as $transport) { - $transport->registerPlugin($plugin); - } - } + /** + * Register a plugin. + */ + public function registerPlugin(Swift_Events_EventListener $plugin) + { + foreach ($this->transports as $transport) { + $transport->registerPlugin($plugin); + } + } - /** - * Rotates the transport list around and returns the first instance. - * - * @return Swift_Transport - */ - protected function getNextTransport() - { - if ($next = array_shift($this->transports)) { - $this->transports[] = $next; - } + /** + * Rotates the transport list around and returns the first instance. + * + * @return Swift_Transport + */ + protected function getNextTransport() + { + if ($next = array_shift($this->transports)) { + $this->transports[] = $next; + } - return $next; - } + return $next; + } - /** - * Tag the currently used (top of stack) transport as dead/useless. - */ - protected function killCurrentTransport() - { - if ($transport = array_pop($this->transports)) { - try { - $transport->stop(); - } catch (Exception $e) { - } - $this->deadTransports[] = $transport; - } - } + /** + * Tag the currently used (top of stack) transport as dead/useless. + */ + protected function killCurrentTransport() + { + if ($transport = array_pop($this->transports)) { + try { + $transport->stop(); + } catch (Exception $e) { + } + $this->deadTransports[] = $transport; + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/NullTransport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/NullTransport.php index 7d910db5a58..ec82fced23b 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/NullTransport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/NullTransport.php @@ -15,84 +15,84 @@ */ class Swift_Transport_NullTransport implements Swift_Transport { - /** The event dispatcher from the plugin API */ - private $eventDispatcher; + /** The event dispatcher from the plugin API */ + private $eventDispatcher; - /** - * Constructor. - */ - public function __construct(Swift_Events_EventDispatcher $eventDispatcher) - { - $this->eventDispatcher = $eventDispatcher; - } + /** + * Constructor. + */ + public function __construct(Swift_Events_EventDispatcher $eventDispatcher) + { + $this->eventDispatcher = $eventDispatcher; + } - /** - * Tests if this Transport mechanism has started. - * - * @return bool - */ - public function isStarted() - { - return true; - } + /** + * Tests if this Transport mechanism has started. + * + * @return bool + */ + public function isStarted() + { + return true; + } - /** - * Starts this Transport mechanism. - */ - public function start() - { - } + /** + * Starts this Transport mechanism. + */ + public function start() + { + } - /** - * Stops this Transport mechanism. - */ - public function stop() - { - } + /** + * Stops this Transport mechanism. + */ + public function stop() + { + } - /** - * {@inheritdoc} - */ - public function ping() - { - return true; - } + /** + * {@inheritdoc} + */ + public function ping() + { + return true; + } - /** - * Sends the given message. - * - * @param string[] $failedRecipients An array of failures by-reference - * - * @return int The number of sent emails - */ - public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) - { - if ($evt = $this->eventDispatcher->createSendEvent($this, $message)) { - $this->eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed'); - if ($evt->bubbleCancelled()) { - return 0; - } - } + /** + * Sends the given message. + * + * @param string[] $failedRecipients An array of failures by-reference + * + * @return int The number of sent emails + */ + public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) + { + if ($evt = $this->eventDispatcher->createSendEvent($this, $message)) { + $this->eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed'); + if ($evt->bubbleCancelled()) { + return 0; + } + } - if ($evt) { - $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS); - $this->eventDispatcher->dispatchEvent($evt, 'sendPerformed'); - } + if ($evt) { + $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS); + $this->eventDispatcher->dispatchEvent($evt, 'sendPerformed'); + } - $count = ( - \count((array) $message->getTo()) - + \count((array) $message->getCc()) - + \count((array) $message->getBcc()) - ); + $count = ( + \count((array) $message->getTo()) + + \count((array) $message->getCc()) + + \count((array) $message->getBcc()) + ); - return $count; - } + return $count; + } - /** - * Register a plugin. - */ - public function registerPlugin(Swift_Events_EventListener $plugin) - { - $this->eventDispatcher->bindEventListener($plugin); - } + /** + * Register a plugin. + */ + public function registerPlugin(Swift_Events_EventListener $plugin) + { + $this->eventDispatcher->bindEventListener($plugin); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/SendmailTransport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/SendmailTransport.php index 65a434d1173..e1723b24f10 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/SendmailTransport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/SendmailTransport.php @@ -19,140 +19,139 @@ */ class Swift_Transport_SendmailTransport extends Swift_Transport_AbstractSmtpTransport { - /** - * Connection buffer parameters. - * - * @var array - */ - private $params = [ - 'timeout' => 30, - 'blocking' => 1, - 'command' => '/usr/sbin/sendmail -bs', - 'type' => Swift_Transport_IoBuffer::TYPE_PROCESS, - ]; + /** + * Connection buffer parameters. + * + * @var array + */ + private $params = [ + 'timeout' => 30, + 'blocking' => 1, + 'command' => '/usr/sbin/sendmail -bs', + 'type' => Swift_Transport_IoBuffer::TYPE_PROCESS, + ]; - /** - * Create a new SendmailTransport with $buf for I/O. - * - * @param string $localDomain - */ - public function __construct(Swift_Transport_IoBuffer $buf, Swift_Events_EventDispatcher $dispatcher, $localDomain = '127.0.0.1', Swift_AddressEncoder $addressEncoder = null) - { - parent::__construct($buf, $dispatcher, $localDomain, $addressEncoder); - } + /** + * Create a new SendmailTransport with $buf for I/O. + * + * @param string $localDomain + */ + public function __construct(Swift_Transport_IoBuffer $buf, Swift_Events_EventDispatcher $dispatcher, $localDomain = '127.0.0.1', Swift_AddressEncoder $addressEncoder = null) + { + parent::__construct($buf, $dispatcher, $localDomain, $addressEncoder); + } - /** - * Start the standalone SMTP session if running in -bs mode. - */ - public function start() - { - if (false !== strpos($this->getCommand(), ' -bs')) { - parent::start(); - } - } + /** + * Start the standalone SMTP session if running in -bs mode. + */ + public function start() + { + if (false !== strpos($this->getCommand(), ' -bs')) { + parent::start(); + } + } - /** - * Set the command to invoke. - * - * If using -t mode you are strongly advised to include -oi or -i in the flags. - * For example: /usr/sbin/sendmail -oi -t - * Swift will append a -f flag if one is not present. - * - * The recommended mode is "-bs" since it is interactive and failure notifications - * are hence possible. - * - * @param string $command - * - * @return $this - */ - public function setCommand($command) - { - $this->params['command'] = $command; + /** + * Set the command to invoke. + * + * If using -t mode you are strongly advised to include -oi or -i in the flags. + * For example: /usr/sbin/sendmail -oi -t + * Swift will append a -f flag if one is not present. + * + * The recommended mode is "-bs" since it is interactive and failure notifications + * are hence possible. + * + * @param string $command + * + * @return $this + */ + public function setCommand($command) + { + $this->params['command'] = $command; - return $this; - } + return $this; + } - /** - * Get the sendmail command which will be invoked. - * - * @return string - */ - public function getCommand() - { - return $this->params['command']; - } + /** + * Get the sendmail command which will be invoked. + * + * @return string + */ + public function getCommand() + { + return $this->params['command']; + } - /** - * Send the given Message. - * - * Recipient/sender data will be retrieved from the Message API. - * - * The return value is the number of recipients who were accepted for delivery. - * NOTE: If using 'sendmail -t' you will not be aware of any failures until - * they bounce (i.e. send() will always return 100% success). - * - * @param string[] $failedRecipients An array of failures by-reference - * - * @return int - */ - public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) - { - $failedRecipients = (array) $failedRecipients; - $command = $this->getCommand(); - $buffer = $this->getBuffer(); - $count = 0; + /** + * Send the given Message. + * + * Recipient/sender data will be retrieved from the Message API. + * + * The return value is the number of recipients who were accepted for delivery. + * NOTE: If using 'sendmail -t' you will not be aware of any failures until + * they bounce (i.e. send() will always return 100% success). + * + * @param string[] $failedRecipients An array of failures by-reference + * + * @return int + */ + public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) + { + $failedRecipients = (array) $failedRecipients; + $command = $this->getCommand(); + $buffer = $this->getBuffer(); + $count = 0; - if (false !== strpos($command, ' -t')) { - if ($evt = $this->eventDispatcher->createSendEvent($this, $message)) { - $this->eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed'); - if ($evt->bubbleCancelled()) { - return 0; - } - } + if (false !== strpos($command, ' -t')) { + if ($evt = $this->eventDispatcher->createSendEvent($this, $message)) { + $this->eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed'); + if ($evt->bubbleCancelled()) { + return 0; + } + } - if (false === strpos($command, ' -f')) { - $command .= ' -f'.escapeshellarg($this->getReversePath($message) ?? ''); - } + if (false === strpos($command, ' -f')) { + $command .= ' -f'.escapeshellarg($this->getReversePath($message) ?? ''); + } - $buffer->initialize(array_merge($this->params, ['command' => $command])); + $buffer->initialize(array_merge($this->params, ['command' => $command])); - if (false === strpos($command, ' -i') && false === strpos($command, ' -oi')) { - $buffer->setWriteTranslations(["\r\n" => "\n", "\n." => "\n.."]); - } else { - $buffer->setWriteTranslations(["\r\n" => "\n"]); - } + if (false === strpos($command, ' -i') && false === strpos($command, ' -oi')) { + $buffer->setWriteTranslations(["\r\n" => "\n", "\n." => "\n.."]); + } else { + $buffer->setWriteTranslations(["\r\n" => "\n"]); + } - $count = \count((array) $message->getTo()) - + \count((array) $message->getCc()) - + \count((array) $message->getBcc()) - ; - $message->toByteStream($buffer); - $buffer->flushBuffers(); - $buffer->setWriteTranslations([]); - $buffer->terminate(); + $count = \count((array) $message->getTo()) + + \count((array) $message->getCc()) + + \count((array) $message->getBcc()); + $message->toByteStream($buffer); + $buffer->flushBuffers(); + $buffer->setWriteTranslations([]); + $buffer->terminate(); - if ($evt) { - $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS); - $evt->setFailedRecipients($failedRecipients); - $this->eventDispatcher->dispatchEvent($evt, 'sendPerformed'); - } + if ($evt) { + $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS); + $evt->setFailedRecipients($failedRecipients); + $this->eventDispatcher->dispatchEvent($evt, 'sendPerformed'); + } - $message->generateId(); - } elseif (false !== strpos($command, ' -bs')) { - $count = parent::send($message, $failedRecipients); - } else { - $this->throwException(new Swift_TransportException( - 'Unsupported sendmail command flags ['.$command.']. '. - 'Must be one of "-bs" or "-t" but can include additional flags.' - )); - } + $message->generateId(); + } elseif (false !== strpos($command, ' -bs')) { + $count = parent::send($message, $failedRecipients); + } else { + $this->throwException(new Swift_TransportException( + 'Unsupported sendmail command flags ['.$command.']. '. + 'Must be one of "-bs" or "-t" but can include additional flags.' + )); + } - return $count; - } + return $count; + } - /** Get the params to initialize the buffer */ - protected function getBufferParams() - { - return $this->params; - } + /** Get the params to initialize the buffer */ + protected function getBufferParams() + { + return $this->params; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/SmtpAgent.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/SmtpAgent.php index e8ce65c2648..bb761237b1c 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/SmtpAgent.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/SmtpAgent.php @@ -15,22 +15,22 @@ */ interface Swift_Transport_SmtpAgent { - /** - * Get the IoBuffer where read/writes are occurring. - * - * @return Swift_Transport_IoBuffer - */ - public function getBuffer(); + /** + * Get the IoBuffer where read/writes are occurring. + * + * @return Swift_Transport_IoBuffer + */ + public function getBuffer(); - /** - * Run a command against the buffer, expecting the given response codes. - * - * If no response codes are given, the response will not be validated. - * If codes are given, an exception will be thrown on an invalid response. - * - * @param string $command - * @param int[] $codes - * @param string[] $failures An array of failures by-reference - */ - public function executeCommand($command, $codes = [], &$failures = null); + /** + * Run a command against the buffer, expecting the given response codes. + * + * If no response codes are given, the response will not be validated. + * If codes are given, an exception will be thrown on an invalid response. + * + * @param string $command + * @param int[] $codes + * @param string[] $failures An array of failures by-reference + */ + public function executeCommand($command, $codes = [], &$failures = null); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/SpoolTransport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/SpoolTransport.php index 0cb6a5b80a9..f7c19d05579 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/SpoolTransport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/SpoolTransport.php @@ -15,106 +15,106 @@ */ class Swift_Transport_SpoolTransport implements Swift_Transport { - /** The spool instance */ - private $spool; + /** The spool instance */ + private $spool; - /** The event dispatcher from the plugin API */ - private $eventDispatcher; + /** The event dispatcher from the plugin API */ + private $eventDispatcher; - /** - * Constructor. - */ - public function __construct(Swift_Events_EventDispatcher $eventDispatcher, Swift_Spool $spool = null) - { - $this->eventDispatcher = $eventDispatcher; - $this->spool = $spool; - } + /** + * Constructor. + */ + public function __construct(Swift_Events_EventDispatcher $eventDispatcher, Swift_Spool $spool = null) + { + $this->eventDispatcher = $eventDispatcher; + $this->spool = $spool; + } - /** - * Sets the spool object. - * - * @return $this - */ - public function setSpool(Swift_Spool $spool) - { - $this->spool = $spool; + /** + * Sets the spool object. + * + * @return $this + */ + public function setSpool(Swift_Spool $spool) + { + $this->spool = $spool; - return $this; - } + return $this; + } - /** - * Get the spool object. - * - * @return Swift_Spool - */ - public function getSpool() - { - return $this->spool; - } + /** + * Get the spool object. + * + * @return Swift_Spool + */ + public function getSpool() + { + return $this->spool; + } - /** - * Tests if this Transport mechanism has started. - * - * @return bool - */ - public function isStarted() - { - return true; - } + /** + * Tests if this Transport mechanism has started. + * + * @return bool + */ + public function isStarted() + { + return true; + } - /** - * Starts this Transport mechanism. - */ - public function start() - { - } + /** + * Starts this Transport mechanism. + */ + public function start() + { + } - /** - * Stops this Transport mechanism. - */ - public function stop() - { - } + /** + * Stops this Transport mechanism. + */ + public function stop() + { + } - /** - * {@inheritdoc} - */ - public function ping() - { - return true; - } + /** + * {@inheritdoc} + */ + public function ping() + { + return true; + } - /** - * Sends the given message. - * - * @param string[] $failedRecipients An array of failures by-reference - * - * @return int The number of sent e-mail's - */ - public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) - { - if ($evt = $this->eventDispatcher->createSendEvent($this, $message)) { - $this->eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed'); - if ($evt->bubbleCancelled()) { - return 0; - } - } + /** + * Sends the given message. + * + * @param string[] $failedRecipients An array of failures by-reference + * + * @return int The number of sent e-mail's + */ + public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) + { + if ($evt = $this->eventDispatcher->createSendEvent($this, $message)) { + $this->eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed'); + if ($evt->bubbleCancelled()) { + return 0; + } + } - $success = $this->spool->queueMessage($message); + $success = $this->spool->queueMessage($message); - if ($evt) { - $evt->setResult($success ? Swift_Events_SendEvent::RESULT_SPOOLED : Swift_Events_SendEvent::RESULT_FAILED); - $this->eventDispatcher->dispatchEvent($evt, 'sendPerformed'); - } + if ($evt) { + $evt->setResult($success ? Swift_Events_SendEvent::RESULT_SPOOLED : Swift_Events_SendEvent::RESULT_FAILED); + $this->eventDispatcher->dispatchEvent($evt, 'sendPerformed'); + } - return 1; - } + return 1; + } - /** - * Register a plugin. - */ - public function registerPlugin(Swift_Events_EventListener $plugin) - { - $this->eventDispatcher->bindEventListener($plugin); - } + /** + * Register a plugin. + */ + public function registerPlugin(Swift_Events_EventListener $plugin) + { + $this->eventDispatcher->bindEventListener($plugin); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php index 70782ada044..6a09db7938f 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php @@ -15,305 +15,305 @@ */ class Swift_Transport_StreamBuffer extends Swift_ByteStream_AbstractFilterableInputStream implements Swift_Transport_IoBuffer { - /** A primary socket */ - private $stream; + /** A primary socket */ + private $stream; - /** The input stream */ - private $in; + /** The input stream */ + private $in; - /** The output stream */ - private $out; + /** The output stream */ + private $out; - /** Buffer initialization parameters */ - private $params = []; + /** Buffer initialization parameters */ + private $params = []; - /** The ReplacementFilterFactory */ - private $replacementFactory; + /** The ReplacementFilterFactory */ + private $replacementFactory; - /** Translations performed on data being streamed into the buffer */ - private $translations = []; + /** Translations performed on data being streamed into the buffer */ + private $translations = []; - /** - * Create a new StreamBuffer using $replacementFactory for transformations. - */ - public function __construct(Swift_ReplacementFilterFactory $replacementFactory) - { - $this->replacementFactory = $replacementFactory; - } + /** + * Create a new StreamBuffer using $replacementFactory for transformations. + */ + public function __construct(Swift_ReplacementFilterFactory $replacementFactory) + { + $this->replacementFactory = $replacementFactory; + } - /** - * Perform any initialization needed, using the given $params. - * - * Parameters will vary depending upon the type of IoBuffer used. - */ - public function initialize(array $params) - { - $this->params = $params; - switch ($params['type']) { - case self::TYPE_PROCESS: - $this->establishProcessConnection(); - break; - case self::TYPE_SOCKET: - default: - $this->establishSocketConnection(); - break; - } - } + /** + * Perform any initialization needed, using the given $params. + * + * Parameters will vary depending upon the type of IoBuffer used. + */ + public function initialize(array $params) + { + $this->params = $params; + switch ($params['type']) { + case self::TYPE_PROCESS: + $this->establishProcessConnection(); + break; + case self::TYPE_SOCKET: + default: + $this->establishSocketConnection(); + break; + } + } - /** - * Set an individual param on the buffer (e.g. switching to SSL). - * - * @param string $param - * @param mixed $value - */ - public function setParam($param, $value) - { - if (isset($this->stream)) { - switch ($param) { - case 'timeout': - if ($this->stream) { - stream_set_timeout($this->stream, $value); - } - break; + /** + * Set an individual param on the buffer (e.g. switching to SSL). + * + * @param string $param + * @param mixed $value + */ + public function setParam($param, $value) + { + if (isset($this->stream)) { + switch ($param) { + case 'timeout': + if ($this->stream) { + stream_set_timeout($this->stream, $value); + } + break; - case 'blocking': - if ($this->stream) { - stream_set_blocking($this->stream, 1); - } - } - } - $this->params[$param] = $value; - } + case 'blocking': + if ($this->stream) { + stream_set_blocking($this->stream, 1); + } + } + } + $this->params[$param] = $value; + } - public function startTLS() - { - // STREAM_CRYPTO_METHOD_TLS_CLIENT only allow tls1.0 connections (some php versions) - // To support modern tls we allow explicit tls1.0, tls1.1, tls1.2 - // Ssl3 and older are not allowed because they are vulnerable - // @TODO make tls arguments configurable - return stream_socket_enable_crypto($this->stream, true, STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT); - } + public function startTLS() + { + // STREAM_CRYPTO_METHOD_TLS_CLIENT only allow tls1.0 connections (some php versions) + // To support modern tls we allow explicit tls1.0, tls1.1, tls1.2 + // Ssl3 and older are not allowed because they are vulnerable + // @TODO make tls arguments configurable + return stream_socket_enable_crypto($this->stream, true, STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT); + } - /** - * Perform any shutdown logic needed. - */ - public function terminate() - { - if (isset($this->stream)) { - switch ($this->params['type']) { - case self::TYPE_PROCESS: - fclose($this->in); - fclose($this->out); - proc_close($this->stream); - break; - case self::TYPE_SOCKET: - default: - fclose($this->stream); - break; - } - } - $this->stream = null; - $this->out = null; - $this->in = null; - } + /** + * Perform any shutdown logic needed. + */ + public function terminate() + { + if (isset($this->stream)) { + switch ($this->params['type']) { + case self::TYPE_PROCESS: + fclose($this->in); + fclose($this->out); + proc_close($this->stream); + break; + case self::TYPE_SOCKET: + default: + fclose($this->stream); + break; + } + } + $this->stream = null; + $this->out = null; + $this->in = null; + } - /** - * Set an array of string replacements which should be made on data written - * to the buffer. - * - * This could replace LF with CRLF for example. - * - * @param string[] $replacements - */ - public function setWriteTranslations(array $replacements) - { - foreach ($this->translations as $search => $replace) { - if (!isset($replacements[$search])) { - $this->removeFilter($search); - unset($this->translations[$search]); - } - } + /** + * Set an array of string replacements which should be made on data written + * to the buffer. + * + * This could replace LF with CRLF for example. + * + * @param string[] $replacements + */ + public function setWriteTranslations(array $replacements) + { + foreach ($this->translations as $search => $replace) { + if (!isset($replacements[$search])) { + $this->removeFilter($search); + unset($this->translations[$search]); + } + } - foreach ($replacements as $search => $replace) { - if (!isset($this->translations[$search])) { - $this->addFilter( - $this->replacementFactory->createFilter($search, $replace), $search - ); - $this->translations[$search] = true; - } - } - } + foreach ($replacements as $search => $replace) { + if (!isset($this->translations[$search])) { + $this->addFilter( + $this->replacementFactory->createFilter($search, $replace), $search + ); + $this->translations[$search] = true; + } + } + } - /** - * Get a line of output (including any CRLF). - * - * The $sequence number comes from any writes and may or may not be used - * depending upon the implementation. - * - * @param int $sequence of last write to scan from - * - * @return string - * - * @throws Swift_IoException - */ - public function readLine($sequence) - { - if (isset($this->out) && !feof($this->out)) { - $line = fgets($this->out); - if (0 == \strlen($line)) { - $metas = stream_get_meta_data($this->out); - if ($metas['timed_out']) { - throw new Swift_IoException('Connection to '.$this->getReadConnectionDescription().' Timed Out'); - } - } + /** + * Get a line of output (including any CRLF). + * + * The $sequence number comes from any writes and may or may not be used + * depending upon the implementation. + * + * @param int $sequence of last write to scan from + * + * @return string + * + * @throws Swift_IoException + */ + public function readLine($sequence) + { + if (isset($this->out) && !feof($this->out)) { + $line = fgets($this->out); + if (0 == \strlen($line)) { + $metas = stream_get_meta_data($this->out); + if ($metas['timed_out']) { + throw new Swift_IoException('Connection to '.$this->getReadConnectionDescription().' Timed Out'); + } + } - return $line; - } - } + return $line; + } + } - /** - * Reads $length bytes from the stream into a string and moves the pointer - * through the stream by $length. - * - * If less bytes exist than are requested the remaining bytes are given instead. - * If no bytes are remaining at all, boolean false is returned. - * - * @param int $length - * - * @return string|bool - * - * @throws Swift_IoException - */ - public function read($length) - { - if (isset($this->out) && !feof($this->out)) { - $ret = fread($this->out, $length); - if (0 == \strlen($ret)) { - $metas = stream_get_meta_data($this->out); - if ($metas['timed_out']) { - throw new Swift_IoException('Connection to '.$this->getReadConnectionDescription().' Timed Out'); - } - } + /** + * Reads $length bytes from the stream into a string and moves the pointer + * through the stream by $length. + * + * If less bytes exist than are requested the remaining bytes are given instead. + * If no bytes are remaining at all, boolean false is returned. + * + * @param int $length + * + * @return string|bool + * + * @throws Swift_IoException + */ + public function read($length) + { + if (isset($this->out) && !feof($this->out)) { + $ret = fread($this->out, $length); + if (0 == \strlen($ret)) { + $metas = stream_get_meta_data($this->out); + if ($metas['timed_out']) { + throw new Swift_IoException('Connection to '.$this->getReadConnectionDescription().' Timed Out'); + } + } - return $ret; - } - } + return $ret; + } + } - /** Not implemented */ - public function setReadPointer($byteOffset) - { - } + /** Not implemented */ + public function setReadPointer($byteOffset) + { + } - /** Flush the stream contents */ - protected function flush() - { - if (isset($this->in)) { - fflush($this->in); - } - } + /** Flush the stream contents */ + protected function flush() + { + if (isset($this->in)) { + fflush($this->in); + } + } - /** Write this bytes to the stream */ - protected function doCommit($bytes) - { - if (isset($this->in)) { - $bytesToWrite = \strlen($bytes); - $totalBytesWritten = 0; + /** Write this bytes to the stream */ + protected function doCommit($bytes) + { + if (isset($this->in)) { + $bytesToWrite = \strlen($bytes); + $totalBytesWritten = 0; - while ($totalBytesWritten < $bytesToWrite) { - $bytesWritten = fwrite($this->in, substr($bytes, $totalBytesWritten)); - if (false === $bytesWritten || 0 === $bytesWritten) { - break; - } + while ($totalBytesWritten < $bytesToWrite) { + $bytesWritten = fwrite($this->in, substr($bytes, $totalBytesWritten)); + if (false === $bytesWritten || 0 === $bytesWritten) { + break; + } - $totalBytesWritten += $bytesWritten; - } + $totalBytesWritten += $bytesWritten; + } - if ($totalBytesWritten > 0) { - return ++$this->sequence; - } - } - } + if ($totalBytesWritten > 0) { + return ++$this->sequence; + } + } + } - /** - * Establishes a connection to a remote server. - */ - private function establishSocketConnection() - { - $host = $this->params['host']; - if (!empty($this->params['protocol'])) { - $host = $this->params['protocol'].'://'.$host; - } - $timeout = 15; - if (!empty($this->params['timeout'])) { - $timeout = $this->params['timeout']; - } - $options = []; - if (!empty($this->params['sourceIp'])) { - $options['socket']['bindto'] = $this->params['sourceIp'].':0'; - } + /** + * Establishes a connection to a remote server. + */ + private function establishSocketConnection() + { + $host = $this->params['host']; + if (!empty($this->params['protocol'])) { + $host = $this->params['protocol'].'://'.$host; + } + $timeout = 15; + if (!empty($this->params['timeout'])) { + $timeout = $this->params['timeout']; + } + $options = []; + if (!empty($this->params['sourceIp'])) { + $options['socket']['bindto'] = $this->params['sourceIp'].':0'; + } - if (isset($this->params['stream_context_options'])) { - $options = array_merge($options, $this->params['stream_context_options']); - } - $streamContext = stream_context_create($options); + if (isset($this->params['stream_context_options'])) { + $options = array_merge($options, $this->params['stream_context_options']); + } + $streamContext = stream_context_create($options); - set_error_handler(function ($type, $msg) { - throw new Swift_TransportException('Connection could not be established with host '.$this->params['host'].' :'.$msg); - }); - try { - $this->stream = stream_socket_client($host.':'.$this->params['port'], $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $streamContext); - } finally { - restore_error_handler(); - } + set_error_handler(function ($type, $msg) { + throw new Swift_TransportException('Connection could not be established with host '.$this->params['host'].' :'.$msg); + }); + try { + $this->stream = stream_socket_client($host.':'.$this->params['port'], $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $streamContext); + } finally { + restore_error_handler(); + } - if (!empty($this->params['blocking'])) { - stream_set_blocking($this->stream, 1); - } else { - stream_set_blocking($this->stream, 0); - } - stream_set_timeout($this->stream, $timeout); - $this->in = &$this->stream; - $this->out = &$this->stream; - } + if (!empty($this->params['blocking'])) { + stream_set_blocking($this->stream, 1); + } else { + stream_set_blocking($this->stream, 0); + } + stream_set_timeout($this->stream, $timeout); + $this->in = &$this->stream; + $this->out = &$this->stream; + } - /** - * Opens a process for input/output. - */ - private function establishProcessConnection() - { - $command = $this->params['command']; - $descriptorSpec = [ - 0 => ['pipe', 'r'], - 1 => ['pipe', 'w'], - 2 => ['pipe', 'w'], - ]; - $pipes = []; - $this->stream = proc_open($command, $descriptorSpec, $pipes); - stream_set_blocking($pipes[2], 0); - if ($err = stream_get_contents($pipes[2])) { - throw new Swift_TransportException('Process could not be started ['.$err.']'); - } - $this->in = &$pipes[0]; - $this->out = &$pipes[1]; - } + /** + * Opens a process for input/output. + */ + private function establishProcessConnection() + { + $command = $this->params['command']; + $descriptorSpec = [ + 0 => ['pipe', 'r'], + 1 => ['pipe', 'w'], + 2 => ['pipe', 'w'], + ]; + $pipes = []; + $this->stream = proc_open($command, $descriptorSpec, $pipes); + stream_set_blocking($pipes[2], 0); + if ($err = stream_get_contents($pipes[2])) { + throw new Swift_TransportException('Process could not be started ['.$err.']'); + } + $this->in = &$pipes[0]; + $this->out = &$pipes[1]; + } - private function getReadConnectionDescription() - { - switch ($this->params['type']) { - case self::TYPE_PROCESS: - return 'Process '.$this->params['command']; - break; + private function getReadConnectionDescription() + { + switch ($this->params['type']) { + case self::TYPE_PROCESS: + return 'Process '.$this->params['command']; + break; - case self::TYPE_SOCKET: - default: - $host = $this->params['host']; - if (!empty($this->params['protocol'])) { - $host = $this->params['protocol'].'://'.$host; - } - $host .= ':'.$this->params['port']; + case self::TYPE_SOCKET: + default: + $host = $this->params['host']; + if (!empty($this->params['protocol'])) { + $host = $this->params['protocol'].'://'.$host; + } + $host .= ':'.$this->params['port']; - return $host; - break; - } - } + return $host; + break; + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/TransportException.php b/htdocs/includes/swiftmailer/lib/classes/Swift/TransportException.php index c7417455b3e..763c9fed2ee 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/TransportException.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/TransportException.php @@ -15,14 +15,14 @@ */ class Swift_TransportException extends Swift_IoException { - /** - * Create a new TransportException with $message. - * - * @param string $message - * @param int $code - */ - public function __construct($message, $code = 0, Exception $previous = null) - { - parent::__construct($message, $code, $previous); - } + /** + * Create a new TransportException with $message. + * + * @param string $message + * @param int $code + */ + public function __construct($message, $code = 0, Exception $previous = null) + { + parent::__construct($message, $code, $previous); + } } diff --git a/htdocs/includes/swiftmailer/lib/dependency_maps/cache_deps.php b/htdocs/includes/swiftmailer/lib/dependency_maps/cache_deps.php index 9d94d774014..c2f2df20bc3 100644 --- a/htdocs/includes/swiftmailer/lib/dependency_maps/cache_deps.php +++ b/htdocs/includes/swiftmailer/lib/dependency_maps/cache_deps.php @@ -1,23 +1,22 @@ register('cache') - ->asAliasOf('cache.array') + ->register('cache') + ->asAliasOf('cache.array') - ->register('tempdir') - ->asValue('/tmp') + ->register('tempdir') + ->asValue('/tmp') - ->register('cache.null') - ->asSharedInstanceOf('Swift_KeyCache_NullKeyCache') + ->register('cache.null') + ->asSharedInstanceOf('Swift_KeyCache_NullKeyCache') - ->register('cache.array') - ->asSharedInstanceOf('Swift_KeyCache_ArrayKeyCache') - ->withDependencies(['cache.inputstream']) + ->register('cache.array') + ->asSharedInstanceOf('Swift_KeyCache_ArrayKeyCache') + ->withDependencies(['cache.inputstream']) - ->register('cache.disk') - ->asSharedInstanceOf('Swift_KeyCache_DiskKeyCache') - ->withDependencies(['cache.inputstream', 'tempdir']) + ->register('cache.disk') + ->asSharedInstanceOf('Swift_KeyCache_DiskKeyCache') + ->withDependencies(['cache.inputstream', 'tempdir']) - ->register('cache.inputstream') - ->asNewInstanceOf('Swift_KeyCache_SimpleKeyCacheInputStream') -; + ->register('cache.inputstream') + ->asNewInstanceOf('Swift_KeyCache_SimpleKeyCacheInputStream'); diff --git a/htdocs/includes/swiftmailer/lib/dependency_maps/mime_deps.php b/htdocs/includes/swiftmailer/lib/dependency_maps/mime_deps.php index 307756c89f3..3ee1b762ebe 100644 --- a/htdocs/includes/swiftmailer/lib/dependency_maps/mime_deps.php +++ b/htdocs/includes/swiftmailer/lib/dependency_maps/mime_deps.php @@ -3,132 +3,131 @@ require __DIR__.'/../mime_types.php'; Swift_DependencyContainer::getInstance() - ->register('properties.charset') - ->asValue('utf-8') + ->register('properties.charset') + ->asValue('utf-8') - ->register('email.validator') - ->asSharedInstanceOf('Egulias\EmailValidator\EmailValidator') + ->register('email.validator') + ->asSharedInstanceOf('Egulias\EmailValidator\EmailValidator') - ->register('mime.idgenerator.idright') - // As SERVER_NAME can come from the user in certain configurations, check that - // it does not contain forbidden characters (see RFC 952 and RFC 2181). Use - // preg_replace() instead of preg_match() to prevent DoS attacks with long host names. - ->asValue(!empty($_SERVER['SERVER_NAME']) && '' === preg_replace('/(?:^\[)?[a-zA-Z0-9-:\]_]+\.?/', '', $_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'swift.generated') + ->register('mime.idgenerator.idright') + // As SERVER_NAME can come from the user in certain configurations, check that + // it does not contain forbidden characters (see RFC 952 and RFC 2181). Use + // preg_replace() instead of preg_match() to prevent DoS attacks with long host names. + ->asValue(!empty($_SERVER['SERVER_NAME']) && '' === preg_replace('/(?:^\[)?[a-zA-Z0-9-:\]_]+\.?/', '', $_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'swift.generated') - ->register('mime.idgenerator') - ->asSharedInstanceOf('Swift_Mime_IdGenerator') - ->withDependencies([ - 'mime.idgenerator.idright', - ]) + ->register('mime.idgenerator') + ->asSharedInstanceOf('Swift_Mime_IdGenerator') + ->withDependencies([ + 'mime.idgenerator.idright', + ]) - ->register('mime.message') - ->asNewInstanceOf('Swift_Mime_SimpleMessage') - ->withDependencies([ - 'mime.headerset', - 'mime.textcontentencoder', - 'cache', - 'mime.idgenerator', - 'properties.charset', - ]) + ->register('mime.message') + ->asNewInstanceOf('Swift_Mime_SimpleMessage') + ->withDependencies([ + 'mime.headerset', + 'mime.textcontentencoder', + 'cache', + 'mime.idgenerator', + 'properties.charset', + ]) - ->register('mime.part') - ->asNewInstanceOf('Swift_Mime_MimePart') - ->withDependencies([ - 'mime.headerset', - 'mime.textcontentencoder', - 'cache', - 'mime.idgenerator', - 'properties.charset', - ]) + ->register('mime.part') + ->asNewInstanceOf('Swift_Mime_MimePart') + ->withDependencies([ + 'mime.headerset', + 'mime.textcontentencoder', + 'cache', + 'mime.idgenerator', + 'properties.charset', + ]) - ->register('mime.attachment') - ->asNewInstanceOf('Swift_Mime_Attachment') - ->withDependencies([ - 'mime.headerset', - 'mime.base64contentencoder', - 'cache', - 'mime.idgenerator', - ]) - ->addConstructorValue($swift_mime_types) + ->register('mime.attachment') + ->asNewInstanceOf('Swift_Mime_Attachment') + ->withDependencies([ + 'mime.headerset', + 'mime.base64contentencoder', + 'cache', + 'mime.idgenerator', + ]) + ->addConstructorValue($swift_mime_types) - ->register('mime.embeddedfile') - ->asNewInstanceOf('Swift_Mime_EmbeddedFile') - ->withDependencies([ - 'mime.headerset', - 'mime.base64contentencoder', - 'cache', - 'mime.idgenerator', - ]) - ->addConstructorValue($swift_mime_types) + ->register('mime.embeddedfile') + ->asNewInstanceOf('Swift_Mime_EmbeddedFile') + ->withDependencies([ + 'mime.headerset', + 'mime.base64contentencoder', + 'cache', + 'mime.idgenerator', + ]) + ->addConstructorValue($swift_mime_types) - ->register('mime.headerfactory') - ->asNewInstanceOf('Swift_Mime_SimpleHeaderFactory') - ->withDependencies([ - 'mime.qpheaderencoder', - 'mime.rfc2231encoder', - 'email.validator', - 'properties.charset', - 'address.idnaddressencoder', - ]) + ->register('mime.headerfactory') + ->asNewInstanceOf('Swift_Mime_SimpleHeaderFactory') + ->withDependencies([ + 'mime.qpheaderencoder', + 'mime.rfc2231encoder', + 'email.validator', + 'properties.charset', + 'address.idnaddressencoder', + ]) - ->register('mime.headerset') - ->asNewInstanceOf('Swift_Mime_SimpleHeaderSet') - ->withDependencies(['mime.headerfactory', 'properties.charset']) + ->register('mime.headerset') + ->asNewInstanceOf('Swift_Mime_SimpleHeaderSet') + ->withDependencies(['mime.headerfactory', 'properties.charset']) - ->register('mime.qpheaderencoder') - ->asNewInstanceOf('Swift_Mime_HeaderEncoder_QpHeaderEncoder') - ->withDependencies(['mime.charstream']) + ->register('mime.qpheaderencoder') + ->asNewInstanceOf('Swift_Mime_HeaderEncoder_QpHeaderEncoder') + ->withDependencies(['mime.charstream']) - ->register('mime.base64headerencoder') - ->asNewInstanceOf('Swift_Mime_HeaderEncoder_Base64HeaderEncoder') - ->withDependencies(['mime.charstream']) + ->register('mime.base64headerencoder') + ->asNewInstanceOf('Swift_Mime_HeaderEncoder_Base64HeaderEncoder') + ->withDependencies(['mime.charstream']) - ->register('mime.charstream') - ->asNewInstanceOf('Swift_CharacterStream_NgCharacterStream') - ->withDependencies(['mime.characterreaderfactory', 'properties.charset']) + ->register('mime.charstream') + ->asNewInstanceOf('Swift_CharacterStream_NgCharacterStream') + ->withDependencies(['mime.characterreaderfactory', 'properties.charset']) - ->register('mime.bytecanonicalizer') - ->asSharedInstanceOf('Swift_StreamFilters_ByteArrayReplacementFilter') - ->addConstructorValue([[0x0D, 0x0A], [0x0D], [0x0A]]) - ->addConstructorValue([[0x0A], [0x0A], [0x0D, 0x0A]]) + ->register('mime.bytecanonicalizer') + ->asSharedInstanceOf('Swift_StreamFilters_ByteArrayReplacementFilter') + ->addConstructorValue([[0x0D, 0x0A], [0x0D], [0x0A]]) + ->addConstructorValue([[0x0A], [0x0A], [0x0D, 0x0A]]) - ->register('mime.characterreaderfactory') - ->asSharedInstanceOf('Swift_CharacterReaderFactory_SimpleCharacterReaderFactory') + ->register('mime.characterreaderfactory') + ->asSharedInstanceOf('Swift_CharacterReaderFactory_SimpleCharacterReaderFactory') - ->register('mime.textcontentencoder') - ->asAliasOf('mime.qpcontentencoder') + ->register('mime.textcontentencoder') + ->asAliasOf('mime.qpcontentencoder') - ->register('mime.safeqpcontentencoder') - ->asNewInstanceOf('Swift_Mime_ContentEncoder_QpContentEncoder') - ->withDependencies(['mime.charstream', 'mime.bytecanonicalizer']) + ->register('mime.safeqpcontentencoder') + ->asNewInstanceOf('Swift_Mime_ContentEncoder_QpContentEncoder') + ->withDependencies(['mime.charstream', 'mime.bytecanonicalizer']) - ->register('mime.rawcontentencoder') - ->asNewInstanceOf('Swift_Mime_ContentEncoder_RawContentEncoder') + ->register('mime.rawcontentencoder') + ->asNewInstanceOf('Swift_Mime_ContentEncoder_RawContentEncoder') - ->register('mime.nativeqpcontentencoder') - ->withDependencies(['properties.charset']) - ->asNewInstanceOf('Swift_Mime_ContentEncoder_NativeQpContentEncoder') + ->register('mime.nativeqpcontentencoder') + ->withDependencies(['properties.charset']) + ->asNewInstanceOf('Swift_Mime_ContentEncoder_NativeQpContentEncoder') - ->register('mime.qpcontentencoder') - ->asNewInstanceOf('Swift_Mime_ContentEncoder_QpContentEncoderProxy') - ->withDependencies(['mime.safeqpcontentencoder', 'mime.nativeqpcontentencoder', 'properties.charset']) + ->register('mime.qpcontentencoder') + ->asNewInstanceOf('Swift_Mime_ContentEncoder_QpContentEncoderProxy') + ->withDependencies(['mime.safeqpcontentencoder', 'mime.nativeqpcontentencoder', 'properties.charset']) - ->register('mime.7bitcontentencoder') - ->asNewInstanceOf('Swift_Mime_ContentEncoder_PlainContentEncoder') - ->addConstructorValue('7bit') - ->addConstructorValue(true) + ->register('mime.7bitcontentencoder') + ->asNewInstanceOf('Swift_Mime_ContentEncoder_PlainContentEncoder') + ->addConstructorValue('7bit') + ->addConstructorValue(true) - ->register('mime.8bitcontentencoder') - ->asNewInstanceOf('Swift_Mime_ContentEncoder_PlainContentEncoder') - ->addConstructorValue('8bit') - ->addConstructorValue(true) + ->register('mime.8bitcontentencoder') + ->asNewInstanceOf('Swift_Mime_ContentEncoder_PlainContentEncoder') + ->addConstructorValue('8bit') + ->addConstructorValue(true) - ->register('mime.base64contentencoder') - ->asSharedInstanceOf('Swift_Mime_ContentEncoder_Base64ContentEncoder') + ->register('mime.base64contentencoder') + ->asSharedInstanceOf('Swift_Mime_ContentEncoder_Base64ContentEncoder') - ->register('mime.rfc2231encoder') - ->asNewInstanceOf('Swift_Encoder_Rfc2231Encoder') - ->withDependencies(['mime.charstream']) -; + ->register('mime.rfc2231encoder') + ->asNewInstanceOf('Swift_Encoder_Rfc2231Encoder') + ->withDependencies(['mime.charstream']); unset($swift_mime_types); diff --git a/htdocs/includes/swiftmailer/lib/dependency_maps/transport_deps.php b/htdocs/includes/swiftmailer/lib/dependency_maps/transport_deps.php index 34a63c78e51..40d65b176b9 100644 --- a/htdocs/includes/swiftmailer/lib/dependency_maps/transport_deps.php +++ b/htdocs/includes/swiftmailer/lib/dependency_maps/transport_deps.php @@ -1,97 +1,96 @@ register('transport.localdomain') - // As SERVER_NAME can come from the user in certain configurations, check that - // it does not contain forbidden characters (see RFC 952 and RFC 2181). Use - // preg_replace() instead of preg_match() to prevent DoS attacks with long host names. - ->asValue(!empty($_SERVER['SERVER_NAME']) && '' === preg_replace('/(?:^\[)?[a-zA-Z0-9-:\]_]+\.?/', '', $_SERVER['SERVER_NAME']) ? trim($_SERVER['SERVER_NAME'], '[]') : '127.0.0.1') + ->register('transport.localdomain') + // As SERVER_NAME can come from the user in certain configurations, check that + // it does not contain forbidden characters (see RFC 952 and RFC 2181). Use + // preg_replace() instead of preg_match() to prevent DoS attacks with long host names. + ->asValue(!empty($_SERVER['SERVER_NAME']) && '' === preg_replace('/(?:^\[)?[a-zA-Z0-9-:\]_]+\.?/', '', $_SERVER['SERVER_NAME']) ? trim($_SERVER['SERVER_NAME'], '[]') : '127.0.0.1') - ->register('transport.smtp') - ->asNewInstanceOf('Swift_Transport_EsmtpTransport') - ->withDependencies([ - 'transport.buffer', - 'transport.smtphandlers', - 'transport.eventdispatcher', - 'transport.localdomain', - 'address.idnaddressencoder', - ]) + ->register('transport.smtp') + ->asNewInstanceOf('Swift_Transport_EsmtpTransport') + ->withDependencies([ + 'transport.buffer', + 'transport.smtphandlers', + 'transport.eventdispatcher', + 'transport.localdomain', + 'address.idnaddressencoder', + ]) - ->register('transport.sendmail') - ->asNewInstanceOf('Swift_Transport_SendmailTransport') - ->withDependencies([ - 'transport.buffer', - 'transport.eventdispatcher', - 'transport.localdomain', - ]) + ->register('transport.sendmail') + ->asNewInstanceOf('Swift_Transport_SendmailTransport') + ->withDependencies([ + 'transport.buffer', + 'transport.eventdispatcher', + 'transport.localdomain', + ]) - ->register('transport.loadbalanced') - ->asNewInstanceOf('Swift_Transport_LoadBalancedTransport') + ->register('transport.loadbalanced') + ->asNewInstanceOf('Swift_Transport_LoadBalancedTransport') - ->register('transport.failover') - ->asNewInstanceOf('Swift_Transport_FailoverTransport') + ->register('transport.failover') + ->asNewInstanceOf('Swift_Transport_FailoverTransport') - ->register('transport.spool') - ->asNewInstanceOf('Swift_Transport_SpoolTransport') - ->withDependencies(['transport.eventdispatcher']) + ->register('transport.spool') + ->asNewInstanceOf('Swift_Transport_SpoolTransport') + ->withDependencies(['transport.eventdispatcher']) - ->register('transport.null') - ->asNewInstanceOf('Swift_Transport_NullTransport') - ->withDependencies(['transport.eventdispatcher']) + ->register('transport.null') + ->asNewInstanceOf('Swift_Transport_NullTransport') + ->withDependencies(['transport.eventdispatcher']) - ->register('transport.buffer') - ->asNewInstanceOf('Swift_Transport_StreamBuffer') - ->withDependencies(['transport.replacementfactory']) + ->register('transport.buffer') + ->asNewInstanceOf('Swift_Transport_StreamBuffer') + ->withDependencies(['transport.replacementfactory']) - ->register('transport.smtphandlers') - ->asArray() - ->withDependencies(['transport.authhandler']) + ->register('transport.smtphandlers') + ->asArray() + ->withDependencies(['transport.authhandler']) - ->register('transport.authhandler') - ->asNewInstanceOf('Swift_Transport_Esmtp_AuthHandler') - ->withDependencies(['transport.authhandlers']) + ->register('transport.authhandler') + ->asNewInstanceOf('Swift_Transport_Esmtp_AuthHandler') + ->withDependencies(['transport.authhandlers']) - ->register('transport.authhandlers') - ->asArray() - ->withDependencies([ - 'transport.crammd5auth', - 'transport.loginauth', - 'transport.plainauth', - 'transport.ntlmauth', - 'transport.xoauth2auth', - ]) + ->register('transport.authhandlers') + ->asArray() + ->withDependencies([ + 'transport.crammd5auth', + 'transport.loginauth', + 'transport.plainauth', + 'transport.ntlmauth', + 'transport.xoauth2auth', + ]) - ->register('transport.smtputf8handler') - ->asNewInstanceOf('Swift_Transport_Esmtp_SmtpUtf8Handler') + ->register('transport.smtputf8handler') + ->asNewInstanceOf('Swift_Transport_Esmtp_SmtpUtf8Handler') - ->register('transport.8bitmimehandler') - ->asNewInstanceOf('Swift_Transport_Esmtp_EightBitMimeHandler') - ->addConstructorValue('8BITMIME') + ->register('transport.8bitmimehandler') + ->asNewInstanceOf('Swift_Transport_Esmtp_EightBitMimeHandler') + ->addConstructorValue('8BITMIME') - ->register('transport.crammd5auth') - ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_CramMd5Authenticator') + ->register('transport.crammd5auth') + ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_CramMd5Authenticator') - ->register('transport.loginauth') - ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_LoginAuthenticator') + ->register('transport.loginauth') + ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_LoginAuthenticator') - ->register('transport.plainauth') - ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_PlainAuthenticator') + ->register('transport.plainauth') + ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_PlainAuthenticator') - ->register('transport.xoauth2auth') - ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_XOAuth2Authenticator') + ->register('transport.xoauth2auth') + ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_XOAuth2Authenticator') - ->register('transport.ntlmauth') - ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_NTLMAuthenticator') + ->register('transport.ntlmauth') + ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_NTLMAuthenticator') - ->register('transport.eventdispatcher') - ->asNewInstanceOf('Swift_Events_SimpleEventDispatcher') + ->register('transport.eventdispatcher') + ->asNewInstanceOf('Swift_Events_SimpleEventDispatcher') - ->register('transport.replacementfactory') - ->asSharedInstanceOf('Swift_StreamFilters_StringReplacementFilterFactory') + ->register('transport.replacementfactory') + ->asSharedInstanceOf('Swift_StreamFilters_StringReplacementFilterFactory') - ->register('address.idnaddressencoder') - ->asNewInstanceOf('Swift_AddressEncoder_IdnAddressEncoder') + ->register('address.idnaddressencoder') + ->asNewInstanceOf('Swift_AddressEncoder_IdnAddressEncoder') - ->register('address.utf8addressencoder') - ->asNewInstanceOf('Swift_AddressEncoder_Utf8AddressEncoder') -; + ->register('address.utf8addressencoder') + ->asNewInstanceOf('Swift_AddressEncoder_Utf8AddressEncoder'); diff --git a/htdocs/includes/swiftmailer/lib/mime_types.php b/htdocs/includes/swiftmailer/lib/mime_types.php index 72c6fd2afa6..0cb61d18832 100644 --- a/htdocs/includes/swiftmailer/lib/mime_types.php +++ b/htdocs/includes/swiftmailer/lib/mime_types.php @@ -18,990 +18,990 @@ // You may add or take away what you like (lowercase required) $swift_mime_types = [ - '3dml' => 'text/vnd.in3d.3dml', - '3ds' => 'image/x-3ds', - '3g2' => 'video/3gpp2', - '3gp' => 'video/3gpp', - '7z' => 'application/x-7z-compressed', - 'aab' => 'application/x-authorware-bin', - 'aac' => 'audio/x-aac', - 'aam' => 'application/x-authorware-map', - 'aas' => 'application/x-authorware-seg', - 'abw' => 'application/x-abiword', - 'ac' => 'application/pkix-attr-cert', - 'acc' => 'application/vnd.americandynamics.acc', - 'ace' => 'application/x-ace-compressed', - 'acu' => 'application/vnd.acucobol', - 'acutc' => 'application/vnd.acucorp', - 'adp' => 'audio/adpcm', - 'aep' => 'application/vnd.audiograph', - 'afm' => 'application/x-font-type1', - 'afp' => 'application/vnd.ibm.modcap', - 'ahead' => 'application/vnd.ahead.space', - 'ai' => 'application/postscript', - 'aif' => 'audio/x-aiff', - 'aifc' => 'audio/x-aiff', - 'aiff' => 'audio/x-aiff', - 'air' => 'application/vnd.adobe.air-application-installer-package+zip', - 'ait' => 'application/vnd.dvb.ait', - 'ami' => 'application/vnd.amiga.ami', - 'apk' => 'application/vnd.android.package-archive', - 'appcache' => 'text/cache-manifest', - 'apr' => 'application/vnd.lotus-approach', - 'aps' => 'application/postscript', - 'arc' => 'application/x-freearc', - 'asc' => 'application/pgp-signature', - 'asf' => 'video/x-ms-asf', - 'asm' => 'text/x-asm', - 'aso' => 'application/vnd.accpac.simply.aso', - 'asx' => 'video/x-ms-asf', - 'atc' => 'application/vnd.acucorp', - 'atom' => 'application/atom+xml', - 'atomcat' => 'application/atomcat+xml', - 'atomsvc' => 'application/atomsvc+xml', - 'atx' => 'application/vnd.antix.game-component', - 'au' => 'audio/basic', - 'avi' => 'video/x-msvideo', - 'aw' => 'application/applixware', - 'azf' => 'application/vnd.airzip.filesecure.azf', - 'azs' => 'application/vnd.airzip.filesecure.azs', - 'azw' => 'application/vnd.amazon.ebook', - 'bat' => 'application/x-msdownload', - 'bcpio' => 'application/x-bcpio', - 'bdf' => 'application/x-font-bdf', - 'bdm' => 'application/vnd.syncml.dm+wbxml', - 'bed' => 'application/vnd.realvnc.bed', - 'bh2' => 'application/vnd.fujitsu.oasysprs', - 'bin' => 'application/octet-stream', - 'blb' => 'application/x-blorb', - 'blorb' => 'application/x-blorb', - 'bmi' => 'application/vnd.bmi', - 'bmp' => 'image/bmp', - 'book' => 'application/vnd.framemaker', - 'box' => 'application/vnd.previewsystems.box', - 'boz' => 'application/x-bzip2', - 'bpk' => 'application/octet-stream', - 'btif' => 'image/prs.btif', - 'bz' => 'application/x-bzip', - 'bz2' => 'application/x-bzip2', - 'c' => 'text/x-c', - 'c11amc' => 'application/vnd.cluetrust.cartomobile-config', - 'c11amz' => 'application/vnd.cluetrust.cartomobile-config-pkg', - 'c4d' => 'application/vnd.clonk.c4group', - 'c4f' => 'application/vnd.clonk.c4group', - 'c4g' => 'application/vnd.clonk.c4group', - 'c4p' => 'application/vnd.clonk.c4group', - 'c4u' => 'application/vnd.clonk.c4group', - 'cab' => 'application/vnd.ms-cab-compressed', - 'caf' => 'audio/x-caf', - 'cap' => 'application/vnd.tcpdump.pcap', - 'car' => 'application/vnd.curl.car', - 'cat' => 'application/vnd.ms-pki.seccat', - 'cb7' => 'application/x-cbr', - 'cba' => 'application/x-cbr', - 'cbr' => 'application/x-cbr', - 'cbt' => 'application/x-cbr', - 'cbz' => 'application/x-cbr', - 'cc' => 'text/x-c', - 'cct' => 'application/x-director', - 'ccxml' => 'application/ccxml+xml', - 'cdbcmsg' => 'application/vnd.contact.cmsg', - 'cdf' => 'application/x-netcdf', - 'cdkey' => 'application/vnd.mediastation.cdkey', - 'cdmia' => 'application/cdmi-capability', - 'cdmic' => 'application/cdmi-container', - 'cdmid' => 'application/cdmi-domain', - 'cdmio' => 'application/cdmi-object', - 'cdmiq' => 'application/cdmi-queue', - 'cdx' => 'chemical/x-cdx', - 'cdxml' => 'application/vnd.chemdraw+xml', - 'cdy' => 'application/vnd.cinderella', - 'cer' => 'application/pkix-cert', - 'cfs' => 'application/x-cfs-compressed', - 'cgm' => 'image/cgm', - 'chat' => 'application/x-chat', - 'chm' => 'application/vnd.ms-htmlhelp', - 'chrt' => 'application/vnd.kde.kchart', - 'cif' => 'chemical/x-cif', - 'cii' => 'application/vnd.anser-web-certificate-issue-initiation', - 'cil' => 'application/vnd.ms-artgalry', - 'cla' => 'application/vnd.claymore', - 'class' => 'application/java-vm', - 'clkk' => 'application/vnd.crick.clicker.keyboard', - 'clkp' => 'application/vnd.crick.clicker.palette', - 'clkt' => 'application/vnd.crick.clicker.template', - 'clkw' => 'application/vnd.crick.clicker.wordbank', - 'clkx' => 'application/vnd.crick.clicker', - 'clp' => 'application/x-msclip', - 'cmc' => 'application/vnd.cosmocaller', - 'cmdf' => 'chemical/x-cmdf', - 'cml' => 'chemical/x-cml', - 'cmp' => 'application/vnd.yellowriver-custom-menu', - 'cmx' => 'image/x-cmx', - 'cod' => 'application/vnd.rim.cod', - 'com' => 'application/x-msdownload', - 'conf' => 'text/plain', - 'cpio' => 'application/x-cpio', - 'cpp' => 'text/x-c', - 'cpt' => 'application/mac-compactpro', - 'crd' => 'application/x-mscardfile', - 'crl' => 'application/pkix-crl', - 'crt' => 'application/x-x509-ca-cert', - 'csh' => 'application/x-csh', - 'csml' => 'chemical/x-csml', - 'csp' => 'application/vnd.commonspace', - 'css' => 'text/css', - 'cst' => 'application/x-director', - 'csv' => 'text/csv', - 'cu' => 'application/cu-seeme', - 'curl' => 'text/vnd.curl', - 'cww' => 'application/prs.cww', - 'cxt' => 'application/x-director', - 'cxx' => 'text/x-c', - 'dae' => 'model/vnd.collada+xml', - 'daf' => 'application/vnd.mobius.daf', - 'dart' => 'application/vnd.dart', - 'dataless' => 'application/vnd.fdsn.seed', - 'davmount' => 'application/davmount+xml', - 'dbk' => 'application/docbook+xml', - 'dcr' => 'application/x-director', - 'dcurl' => 'text/vnd.curl.dcurl', - 'dd2' => 'application/vnd.oma.dd2+xml', - 'ddd' => 'application/vnd.fujixerox.ddd', - 'deb' => 'application/x-debian-package', - 'def' => 'text/plain', - 'deploy' => 'application/octet-stream', - 'der' => 'application/x-x509-ca-cert', - 'dfac' => 'application/vnd.dreamfactory', - 'dgc' => 'application/x-dgc-compressed', - 'dic' => 'text/x-c', - 'dir' => 'application/x-director', - 'dis' => 'application/vnd.mobius.dis', - 'dist' => 'application/octet-stream', - 'distz' => 'application/octet-stream', - 'djv' => 'image/vnd.djvu', - 'djvu' => 'image/vnd.djvu', - 'dll' => 'application/x-msdownload', - 'dmg' => 'application/x-apple-diskimage', - 'dmp' => 'application/vnd.tcpdump.pcap', - 'dms' => 'application/octet-stream', - 'dna' => 'application/vnd.dna', - 'doc' => 'application/msword', - 'docm' => 'application/vnd.ms-word.document.macroenabled.12', - 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', - 'dot' => 'application/msword', - 'dotm' => 'application/vnd.ms-word.template.macroenabled.12', - 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', - 'dp' => 'application/vnd.osgi.dp', - 'dpg' => 'application/vnd.dpgraph', - 'dra' => 'audio/vnd.dra', - 'dsc' => 'text/prs.lines.tag', - 'dssc' => 'application/dssc+der', - 'dtb' => 'application/x-dtbook+xml', - 'dtd' => 'application/xml-dtd', - 'dts' => 'audio/vnd.dts', - 'dtshd' => 'audio/vnd.dts.hd', - 'dump' => 'application/octet-stream', - 'dvb' => 'video/vnd.dvb.file', - 'dvi' => 'application/x-dvi', - 'dwf' => 'model/vnd.dwf', - 'dwg' => 'image/vnd.dwg', - 'dxf' => 'image/vnd.dxf', - 'dxp' => 'application/vnd.spotfire.dxp', - 'dxr' => 'application/x-director', - 'ecelp4800' => 'audio/vnd.nuera.ecelp4800', - 'ecelp7470' => 'audio/vnd.nuera.ecelp7470', - 'ecelp9600' => 'audio/vnd.nuera.ecelp9600', - 'ecma' => 'application/ecmascript', - 'edm' => 'application/vnd.novadigm.edm', - 'edx' => 'application/vnd.novadigm.edx', - 'efif' => 'application/vnd.picsel', - 'ei6' => 'application/vnd.pg.osasli', - 'elc' => 'application/octet-stream', - 'emf' => 'application/x-msmetafile', - 'eml' => 'message/rfc822', - 'emma' => 'application/emma+xml', - 'emz' => 'application/x-msmetafile', - 'eol' => 'audio/vnd.digital-winds', - 'eot' => 'application/vnd.ms-fontobject', - 'eps' => 'application/postscript', - 'epub' => 'application/epub+zip', - 'es3' => 'application/vnd.eszigno3+xml', - 'esa' => 'application/vnd.osgi.subsystem', - 'esf' => 'application/vnd.epson.esf', - 'et3' => 'application/vnd.eszigno3+xml', - 'etx' => 'text/x-setext', - 'eva' => 'application/x-eva', - 'evy' => 'application/x-envoy', - 'exe' => 'application/x-msdownload', - 'exi' => 'application/exi', - 'ext' => 'application/vnd.novadigm.ext', - 'ez' => 'application/andrew-inset', - 'ez2' => 'application/vnd.ezpix-album', - 'ez3' => 'application/vnd.ezpix-package', - 'f' => 'text/x-fortran', - 'f4v' => 'video/x-f4v', - 'f77' => 'text/x-fortran', - 'f90' => 'text/x-fortran', - 'fbs' => 'image/vnd.fastbidsheet', - 'fcdt' => 'application/vnd.adobe.formscentral.fcdt', - 'fcs' => 'application/vnd.isac.fcs', - 'fdf' => 'application/vnd.fdf', - 'fe_launch' => 'application/vnd.denovo.fcselayout-link', - 'fg5' => 'application/vnd.fujitsu.oasysgp', - 'fgd' => 'application/x-director', - 'fh' => 'image/x-freehand', - 'fh4' => 'image/x-freehand', - 'fh5' => 'image/x-freehand', - 'fh7' => 'image/x-freehand', - 'fhc' => 'image/x-freehand', - 'fig' => 'application/x-xfig', - 'flac' => 'audio/x-flac', - 'fli' => 'video/x-fli', - 'flo' => 'application/vnd.micrografx.flo', - 'flv' => 'video/x-flv', - 'flw' => 'application/vnd.kde.kivio', - 'flx' => 'text/vnd.fmi.flexstor', - 'fly' => 'text/vnd.fly', - 'fm' => 'application/vnd.framemaker', - 'fnc' => 'application/vnd.frogans.fnc', - 'for' => 'text/x-fortran', - 'fpx' => 'image/vnd.fpx', - 'frame' => 'application/vnd.framemaker', - 'fsc' => 'application/vnd.fsc.weblaunch', - 'fst' => 'image/vnd.fst', - 'ftc' => 'application/vnd.fluxtime.clip', - 'fti' => 'application/vnd.anser-web-funds-transfer-initiation', - 'fvt' => 'video/vnd.fvt', - 'fxp' => 'application/vnd.adobe.fxp', - 'fxpl' => 'application/vnd.adobe.fxp', - 'fzs' => 'application/vnd.fuzzysheet', - 'g2w' => 'application/vnd.geoplan', - 'g3' => 'image/g3fax', - 'g3w' => 'application/vnd.geospace', - 'gac' => 'application/vnd.groove-account', - 'gam' => 'application/x-tads', - 'gbr' => 'application/rpki-ghostbusters', - 'gca' => 'application/x-gca-compressed', - 'gdl' => 'model/vnd.gdl', - 'geo' => 'application/vnd.dynageo', - 'gex' => 'application/vnd.geometry-explorer', - 'ggb' => 'application/vnd.geogebra.file', - 'ggt' => 'application/vnd.geogebra.tool', - 'ghf' => 'application/vnd.groove-help', - 'gif' => 'image/gif', - 'gim' => 'application/vnd.groove-identity-message', - 'gml' => 'application/gml+xml', - 'gmx' => 'application/vnd.gmx', - 'gnumeric' => 'application/x-gnumeric', - 'gph' => 'application/vnd.flographit', - 'gpx' => 'application/gpx+xml', - 'gqf' => 'application/vnd.grafeq', - 'gqs' => 'application/vnd.grafeq', - 'gram' => 'application/srgs', - 'gramps' => 'application/x-gramps-xml', - 'gre' => 'application/vnd.geometry-explorer', - 'grv' => 'application/vnd.groove-injector', - 'grxml' => 'application/srgs+xml', - 'gsf' => 'application/x-font-ghostscript', - 'gtar' => 'application/x-gtar', - 'gtm' => 'application/vnd.groove-tool-message', - 'gtw' => 'model/vnd.gtw', - 'gv' => 'text/vnd.graphviz', - 'gxf' => 'application/gxf', - 'gxt' => 'application/vnd.geonext', - 'gz' => 'application/x-gzip', - 'h' => 'text/x-c', - 'h261' => 'video/h261', - 'h263' => 'video/h263', - 'h264' => 'video/h264', - 'hal' => 'application/vnd.hal+xml', - 'hbci' => 'application/vnd.hbci', - 'hdf' => 'application/x-hdf', - 'hh' => 'text/x-c', - 'hlp' => 'application/winhlp', - 'hpgl' => 'application/vnd.hp-hpgl', - 'hpid' => 'application/vnd.hp-hpid', - 'hps' => 'application/vnd.hp-hps', - 'hqx' => 'application/mac-binhex40', - 'htke' => 'application/vnd.kenameaapp', - 'htm' => 'text/html', - 'html' => 'text/html', - 'hvd' => 'application/vnd.yamaha.hv-dic', - 'hvp' => 'application/vnd.yamaha.hv-voice', - 'hvs' => 'application/vnd.yamaha.hv-script', - 'i2g' => 'application/vnd.intergeo', - 'icc' => 'application/vnd.iccprofile', - 'ice' => 'x-conference/x-cooltalk', - 'icm' => 'application/vnd.iccprofile', - 'ico' => 'image/x-icon', - 'ics' => 'text/calendar', - 'ief' => 'image/ief', - 'ifb' => 'text/calendar', - 'ifm' => 'application/vnd.shana.informed.formdata', - 'iges' => 'model/iges', - 'igl' => 'application/vnd.igloader', - 'igm' => 'application/vnd.insors.igm', - 'igs' => 'model/iges', - 'igx' => 'application/vnd.micrografx.igx', - 'iif' => 'application/vnd.shana.informed.interchange', - 'imp' => 'application/vnd.accpac.simply.imp', - 'ims' => 'application/vnd.ms-ims', - 'in' => 'text/plain', - 'ink' => 'application/inkml+xml', - 'inkml' => 'application/inkml+xml', - 'install' => 'application/x-install-instructions', - 'iota' => 'application/vnd.astraea-software.iota', - 'ipfix' => 'application/ipfix', - 'ipk' => 'application/vnd.shana.informed.package', - 'irm' => 'application/vnd.ibm.rights-management', - 'irp' => 'application/vnd.irepository.package+xml', - 'iso' => 'application/x-iso9660-image', - 'itp' => 'application/vnd.shana.informed.formtemplate', - 'ivp' => 'application/vnd.immervision-ivp', - 'ivu' => 'application/vnd.immervision-ivu', - 'jad' => 'text/vnd.sun.j2me.app-descriptor', - 'jam' => 'application/vnd.jam', - 'jar' => 'application/java-archive', - 'java' => 'text/x-java-source', - 'jisp' => 'application/vnd.jisp', - 'jlt' => 'application/vnd.hp-jlyt', - 'jnlp' => 'application/x-java-jnlp-file', - 'joda' => 'application/vnd.joost.joda-archive', - 'jpe' => 'image/jpeg', - 'jpeg' => 'image/jpeg', - 'jpg' => 'image/jpeg', - 'jpgm' => 'video/jpm', - 'jpgv' => 'video/jpeg', - 'jpm' => 'video/jpm', - 'js' => 'application/javascript', - 'json' => 'application/json', - 'jsonml' => 'application/jsonml+json', - 'kar' => 'audio/midi', - 'karbon' => 'application/vnd.kde.karbon', - 'kfo' => 'application/vnd.kde.kformula', - 'kia' => 'application/vnd.kidspiration', - 'kml' => 'application/vnd.google-earth.kml+xml', - 'kmz' => 'application/vnd.google-earth.kmz', - 'kne' => 'application/vnd.kinar', - 'knp' => 'application/vnd.kinar', - 'kon' => 'application/vnd.kde.kontour', - 'kpr' => 'application/vnd.kde.kpresenter', - 'kpt' => 'application/vnd.kde.kpresenter', - 'kpxx' => 'application/vnd.ds-keypoint', - 'ksp' => 'application/vnd.kde.kspread', - 'ktr' => 'application/vnd.kahootz', - 'ktx' => 'image/ktx', - 'ktz' => 'application/vnd.kahootz', - 'kwd' => 'application/vnd.kde.kword', - 'kwt' => 'application/vnd.kde.kword', - 'lasxml' => 'application/vnd.las.las+xml', - 'latex' => 'application/x-latex', - 'lbd' => 'application/vnd.llamagraphics.life-balance.desktop', - 'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml', - 'les' => 'application/vnd.hhe.lesson-player', - 'lha' => 'application/x-lzh-compressed', - 'link66' => 'application/vnd.route66.link66+xml', - 'list' => 'text/plain', - 'list3820' => 'application/vnd.ibm.modcap', - 'listafp' => 'application/vnd.ibm.modcap', - 'lnk' => 'application/x-ms-shortcut', - 'log' => 'text/plain', - 'lostxml' => 'application/lost+xml', - 'lrf' => 'application/octet-stream', - 'lrm' => 'application/vnd.ms-lrm', - 'ltf' => 'application/vnd.frogans.ltf', - 'lvp' => 'audio/vnd.lucent.voice', - 'lwp' => 'application/vnd.lotus-wordpro', - 'lzh' => 'application/x-lzh-compressed', - 'm13' => 'application/x-msmediaview', - 'm14' => 'application/x-msmediaview', - 'm1v' => 'video/mpeg', - 'm21' => 'application/mp21', - 'm2a' => 'audio/mpeg', - 'm2v' => 'video/mpeg', - 'm3a' => 'audio/mpeg', - 'm3u' => 'audio/x-mpegurl', - 'm3u8' => 'application/vnd.apple.mpegurl', - 'm4a' => 'audio/mp4', - 'm4u' => 'video/vnd.mpegurl', - 'm4v' => 'video/x-m4v', - 'ma' => 'application/mathematica', - 'mads' => 'application/mads+xml', - 'mag' => 'application/vnd.ecowin.chart', - 'maker' => 'application/vnd.framemaker', - 'man' => 'text/troff', - 'mar' => 'application/octet-stream', - 'mathml' => 'application/mathml+xml', - 'mb' => 'application/mathematica', - 'mbk' => 'application/vnd.mobius.mbk', - 'mbox' => 'application/mbox', - 'mc1' => 'application/vnd.medcalcdata', - 'mcd' => 'application/vnd.mcd', - 'mcurl' => 'text/vnd.curl.mcurl', - 'mdb' => 'application/x-msaccess', - 'mdi' => 'image/vnd.ms-modi', - 'me' => 'text/troff', - 'mesh' => 'model/mesh', - 'meta4' => 'application/metalink4+xml', - 'metalink' => 'application/metalink+xml', - 'mets' => 'application/mets+xml', - 'mfm' => 'application/vnd.mfmp', - 'mft' => 'application/rpki-manifest', - 'mgp' => 'application/vnd.osgeo.mapguide.package', - 'mgz' => 'application/vnd.proteus.magazine', - 'mid' => 'audio/midi', - 'midi' => 'audio/midi', - 'mie' => 'application/x-mie', - 'mif' => 'application/vnd.mif', - 'mime' => 'message/rfc822', - 'mj2' => 'video/mj2', - 'mjp2' => 'video/mj2', - 'mk3d' => 'video/x-matroska', - 'mka' => 'audio/x-matroska', - 'mks' => 'video/x-matroska', - 'mkv' => 'video/x-matroska', - 'mlp' => 'application/vnd.dolby.mlp', - 'mmd' => 'application/vnd.chipnuts.karaoke-mmd', - 'mmf' => 'application/vnd.smaf', - 'mmr' => 'image/vnd.fujixerox.edmics-mmr', - 'mng' => 'video/x-mng', - 'mny' => 'application/x-msmoney', - 'mobi' => 'application/x-mobipocket-ebook', - 'mods' => 'application/mods+xml', - 'mov' => 'video/quicktime', - 'movie' => 'video/x-sgi-movie', - 'mp2' => 'audio/mpeg', - 'mp21' => 'application/mp21', - 'mp2a' => 'audio/mpeg', - 'mp3' => 'audio/mpeg', - 'mp4' => 'video/mp4', - 'mp4a' => 'audio/mp4', - 'mp4s' => 'application/mp4', - 'mp4v' => 'video/mp4', - 'mpc' => 'application/vnd.mophun.certificate', - 'mpe' => 'video/mpeg', - 'mpeg' => 'video/mpeg', - 'mpg' => 'video/mpeg', - 'mpg4' => 'video/mp4', - 'mpga' => 'audio/mpeg', - 'mpkg' => 'application/vnd.apple.installer+xml', - 'mpm' => 'application/vnd.blueice.multipass', - 'mpn' => 'application/vnd.mophun.application', - 'mpp' => 'application/vnd.ms-project', - 'mpt' => 'application/vnd.ms-project', - 'mpy' => 'application/vnd.ibm.minipay', - 'mqy' => 'application/vnd.mobius.mqy', - 'mrc' => 'application/marc', - 'mrcx' => 'application/marcxml+xml', - 'ms' => 'text/troff', - 'mscml' => 'application/mediaservercontrol+xml', - 'mseed' => 'application/vnd.fdsn.mseed', - 'mseq' => 'application/vnd.mseq', - 'msf' => 'application/vnd.epson.msf', - 'msh' => 'model/mesh', - 'msi' => 'application/x-msdownload', - 'msl' => 'application/vnd.mobius.msl', - 'msty' => 'application/vnd.muvee.style', - 'mts' => 'model/vnd.mts', - 'mus' => 'application/vnd.musician', - 'musicxml' => 'application/vnd.recordare.musicxml+xml', - 'mvb' => 'application/x-msmediaview', - 'mwf' => 'application/vnd.mfer', - 'mxf' => 'application/mxf', - 'mxl' => 'application/vnd.recordare.musicxml', - 'mxml' => 'application/xv+xml', - 'mxs' => 'application/vnd.triscape.mxs', - 'mxu' => 'video/vnd.mpegurl', - 'n-gage' => 'application/vnd.nokia.n-gage.symbian.install', - 'n3' => 'text/n3', - 'nb' => 'application/mathematica', - 'nbp' => 'application/vnd.wolfram.player', - 'nc' => 'application/x-netcdf', - 'ncx' => 'application/x-dtbncx+xml', - 'nfo' => 'text/x-nfo', - 'ngdat' => 'application/vnd.nokia.n-gage.data', - 'nitf' => 'application/vnd.nitf', - 'nlu' => 'application/vnd.neurolanguage.nlu', - 'nml' => 'application/vnd.enliven', - 'nnd' => 'application/vnd.noblenet-directory', - 'nns' => 'application/vnd.noblenet-sealer', - 'nnw' => 'application/vnd.noblenet-web', - 'npx' => 'image/vnd.net-fpx', - 'nsc' => 'application/x-conference', - 'nsf' => 'application/vnd.lotus-notes', - 'ntf' => 'application/vnd.nitf', - 'nzb' => 'application/x-nzb', - 'oa2' => 'application/vnd.fujitsu.oasys2', - 'oa3' => 'application/vnd.fujitsu.oasys3', - 'oas' => 'application/vnd.fujitsu.oasys', - 'obd' => 'application/x-msbinder', - 'obj' => 'application/x-tgif', - 'oda' => 'application/oda', - 'odb' => 'application/vnd.oasis.opendocument.database', - 'odc' => 'application/vnd.oasis.opendocument.chart', - 'odf' => 'application/vnd.oasis.opendocument.formula', - 'odft' => 'application/vnd.oasis.opendocument.formula-template', - 'odg' => 'application/vnd.oasis.opendocument.graphics', - 'odi' => 'application/vnd.oasis.opendocument.image', - 'odm' => 'application/vnd.oasis.opendocument.text-master', - 'odp' => 'application/vnd.oasis.opendocument.presentation', - 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', - 'odt' => 'application/vnd.oasis.opendocument.text', - 'oga' => 'audio/ogg', - 'ogg' => 'audio/ogg', - 'ogv' => 'video/ogg', - 'ogx' => 'application/ogg', - 'omdoc' => 'application/omdoc+xml', - 'onepkg' => 'application/onenote', - 'onetmp' => 'application/onenote', - 'onetoc' => 'application/onenote', - 'onetoc2' => 'application/onenote', - 'opf' => 'application/oebps-package+xml', - 'opml' => 'text/x-opml', - 'oprc' => 'application/vnd.palm', - 'org' => 'application/vnd.lotus-organizer', - 'osf' => 'application/vnd.yamaha.openscoreformat', - 'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml', - 'otc' => 'application/vnd.oasis.opendocument.chart-template', - 'otf' => 'application/x-font-otf', - 'otg' => 'application/vnd.oasis.opendocument.graphics-template', - 'oth' => 'application/vnd.oasis.opendocument.text-web', - 'oti' => 'application/vnd.oasis.opendocument.image-template', - 'otp' => 'application/vnd.oasis.opendocument.presentation-template', - 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template', - 'ott' => 'application/vnd.oasis.opendocument.text-template', - 'oxps' => 'application/oxps', - 'oxt' => 'application/vnd.openofficeorg.extension', - 'p' => 'text/x-pascal', - 'p10' => 'application/pkcs10', - 'p12' => 'application/x-pkcs12', - 'p7b' => 'application/x-pkcs7-certificates', - 'p7c' => 'application/pkcs7-mime', - 'p7m' => 'application/pkcs7-mime', - 'p7r' => 'application/x-pkcs7-certreqresp', - 'p7s' => 'application/pkcs7-signature', - 'p8' => 'application/pkcs8', - 'pas' => 'text/x-pascal', - 'paw' => 'application/vnd.pawaafile', - 'pbd' => 'application/vnd.powerbuilder6', - 'pbm' => 'image/x-portable-bitmap', - 'pcap' => 'application/vnd.tcpdump.pcap', - 'pcf' => 'application/x-font-pcf', - 'pcl' => 'application/vnd.hp-pcl', - 'pclxl' => 'application/vnd.hp-pclxl', - 'pct' => 'image/x-pict', - 'pcurl' => 'application/vnd.curl.pcurl', - 'pcx' => 'image/x-pcx', - 'pdb' => 'application/vnd.palm', - 'pdf' => 'application/pdf', - 'pfa' => 'application/x-font-type1', - 'pfb' => 'application/x-font-type1', - 'pfm' => 'application/x-font-type1', - 'pfr' => 'application/font-tdpfr', - 'pfx' => 'application/x-pkcs12', - 'pgm' => 'image/x-portable-graymap', - 'pgn' => 'application/x-chess-pgn', - 'pgp' => 'application/pgp-encrypted', - 'php' => 'application/x-php', - 'php3' => 'application/x-php', - 'php4' => 'application/x-php', - 'php5' => 'application/x-php', - 'pic' => 'image/x-pict', - 'pkg' => 'application/octet-stream', - 'pki' => 'application/pkixcmp', - 'pkipath' => 'application/pkix-pkipath', - 'plb' => 'application/vnd.3gpp.pic-bw-large', - 'plc' => 'application/vnd.mobius.plc', - 'plf' => 'application/vnd.pocketlearn', - 'pls' => 'application/pls+xml', - 'pml' => 'application/vnd.ctc-posml', - 'png' => 'image/png', - 'pnm' => 'image/x-portable-anymap', - 'portpkg' => 'application/vnd.macports.portpkg', - 'pot' => 'application/vnd.ms-powerpoint', - 'potm' => 'application/vnd.ms-powerpoint.template.macroenabled.12', - 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template', - 'ppam' => 'application/vnd.ms-powerpoint.addin.macroenabled.12', - 'ppd' => 'application/vnd.cups-ppd', - 'ppm' => 'image/x-portable-pixmap', - 'pps' => 'application/vnd.ms-powerpoint', - 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroenabled.12', - 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', - 'ppt' => 'application/vnd.ms-powerpoint', - 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroenabled.12', - 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', - 'pqa' => 'application/vnd.palm', - 'prc' => 'application/x-mobipocket-ebook', - 'pre' => 'application/vnd.lotus-freelance', - 'prf' => 'application/pics-rules', - 'ps' => 'application/postscript', - 'psb' => 'application/vnd.3gpp.pic-bw-small', - 'psd' => 'image/vnd.adobe.photoshop', - 'psf' => 'application/x-font-linux-psf', - 'pskcxml' => 'application/pskc+xml', - 'ptid' => 'application/vnd.pvi.ptid1', - 'pub' => 'application/x-mspublisher', - 'pvb' => 'application/vnd.3gpp.pic-bw-var', - 'pwn' => 'application/vnd.3m.post-it-notes', - 'pya' => 'audio/vnd.ms-playready.media.pya', - 'pyv' => 'video/vnd.ms-playready.media.pyv', - 'qam' => 'application/vnd.epson.quickanime', - 'qbo' => 'application/vnd.intu.qbo', - 'qfx' => 'application/vnd.intu.qfx', - 'qps' => 'application/vnd.publishare-delta-tree', - 'qt' => 'video/quicktime', - 'qwd' => 'application/vnd.quark.quarkxpress', - 'qwt' => 'application/vnd.quark.quarkxpress', - 'qxb' => 'application/vnd.quark.quarkxpress', - 'qxd' => 'application/vnd.quark.quarkxpress', - 'qxl' => 'application/vnd.quark.quarkxpress', - 'qxt' => 'application/vnd.quark.quarkxpress', - 'ra' => 'audio/x-pn-realaudio', - 'ram' => 'audio/x-pn-realaudio', - 'rar' => 'application/x-rar-compressed', - 'ras' => 'image/x-cmu-raster', - 'rcprofile' => 'application/vnd.ipunplugged.rcprofile', - 'rdf' => 'application/rdf+xml', - 'rdz' => 'application/vnd.data-vision.rdz', - 'rep' => 'application/vnd.businessobjects', - 'res' => 'application/x-dtbresource+xml', - 'rgb' => 'image/x-rgb', - 'rif' => 'application/reginfo+xml', - 'rip' => 'audio/vnd.rip', - 'ris' => 'application/x-research-info-systems', - 'rl' => 'application/resource-lists+xml', - 'rlc' => 'image/vnd.fujixerox.edmics-rlc', - 'rld' => 'application/resource-lists-diff+xml', - 'rm' => 'application/vnd.rn-realmedia', - 'rmi' => 'audio/midi', - 'rmp' => 'audio/x-pn-realaudio-plugin', - 'rms' => 'application/vnd.jcp.javame.midlet-rms', - 'rmvb' => 'application/vnd.rn-realmedia-vbr', - 'rnc' => 'application/relax-ng-compact-syntax', - 'roa' => 'application/rpki-roa', - 'roff' => 'text/troff', - 'rp9' => 'application/vnd.cloanto.rp9', - 'rpss' => 'application/vnd.nokia.radio-presets', - 'rpst' => 'application/vnd.nokia.radio-preset', - 'rq' => 'application/sparql-query', - 'rs' => 'application/rls-services+xml', - 'rsd' => 'application/rsd+xml', - 'rss' => 'application/rss+xml', - 'rtf' => 'application/rtf', - 'rtx' => 'text/richtext', - 's' => 'text/x-asm', - 's3m' => 'audio/s3m', - 'saf' => 'application/vnd.yamaha.smaf-audio', - 'sbml' => 'application/sbml+xml', - 'sc' => 'application/vnd.ibm.secure-container', - 'scd' => 'application/x-msschedule', - 'scm' => 'application/vnd.lotus-screencam', - 'scq' => 'application/scvp-cv-request', - 'scs' => 'application/scvp-cv-response', - 'scurl' => 'text/vnd.curl.scurl', - 'sda' => 'application/vnd.stardivision.draw', - 'sdc' => 'application/vnd.stardivision.calc', - 'sdd' => 'application/vnd.stardivision.impress', - 'sdkd' => 'application/vnd.solent.sdkm+xml', - 'sdkm' => 'application/vnd.solent.sdkm+xml', - 'sdp' => 'application/sdp', - 'sdw' => 'application/vnd.stardivision.writer', - 'see' => 'application/vnd.seemail', - 'seed' => 'application/vnd.fdsn.seed', - 'sema' => 'application/vnd.sema', - 'semd' => 'application/vnd.semd', - 'semf' => 'application/vnd.semf', - 'ser' => 'application/java-serialized-object', - 'setpay' => 'application/set-payment-initiation', - 'setreg' => 'application/set-registration-initiation', - 'sfd-hdstx' => 'application/vnd.hydrostatix.sof-data', - 'sfs' => 'application/vnd.spotfire.sfs', - 'sfv' => 'text/x-sfv', - 'sgi' => 'image/sgi', - 'sgl' => 'application/vnd.stardivision.writer-global', - 'sgm' => 'text/sgml', - 'sgml' => 'text/sgml', - 'sh' => 'application/x-sh', - 'shar' => 'application/x-shar', - 'shf' => 'application/shf+xml', - 'sid' => 'image/x-mrsid-image', - 'sig' => 'application/pgp-signature', - 'sil' => 'audio/silk', - 'silo' => 'model/mesh', - 'sis' => 'application/vnd.symbian.install', - 'sisx' => 'application/vnd.symbian.install', - 'sit' => 'application/x-stuffit', - 'sitx' => 'application/x-stuffitx', - 'skd' => 'application/vnd.koan', - 'skm' => 'application/vnd.koan', - 'skp' => 'application/vnd.koan', - 'skt' => 'application/vnd.koan', - 'sldm' => 'application/vnd.ms-powerpoint.slide.macroenabled.12', - 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide', - 'slt' => 'application/vnd.epson.salt', - 'sm' => 'application/vnd.stepmania.stepchart', - 'smf' => 'application/vnd.stardivision.math', - 'smi' => 'application/smil+xml', - 'smil' => 'application/smil+xml', - 'smv' => 'video/x-smv', - 'smzip' => 'application/vnd.stepmania.package', - 'snd' => 'audio/basic', - 'snf' => 'application/x-font-snf', - 'so' => 'application/octet-stream', - 'spc' => 'application/x-pkcs7-certificates', - 'spf' => 'application/vnd.yamaha.smaf-phrase', - 'spl' => 'application/x-futuresplash', - 'spot' => 'text/vnd.in3d.spot', - 'spp' => 'application/scvp-vp-response', - 'spq' => 'application/scvp-vp-request', - 'spx' => 'audio/ogg', - 'sql' => 'application/x-sql', - 'src' => 'application/x-wais-source', - 'srt' => 'application/x-subrip', - 'sru' => 'application/sru+xml', - 'srx' => 'application/sparql-results+xml', - 'ssdl' => 'application/ssdl+xml', - 'sse' => 'application/vnd.kodak-descriptor', - 'ssf' => 'application/vnd.epson.ssf', - 'ssml' => 'application/ssml+xml', - 'st' => 'application/vnd.sailingtracker.track', - 'stc' => 'application/vnd.sun.xml.calc.template', - 'std' => 'application/vnd.sun.xml.draw.template', - 'stf' => 'application/vnd.wt.stf', - 'sti' => 'application/vnd.sun.xml.impress.template', - 'stk' => 'application/hyperstudio', - 'stl' => 'application/vnd.ms-pki.stl', - 'str' => 'application/vnd.pg.format', - 'stw' => 'application/vnd.sun.xml.writer.template', - 'sub' => 'text/vnd.dvb.subtitle', - 'sus' => 'application/vnd.sus-calendar', - 'susp' => 'application/vnd.sus-calendar', - 'sv4cpio' => 'application/x-sv4cpio', - 'sv4crc' => 'application/x-sv4crc', - 'svc' => 'application/vnd.dvb.service', - 'svd' => 'application/vnd.svd', - 'svg' => 'image/svg+xml', - 'svgz' => 'image/svg+xml', - 'swa' => 'application/x-director', - 'swf' => 'application/x-shockwave-flash', - 'swi' => 'application/vnd.aristanetworks.swi', - 'sxc' => 'application/vnd.sun.xml.calc', - 'sxd' => 'application/vnd.sun.xml.draw', - 'sxg' => 'application/vnd.sun.xml.writer.global', - 'sxi' => 'application/vnd.sun.xml.impress', - 'sxm' => 'application/vnd.sun.xml.math', - 'sxw' => 'application/vnd.sun.xml.writer', - 't' => 'text/troff', - 't3' => 'application/x-t3vm-image', - 'taglet' => 'application/vnd.mynfc', - 'tao' => 'application/vnd.tao.intent-module-archive', - 'tar' => 'application/x-tar', - 'tcap' => 'application/vnd.3gpp2.tcap', - 'tcl' => 'application/x-tcl', - 'teacher' => 'application/vnd.smart.teacher', - 'tei' => 'application/tei+xml', - 'teicorpus' => 'application/tei+xml', - 'tex' => 'application/x-tex', - 'texi' => 'application/x-texinfo', - 'texinfo' => 'application/x-texinfo', - 'text' => 'text/plain', - 'tfi' => 'application/thraud+xml', - 'tfm' => 'application/x-tex-tfm', - 'tga' => 'image/x-tga', - 'thmx' => 'application/vnd.ms-officetheme', - 'tif' => 'image/tiff', - 'tiff' => 'image/tiff', - 'tmo' => 'application/vnd.tmobile-livetv', - 'torrent' => 'application/x-bittorrent', - 'tpl' => 'application/vnd.groove-tool-template', - 'tpt' => 'application/vnd.trid.tpt', - 'tr' => 'text/troff', - 'tra' => 'application/vnd.trueapp', - 'trm' => 'application/x-msterminal', - 'tsd' => 'application/timestamped-data', - 'tsv' => 'text/tab-separated-values', - 'ttc' => 'application/x-font-ttf', - 'ttf' => 'application/x-font-ttf', - 'ttl' => 'text/turtle', - 'twd' => 'application/vnd.simtech-mindmapper', - 'twds' => 'application/vnd.simtech-mindmapper', - 'txd' => 'application/vnd.genomatix.tuxedo', - 'txf' => 'application/vnd.mobius.txf', - 'txt' => 'text/plain', - 'u32' => 'application/x-authorware-bin', - 'udeb' => 'application/x-debian-package', - 'ufd' => 'application/vnd.ufdl', - 'ufdl' => 'application/vnd.ufdl', - 'ulx' => 'application/x-glulx', - 'umj' => 'application/vnd.umajin', - 'unityweb' => 'application/vnd.unity', - 'uoml' => 'application/vnd.uoml+xml', - 'uri' => 'text/uri-list', - 'uris' => 'text/uri-list', - 'urls' => 'text/uri-list', - 'ustar' => 'application/x-ustar', - 'utz' => 'application/vnd.uiq.theme', - 'uu' => 'text/x-uuencode', - 'uva' => 'audio/vnd.dece.audio', - 'uvd' => 'application/vnd.dece.data', - 'uvf' => 'application/vnd.dece.data', - 'uvg' => 'image/vnd.dece.graphic', - 'uvh' => 'video/vnd.dece.hd', - 'uvi' => 'image/vnd.dece.graphic', - 'uvm' => 'video/vnd.dece.mobile', - 'uvp' => 'video/vnd.dece.pd', - 'uvs' => 'video/vnd.dece.sd', - 'uvt' => 'application/vnd.dece.ttml+xml', - 'uvu' => 'video/vnd.uvvu.mp4', - 'uvv' => 'video/vnd.dece.video', - 'uvva' => 'audio/vnd.dece.audio', - 'uvvd' => 'application/vnd.dece.data', - 'uvvf' => 'application/vnd.dece.data', - 'uvvg' => 'image/vnd.dece.graphic', - 'uvvh' => 'video/vnd.dece.hd', - 'uvvi' => 'image/vnd.dece.graphic', - 'uvvm' => 'video/vnd.dece.mobile', - 'uvvp' => 'video/vnd.dece.pd', - 'uvvs' => 'video/vnd.dece.sd', - 'uvvt' => 'application/vnd.dece.ttml+xml', - 'uvvu' => 'video/vnd.uvvu.mp4', - 'uvvv' => 'video/vnd.dece.video', - 'uvvx' => 'application/vnd.dece.unspecified', - 'uvvz' => 'application/vnd.dece.zip', - 'uvx' => 'application/vnd.dece.unspecified', - 'uvz' => 'application/vnd.dece.zip', - 'vcard' => 'text/vcard', - 'vcd' => 'application/x-cdlink', - 'vcf' => 'text/x-vcard', - 'vcg' => 'application/vnd.groove-vcard', - 'vcs' => 'text/x-vcalendar', - 'vcx' => 'application/vnd.vcx', - 'vis' => 'application/vnd.visionary', - 'viv' => 'video/vnd.vivo', - 'vob' => 'video/x-ms-vob', - 'vor' => 'application/vnd.stardivision.writer', - 'vox' => 'application/x-authorware-bin', - 'vrml' => 'model/vrml', - 'vsd' => 'application/vnd.visio', - 'vsf' => 'application/vnd.vsf', - 'vss' => 'application/vnd.visio', - 'vst' => 'application/vnd.visio', - 'vsw' => 'application/vnd.visio', - 'vtu' => 'model/vnd.vtu', - 'vxml' => 'application/voicexml+xml', - 'w3d' => 'application/x-director', - 'wad' => 'application/x-doom', - 'wav' => 'audio/x-wav', - 'wax' => 'audio/x-ms-wax', - 'wbmp' => 'image/vnd.wap.wbmp', - 'wbs' => 'application/vnd.criticaltools.wbs+xml', - 'wbxml' => 'application/vnd.wap.wbxml', - 'wcm' => 'application/vnd.ms-works', - 'wdb' => 'application/vnd.ms-works', - 'wdp' => 'image/vnd.ms-photo', - 'weba' => 'audio/webm', - 'webm' => 'video/webm', - 'webp' => 'image/webp', - 'wg' => 'application/vnd.pmi.widget', - 'wgt' => 'application/widget', - 'wks' => 'application/vnd.ms-works', - 'wm' => 'video/x-ms-wm', - 'wma' => 'audio/x-ms-wma', - 'wmd' => 'application/x-ms-wmd', - 'wmf' => 'application/x-msmetafile', - 'wml' => 'text/vnd.wap.wml', - 'wmlc' => 'application/vnd.wap.wmlc', - 'wmls' => 'text/vnd.wap.wmlscript', - 'wmlsc' => 'application/vnd.wap.wmlscriptc', - 'wmv' => 'video/x-ms-wmv', - 'wmx' => 'video/x-ms-wmx', - 'wmz' => 'application/x-msmetafile', - 'woff' => 'application/font-woff', - 'wpd' => 'application/vnd.wordperfect', - 'wpl' => 'application/vnd.ms-wpl', - 'wps' => 'application/vnd.ms-works', - 'wqd' => 'application/vnd.wqd', - 'wri' => 'application/x-mswrite', - 'wrl' => 'model/vrml', - 'wsdl' => 'application/wsdl+xml', - 'wspolicy' => 'application/wspolicy+xml', - 'wtb' => 'application/vnd.webturbo', - 'wvx' => 'video/x-ms-wvx', - 'x32' => 'application/x-authorware-bin', - 'x3d' => 'model/x3d+xml', - 'x3db' => 'model/x3d+binary', - 'x3dbz' => 'model/x3d+binary', - 'x3dv' => 'model/x3d+vrml', - 'x3dvz' => 'model/x3d+vrml', - 'x3dz' => 'model/x3d+xml', - 'xaml' => 'application/xaml+xml', - 'xap' => 'application/x-silverlight-app', - 'xar' => 'application/vnd.xara', - 'xbap' => 'application/x-ms-xbap', - 'xbd' => 'application/vnd.fujixerox.docuworks.binder', - 'xbm' => 'image/x-xbitmap', - 'xdf' => 'application/xcap-diff+xml', - 'xdm' => 'application/vnd.syncml.dm+xml', - 'xdp' => 'application/vnd.adobe.xdp+xml', - 'xdssc' => 'application/dssc+xml', - 'xdw' => 'application/vnd.fujixerox.docuworks', - 'xenc' => 'application/xenc+xml', - 'xer' => 'application/patch-ops-error+xml', - 'xfdf' => 'application/vnd.adobe.xfdf', - 'xfdl' => 'application/vnd.xfdl', - 'xht' => 'application/xhtml+xml', - 'xhtml' => 'application/xhtml+xml', - 'xhvml' => 'application/xv+xml', - 'xif' => 'image/vnd.xiff', - 'xla' => 'application/vnd.ms-excel', - 'xlam' => 'application/vnd.ms-excel.addin.macroenabled.12', - 'xlc' => 'application/vnd.ms-excel', - 'xlf' => 'application/x-xliff+xml', - 'xlm' => 'application/vnd.ms-excel', - 'xls' => 'application/vnd.ms-excel', - 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroenabled.12', - 'xlsm' => 'application/vnd.ms-excel.sheet.macroenabled.12', - 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', - 'xlt' => 'application/vnd.ms-excel', - 'xltm' => 'application/vnd.ms-excel.template.macroenabled.12', - 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', - 'xlw' => 'application/vnd.ms-excel', - 'xm' => 'audio/xm', - 'xml' => 'application/xml', - 'xo' => 'application/vnd.olpc-sugar', - 'xop' => 'application/xop+xml', - 'xpi' => 'application/x-xpinstall', - 'xpl' => 'application/xproc+xml', - 'xpm' => 'image/x-xpixmap', - 'xpr' => 'application/vnd.is-xpr', - 'xps' => 'application/vnd.ms-xpsdocument', - 'xpw' => 'application/vnd.intercon.formnet', - 'xpx' => 'application/vnd.intercon.formnet', - 'xsl' => 'application/xml', - 'xslt' => 'application/xslt+xml', - 'xsm' => 'application/vnd.syncml+xml', - 'xspf' => 'application/xspf+xml', - 'xul' => 'application/vnd.mozilla.xul+xml', - 'xvm' => 'application/xv+xml', - 'xvml' => 'application/xv+xml', - 'xwd' => 'image/x-xwindowdump', - 'xyz' => 'chemical/x-xyz', - 'xz' => 'application/x-xz', - 'yang' => 'application/yang', - 'yin' => 'application/yin+xml', - 'z1' => 'application/x-zmachine', - 'z2' => 'application/x-zmachine', - 'z3' => 'application/x-zmachine', - 'z4' => 'application/x-zmachine', - 'z5' => 'application/x-zmachine', - 'z6' => 'application/x-zmachine', - 'z7' => 'application/x-zmachine', - 'z8' => 'application/x-zmachine', - 'zaz' => 'application/vnd.zzazz.deck+xml', - 'zip' => 'application/zip', - 'zir' => 'application/vnd.zul', - 'zirz' => 'application/vnd.zul', - 'zmm' => 'application/vnd.handheld-entertainment+xml', - '123' => 'application/vnd.lotus-1-2-3', + '3dml' => 'text/vnd.in3d.3dml', + '3ds' => 'image/x-3ds', + '3g2' => 'video/3gpp2', + '3gp' => 'video/3gpp', + '7z' => 'application/x-7z-compressed', + 'aab' => 'application/x-authorware-bin', + 'aac' => 'audio/x-aac', + 'aam' => 'application/x-authorware-map', + 'aas' => 'application/x-authorware-seg', + 'abw' => 'application/x-abiword', + 'ac' => 'application/pkix-attr-cert', + 'acc' => 'application/vnd.americandynamics.acc', + 'ace' => 'application/x-ace-compressed', + 'acu' => 'application/vnd.acucobol', + 'acutc' => 'application/vnd.acucorp', + 'adp' => 'audio/adpcm', + 'aep' => 'application/vnd.audiograph', + 'afm' => 'application/x-font-type1', + 'afp' => 'application/vnd.ibm.modcap', + 'ahead' => 'application/vnd.ahead.space', + 'ai' => 'application/postscript', + 'aif' => 'audio/x-aiff', + 'aifc' => 'audio/x-aiff', + 'aiff' => 'audio/x-aiff', + 'air' => 'application/vnd.adobe.air-application-installer-package+zip', + 'ait' => 'application/vnd.dvb.ait', + 'ami' => 'application/vnd.amiga.ami', + 'apk' => 'application/vnd.android.package-archive', + 'appcache' => 'text/cache-manifest', + 'apr' => 'application/vnd.lotus-approach', + 'aps' => 'application/postscript', + 'arc' => 'application/x-freearc', + 'asc' => 'application/pgp-signature', + 'asf' => 'video/x-ms-asf', + 'asm' => 'text/x-asm', + 'aso' => 'application/vnd.accpac.simply.aso', + 'asx' => 'video/x-ms-asf', + 'atc' => 'application/vnd.acucorp', + 'atom' => 'application/atom+xml', + 'atomcat' => 'application/atomcat+xml', + 'atomsvc' => 'application/atomsvc+xml', + 'atx' => 'application/vnd.antix.game-component', + 'au' => 'audio/basic', + 'avi' => 'video/x-msvideo', + 'aw' => 'application/applixware', + 'azf' => 'application/vnd.airzip.filesecure.azf', + 'azs' => 'application/vnd.airzip.filesecure.azs', + 'azw' => 'application/vnd.amazon.ebook', + 'bat' => 'application/x-msdownload', + 'bcpio' => 'application/x-bcpio', + 'bdf' => 'application/x-font-bdf', + 'bdm' => 'application/vnd.syncml.dm+wbxml', + 'bed' => 'application/vnd.realvnc.bed', + 'bh2' => 'application/vnd.fujitsu.oasysprs', + 'bin' => 'application/octet-stream', + 'blb' => 'application/x-blorb', + 'blorb' => 'application/x-blorb', + 'bmi' => 'application/vnd.bmi', + 'bmp' => 'image/bmp', + 'book' => 'application/vnd.framemaker', + 'box' => 'application/vnd.previewsystems.box', + 'boz' => 'application/x-bzip2', + 'bpk' => 'application/octet-stream', + 'btif' => 'image/prs.btif', + 'bz' => 'application/x-bzip', + 'bz2' => 'application/x-bzip2', + 'c' => 'text/x-c', + 'c11amc' => 'application/vnd.cluetrust.cartomobile-config', + 'c11amz' => 'application/vnd.cluetrust.cartomobile-config-pkg', + 'c4d' => 'application/vnd.clonk.c4group', + 'c4f' => 'application/vnd.clonk.c4group', + 'c4g' => 'application/vnd.clonk.c4group', + 'c4p' => 'application/vnd.clonk.c4group', + 'c4u' => 'application/vnd.clonk.c4group', + 'cab' => 'application/vnd.ms-cab-compressed', + 'caf' => 'audio/x-caf', + 'cap' => 'application/vnd.tcpdump.pcap', + 'car' => 'application/vnd.curl.car', + 'cat' => 'application/vnd.ms-pki.seccat', + 'cb7' => 'application/x-cbr', + 'cba' => 'application/x-cbr', + 'cbr' => 'application/x-cbr', + 'cbt' => 'application/x-cbr', + 'cbz' => 'application/x-cbr', + 'cc' => 'text/x-c', + 'cct' => 'application/x-director', + 'ccxml' => 'application/ccxml+xml', + 'cdbcmsg' => 'application/vnd.contact.cmsg', + 'cdf' => 'application/x-netcdf', + 'cdkey' => 'application/vnd.mediastation.cdkey', + 'cdmia' => 'application/cdmi-capability', + 'cdmic' => 'application/cdmi-container', + 'cdmid' => 'application/cdmi-domain', + 'cdmio' => 'application/cdmi-object', + 'cdmiq' => 'application/cdmi-queue', + 'cdx' => 'chemical/x-cdx', + 'cdxml' => 'application/vnd.chemdraw+xml', + 'cdy' => 'application/vnd.cinderella', + 'cer' => 'application/pkix-cert', + 'cfs' => 'application/x-cfs-compressed', + 'cgm' => 'image/cgm', + 'chat' => 'application/x-chat', + 'chm' => 'application/vnd.ms-htmlhelp', + 'chrt' => 'application/vnd.kde.kchart', + 'cif' => 'chemical/x-cif', + 'cii' => 'application/vnd.anser-web-certificate-issue-initiation', + 'cil' => 'application/vnd.ms-artgalry', + 'cla' => 'application/vnd.claymore', + 'class' => 'application/java-vm', + 'clkk' => 'application/vnd.crick.clicker.keyboard', + 'clkp' => 'application/vnd.crick.clicker.palette', + 'clkt' => 'application/vnd.crick.clicker.template', + 'clkw' => 'application/vnd.crick.clicker.wordbank', + 'clkx' => 'application/vnd.crick.clicker', + 'clp' => 'application/x-msclip', + 'cmc' => 'application/vnd.cosmocaller', + 'cmdf' => 'chemical/x-cmdf', + 'cml' => 'chemical/x-cml', + 'cmp' => 'application/vnd.yellowriver-custom-menu', + 'cmx' => 'image/x-cmx', + 'cod' => 'application/vnd.rim.cod', + 'com' => 'application/x-msdownload', + 'conf' => 'text/plain', + 'cpio' => 'application/x-cpio', + 'cpp' => 'text/x-c', + 'cpt' => 'application/mac-compactpro', + 'crd' => 'application/x-mscardfile', + 'crl' => 'application/pkix-crl', + 'crt' => 'application/x-x509-ca-cert', + 'csh' => 'application/x-csh', + 'csml' => 'chemical/x-csml', + 'csp' => 'application/vnd.commonspace', + 'css' => 'text/css', + 'cst' => 'application/x-director', + 'csv' => 'text/csv', + 'cu' => 'application/cu-seeme', + 'curl' => 'text/vnd.curl', + 'cww' => 'application/prs.cww', + 'cxt' => 'application/x-director', + 'cxx' => 'text/x-c', + 'dae' => 'model/vnd.collada+xml', + 'daf' => 'application/vnd.mobius.daf', + 'dart' => 'application/vnd.dart', + 'dataless' => 'application/vnd.fdsn.seed', + 'davmount' => 'application/davmount+xml', + 'dbk' => 'application/docbook+xml', + 'dcr' => 'application/x-director', + 'dcurl' => 'text/vnd.curl.dcurl', + 'dd2' => 'application/vnd.oma.dd2+xml', + 'ddd' => 'application/vnd.fujixerox.ddd', + 'deb' => 'application/x-debian-package', + 'def' => 'text/plain', + 'deploy' => 'application/octet-stream', + 'der' => 'application/x-x509-ca-cert', + 'dfac' => 'application/vnd.dreamfactory', + 'dgc' => 'application/x-dgc-compressed', + 'dic' => 'text/x-c', + 'dir' => 'application/x-director', + 'dis' => 'application/vnd.mobius.dis', + 'dist' => 'application/octet-stream', + 'distz' => 'application/octet-stream', + 'djv' => 'image/vnd.djvu', + 'djvu' => 'image/vnd.djvu', + 'dll' => 'application/x-msdownload', + 'dmg' => 'application/x-apple-diskimage', + 'dmp' => 'application/vnd.tcpdump.pcap', + 'dms' => 'application/octet-stream', + 'dna' => 'application/vnd.dna', + 'doc' => 'application/msword', + 'docm' => 'application/vnd.ms-word.document.macroenabled.12', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'dot' => 'application/msword', + 'dotm' => 'application/vnd.ms-word.template.macroenabled.12', + 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', + 'dp' => 'application/vnd.osgi.dp', + 'dpg' => 'application/vnd.dpgraph', + 'dra' => 'audio/vnd.dra', + 'dsc' => 'text/prs.lines.tag', + 'dssc' => 'application/dssc+der', + 'dtb' => 'application/x-dtbook+xml', + 'dtd' => 'application/xml-dtd', + 'dts' => 'audio/vnd.dts', + 'dtshd' => 'audio/vnd.dts.hd', + 'dump' => 'application/octet-stream', + 'dvb' => 'video/vnd.dvb.file', + 'dvi' => 'application/x-dvi', + 'dwf' => 'model/vnd.dwf', + 'dwg' => 'image/vnd.dwg', + 'dxf' => 'image/vnd.dxf', + 'dxp' => 'application/vnd.spotfire.dxp', + 'dxr' => 'application/x-director', + 'ecelp4800' => 'audio/vnd.nuera.ecelp4800', + 'ecelp7470' => 'audio/vnd.nuera.ecelp7470', + 'ecelp9600' => 'audio/vnd.nuera.ecelp9600', + 'ecma' => 'application/ecmascript', + 'edm' => 'application/vnd.novadigm.edm', + 'edx' => 'application/vnd.novadigm.edx', + 'efif' => 'application/vnd.picsel', + 'ei6' => 'application/vnd.pg.osasli', + 'elc' => 'application/octet-stream', + 'emf' => 'application/x-msmetafile', + 'eml' => 'message/rfc822', + 'emma' => 'application/emma+xml', + 'emz' => 'application/x-msmetafile', + 'eol' => 'audio/vnd.digital-winds', + 'eot' => 'application/vnd.ms-fontobject', + 'eps' => 'application/postscript', + 'epub' => 'application/epub+zip', + 'es3' => 'application/vnd.eszigno3+xml', + 'esa' => 'application/vnd.osgi.subsystem', + 'esf' => 'application/vnd.epson.esf', + 'et3' => 'application/vnd.eszigno3+xml', + 'etx' => 'text/x-setext', + 'eva' => 'application/x-eva', + 'evy' => 'application/x-envoy', + 'exe' => 'application/x-msdownload', + 'exi' => 'application/exi', + 'ext' => 'application/vnd.novadigm.ext', + 'ez' => 'application/andrew-inset', + 'ez2' => 'application/vnd.ezpix-album', + 'ez3' => 'application/vnd.ezpix-package', + 'f' => 'text/x-fortran', + 'f4v' => 'video/x-f4v', + 'f77' => 'text/x-fortran', + 'f90' => 'text/x-fortran', + 'fbs' => 'image/vnd.fastbidsheet', + 'fcdt' => 'application/vnd.adobe.formscentral.fcdt', + 'fcs' => 'application/vnd.isac.fcs', + 'fdf' => 'application/vnd.fdf', + 'fe_launch' => 'application/vnd.denovo.fcselayout-link', + 'fg5' => 'application/vnd.fujitsu.oasysgp', + 'fgd' => 'application/x-director', + 'fh' => 'image/x-freehand', + 'fh4' => 'image/x-freehand', + 'fh5' => 'image/x-freehand', + 'fh7' => 'image/x-freehand', + 'fhc' => 'image/x-freehand', + 'fig' => 'application/x-xfig', + 'flac' => 'audio/x-flac', + 'fli' => 'video/x-fli', + 'flo' => 'application/vnd.micrografx.flo', + 'flv' => 'video/x-flv', + 'flw' => 'application/vnd.kde.kivio', + 'flx' => 'text/vnd.fmi.flexstor', + 'fly' => 'text/vnd.fly', + 'fm' => 'application/vnd.framemaker', + 'fnc' => 'application/vnd.frogans.fnc', + 'for' => 'text/x-fortran', + 'fpx' => 'image/vnd.fpx', + 'frame' => 'application/vnd.framemaker', + 'fsc' => 'application/vnd.fsc.weblaunch', + 'fst' => 'image/vnd.fst', + 'ftc' => 'application/vnd.fluxtime.clip', + 'fti' => 'application/vnd.anser-web-funds-transfer-initiation', + 'fvt' => 'video/vnd.fvt', + 'fxp' => 'application/vnd.adobe.fxp', + 'fxpl' => 'application/vnd.adobe.fxp', + 'fzs' => 'application/vnd.fuzzysheet', + 'g2w' => 'application/vnd.geoplan', + 'g3' => 'image/g3fax', + 'g3w' => 'application/vnd.geospace', + 'gac' => 'application/vnd.groove-account', + 'gam' => 'application/x-tads', + 'gbr' => 'application/rpki-ghostbusters', + 'gca' => 'application/x-gca-compressed', + 'gdl' => 'model/vnd.gdl', + 'geo' => 'application/vnd.dynageo', + 'gex' => 'application/vnd.geometry-explorer', + 'ggb' => 'application/vnd.geogebra.file', + 'ggt' => 'application/vnd.geogebra.tool', + 'ghf' => 'application/vnd.groove-help', + 'gif' => 'image/gif', + 'gim' => 'application/vnd.groove-identity-message', + 'gml' => 'application/gml+xml', + 'gmx' => 'application/vnd.gmx', + 'gnumeric' => 'application/x-gnumeric', + 'gph' => 'application/vnd.flographit', + 'gpx' => 'application/gpx+xml', + 'gqf' => 'application/vnd.grafeq', + 'gqs' => 'application/vnd.grafeq', + 'gram' => 'application/srgs', + 'gramps' => 'application/x-gramps-xml', + 'gre' => 'application/vnd.geometry-explorer', + 'grv' => 'application/vnd.groove-injector', + 'grxml' => 'application/srgs+xml', + 'gsf' => 'application/x-font-ghostscript', + 'gtar' => 'application/x-gtar', + 'gtm' => 'application/vnd.groove-tool-message', + 'gtw' => 'model/vnd.gtw', + 'gv' => 'text/vnd.graphviz', + 'gxf' => 'application/gxf', + 'gxt' => 'application/vnd.geonext', + 'gz' => 'application/x-gzip', + 'h' => 'text/x-c', + 'h261' => 'video/h261', + 'h263' => 'video/h263', + 'h264' => 'video/h264', + 'hal' => 'application/vnd.hal+xml', + 'hbci' => 'application/vnd.hbci', + 'hdf' => 'application/x-hdf', + 'hh' => 'text/x-c', + 'hlp' => 'application/winhlp', + 'hpgl' => 'application/vnd.hp-hpgl', + 'hpid' => 'application/vnd.hp-hpid', + 'hps' => 'application/vnd.hp-hps', + 'hqx' => 'application/mac-binhex40', + 'htke' => 'application/vnd.kenameaapp', + 'htm' => 'text/html', + 'html' => 'text/html', + 'hvd' => 'application/vnd.yamaha.hv-dic', + 'hvp' => 'application/vnd.yamaha.hv-voice', + 'hvs' => 'application/vnd.yamaha.hv-script', + 'i2g' => 'application/vnd.intergeo', + 'icc' => 'application/vnd.iccprofile', + 'ice' => 'x-conference/x-cooltalk', + 'icm' => 'application/vnd.iccprofile', + 'ico' => 'image/x-icon', + 'ics' => 'text/calendar', + 'ief' => 'image/ief', + 'ifb' => 'text/calendar', + 'ifm' => 'application/vnd.shana.informed.formdata', + 'iges' => 'model/iges', + 'igl' => 'application/vnd.igloader', + 'igm' => 'application/vnd.insors.igm', + 'igs' => 'model/iges', + 'igx' => 'application/vnd.micrografx.igx', + 'iif' => 'application/vnd.shana.informed.interchange', + 'imp' => 'application/vnd.accpac.simply.imp', + 'ims' => 'application/vnd.ms-ims', + 'in' => 'text/plain', + 'ink' => 'application/inkml+xml', + 'inkml' => 'application/inkml+xml', + 'install' => 'application/x-install-instructions', + 'iota' => 'application/vnd.astraea-software.iota', + 'ipfix' => 'application/ipfix', + 'ipk' => 'application/vnd.shana.informed.package', + 'irm' => 'application/vnd.ibm.rights-management', + 'irp' => 'application/vnd.irepository.package+xml', + 'iso' => 'application/x-iso9660-image', + 'itp' => 'application/vnd.shana.informed.formtemplate', + 'ivp' => 'application/vnd.immervision-ivp', + 'ivu' => 'application/vnd.immervision-ivu', + 'jad' => 'text/vnd.sun.j2me.app-descriptor', + 'jam' => 'application/vnd.jam', + 'jar' => 'application/java-archive', + 'java' => 'text/x-java-source', + 'jisp' => 'application/vnd.jisp', + 'jlt' => 'application/vnd.hp-jlyt', + 'jnlp' => 'application/x-java-jnlp-file', + 'joda' => 'application/vnd.joost.joda-archive', + 'jpe' => 'image/jpeg', + 'jpeg' => 'image/jpeg', + 'jpg' => 'image/jpeg', + 'jpgm' => 'video/jpm', + 'jpgv' => 'video/jpeg', + 'jpm' => 'video/jpm', + 'js' => 'application/javascript', + 'json' => 'application/json', + 'jsonml' => 'application/jsonml+json', + 'kar' => 'audio/midi', + 'karbon' => 'application/vnd.kde.karbon', + 'kfo' => 'application/vnd.kde.kformula', + 'kia' => 'application/vnd.kidspiration', + 'kml' => 'application/vnd.google-earth.kml+xml', + 'kmz' => 'application/vnd.google-earth.kmz', + 'kne' => 'application/vnd.kinar', + 'knp' => 'application/vnd.kinar', + 'kon' => 'application/vnd.kde.kontour', + 'kpr' => 'application/vnd.kde.kpresenter', + 'kpt' => 'application/vnd.kde.kpresenter', + 'kpxx' => 'application/vnd.ds-keypoint', + 'ksp' => 'application/vnd.kde.kspread', + 'ktr' => 'application/vnd.kahootz', + 'ktx' => 'image/ktx', + 'ktz' => 'application/vnd.kahootz', + 'kwd' => 'application/vnd.kde.kword', + 'kwt' => 'application/vnd.kde.kword', + 'lasxml' => 'application/vnd.las.las+xml', + 'latex' => 'application/x-latex', + 'lbd' => 'application/vnd.llamagraphics.life-balance.desktop', + 'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml', + 'les' => 'application/vnd.hhe.lesson-player', + 'lha' => 'application/x-lzh-compressed', + 'link66' => 'application/vnd.route66.link66+xml', + 'list' => 'text/plain', + 'list3820' => 'application/vnd.ibm.modcap', + 'listafp' => 'application/vnd.ibm.modcap', + 'lnk' => 'application/x-ms-shortcut', + 'log' => 'text/plain', + 'lostxml' => 'application/lost+xml', + 'lrf' => 'application/octet-stream', + 'lrm' => 'application/vnd.ms-lrm', + 'ltf' => 'application/vnd.frogans.ltf', + 'lvp' => 'audio/vnd.lucent.voice', + 'lwp' => 'application/vnd.lotus-wordpro', + 'lzh' => 'application/x-lzh-compressed', + 'm13' => 'application/x-msmediaview', + 'm14' => 'application/x-msmediaview', + 'm1v' => 'video/mpeg', + 'm21' => 'application/mp21', + 'm2a' => 'audio/mpeg', + 'm2v' => 'video/mpeg', + 'm3a' => 'audio/mpeg', + 'm3u' => 'audio/x-mpegurl', + 'm3u8' => 'application/vnd.apple.mpegurl', + 'm4a' => 'audio/mp4', + 'm4u' => 'video/vnd.mpegurl', + 'm4v' => 'video/x-m4v', + 'ma' => 'application/mathematica', + 'mads' => 'application/mads+xml', + 'mag' => 'application/vnd.ecowin.chart', + 'maker' => 'application/vnd.framemaker', + 'man' => 'text/troff', + 'mar' => 'application/octet-stream', + 'mathml' => 'application/mathml+xml', + 'mb' => 'application/mathematica', + 'mbk' => 'application/vnd.mobius.mbk', + 'mbox' => 'application/mbox', + 'mc1' => 'application/vnd.medcalcdata', + 'mcd' => 'application/vnd.mcd', + 'mcurl' => 'text/vnd.curl.mcurl', + 'mdb' => 'application/x-msaccess', + 'mdi' => 'image/vnd.ms-modi', + 'me' => 'text/troff', + 'mesh' => 'model/mesh', + 'meta4' => 'application/metalink4+xml', + 'metalink' => 'application/metalink+xml', + 'mets' => 'application/mets+xml', + 'mfm' => 'application/vnd.mfmp', + 'mft' => 'application/rpki-manifest', + 'mgp' => 'application/vnd.osgeo.mapguide.package', + 'mgz' => 'application/vnd.proteus.magazine', + 'mid' => 'audio/midi', + 'midi' => 'audio/midi', + 'mie' => 'application/x-mie', + 'mif' => 'application/vnd.mif', + 'mime' => 'message/rfc822', + 'mj2' => 'video/mj2', + 'mjp2' => 'video/mj2', + 'mk3d' => 'video/x-matroska', + 'mka' => 'audio/x-matroska', + 'mks' => 'video/x-matroska', + 'mkv' => 'video/x-matroska', + 'mlp' => 'application/vnd.dolby.mlp', + 'mmd' => 'application/vnd.chipnuts.karaoke-mmd', + 'mmf' => 'application/vnd.smaf', + 'mmr' => 'image/vnd.fujixerox.edmics-mmr', + 'mng' => 'video/x-mng', + 'mny' => 'application/x-msmoney', + 'mobi' => 'application/x-mobipocket-ebook', + 'mods' => 'application/mods+xml', + 'mov' => 'video/quicktime', + 'movie' => 'video/x-sgi-movie', + 'mp2' => 'audio/mpeg', + 'mp21' => 'application/mp21', + 'mp2a' => 'audio/mpeg', + 'mp3' => 'audio/mpeg', + 'mp4' => 'video/mp4', + 'mp4a' => 'audio/mp4', + 'mp4s' => 'application/mp4', + 'mp4v' => 'video/mp4', + 'mpc' => 'application/vnd.mophun.certificate', + 'mpe' => 'video/mpeg', + 'mpeg' => 'video/mpeg', + 'mpg' => 'video/mpeg', + 'mpg4' => 'video/mp4', + 'mpga' => 'audio/mpeg', + 'mpkg' => 'application/vnd.apple.installer+xml', + 'mpm' => 'application/vnd.blueice.multipass', + 'mpn' => 'application/vnd.mophun.application', + 'mpp' => 'application/vnd.ms-project', + 'mpt' => 'application/vnd.ms-project', + 'mpy' => 'application/vnd.ibm.minipay', + 'mqy' => 'application/vnd.mobius.mqy', + 'mrc' => 'application/marc', + 'mrcx' => 'application/marcxml+xml', + 'ms' => 'text/troff', + 'mscml' => 'application/mediaservercontrol+xml', + 'mseed' => 'application/vnd.fdsn.mseed', + 'mseq' => 'application/vnd.mseq', + 'msf' => 'application/vnd.epson.msf', + 'msh' => 'model/mesh', + 'msi' => 'application/x-msdownload', + 'msl' => 'application/vnd.mobius.msl', + 'msty' => 'application/vnd.muvee.style', + 'mts' => 'model/vnd.mts', + 'mus' => 'application/vnd.musician', + 'musicxml' => 'application/vnd.recordare.musicxml+xml', + 'mvb' => 'application/x-msmediaview', + 'mwf' => 'application/vnd.mfer', + 'mxf' => 'application/mxf', + 'mxl' => 'application/vnd.recordare.musicxml', + 'mxml' => 'application/xv+xml', + 'mxs' => 'application/vnd.triscape.mxs', + 'mxu' => 'video/vnd.mpegurl', + 'n-gage' => 'application/vnd.nokia.n-gage.symbian.install', + 'n3' => 'text/n3', + 'nb' => 'application/mathematica', + 'nbp' => 'application/vnd.wolfram.player', + 'nc' => 'application/x-netcdf', + 'ncx' => 'application/x-dtbncx+xml', + 'nfo' => 'text/x-nfo', + 'ngdat' => 'application/vnd.nokia.n-gage.data', + 'nitf' => 'application/vnd.nitf', + 'nlu' => 'application/vnd.neurolanguage.nlu', + 'nml' => 'application/vnd.enliven', + 'nnd' => 'application/vnd.noblenet-directory', + 'nns' => 'application/vnd.noblenet-sealer', + 'nnw' => 'application/vnd.noblenet-web', + 'npx' => 'image/vnd.net-fpx', + 'nsc' => 'application/x-conference', + 'nsf' => 'application/vnd.lotus-notes', + 'ntf' => 'application/vnd.nitf', + 'nzb' => 'application/x-nzb', + 'oa2' => 'application/vnd.fujitsu.oasys2', + 'oa3' => 'application/vnd.fujitsu.oasys3', + 'oas' => 'application/vnd.fujitsu.oasys', + 'obd' => 'application/x-msbinder', + 'obj' => 'application/x-tgif', + 'oda' => 'application/oda', + 'odb' => 'application/vnd.oasis.opendocument.database', + 'odc' => 'application/vnd.oasis.opendocument.chart', + 'odf' => 'application/vnd.oasis.opendocument.formula', + 'odft' => 'application/vnd.oasis.opendocument.formula-template', + 'odg' => 'application/vnd.oasis.opendocument.graphics', + 'odi' => 'application/vnd.oasis.opendocument.image', + 'odm' => 'application/vnd.oasis.opendocument.text-master', + 'odp' => 'application/vnd.oasis.opendocument.presentation', + 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', + 'odt' => 'application/vnd.oasis.opendocument.text', + 'oga' => 'audio/ogg', + 'ogg' => 'audio/ogg', + 'ogv' => 'video/ogg', + 'ogx' => 'application/ogg', + 'omdoc' => 'application/omdoc+xml', + 'onepkg' => 'application/onenote', + 'onetmp' => 'application/onenote', + 'onetoc' => 'application/onenote', + 'onetoc2' => 'application/onenote', + 'opf' => 'application/oebps-package+xml', + 'opml' => 'text/x-opml', + 'oprc' => 'application/vnd.palm', + 'org' => 'application/vnd.lotus-organizer', + 'osf' => 'application/vnd.yamaha.openscoreformat', + 'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml', + 'otc' => 'application/vnd.oasis.opendocument.chart-template', + 'otf' => 'application/x-font-otf', + 'otg' => 'application/vnd.oasis.opendocument.graphics-template', + 'oth' => 'application/vnd.oasis.opendocument.text-web', + 'oti' => 'application/vnd.oasis.opendocument.image-template', + 'otp' => 'application/vnd.oasis.opendocument.presentation-template', + 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template', + 'ott' => 'application/vnd.oasis.opendocument.text-template', + 'oxps' => 'application/oxps', + 'oxt' => 'application/vnd.openofficeorg.extension', + 'p' => 'text/x-pascal', + 'p10' => 'application/pkcs10', + 'p12' => 'application/x-pkcs12', + 'p7b' => 'application/x-pkcs7-certificates', + 'p7c' => 'application/pkcs7-mime', + 'p7m' => 'application/pkcs7-mime', + 'p7r' => 'application/x-pkcs7-certreqresp', + 'p7s' => 'application/pkcs7-signature', + 'p8' => 'application/pkcs8', + 'pas' => 'text/x-pascal', + 'paw' => 'application/vnd.pawaafile', + 'pbd' => 'application/vnd.powerbuilder6', + 'pbm' => 'image/x-portable-bitmap', + 'pcap' => 'application/vnd.tcpdump.pcap', + 'pcf' => 'application/x-font-pcf', + 'pcl' => 'application/vnd.hp-pcl', + 'pclxl' => 'application/vnd.hp-pclxl', + 'pct' => 'image/x-pict', + 'pcurl' => 'application/vnd.curl.pcurl', + 'pcx' => 'image/x-pcx', + 'pdb' => 'application/vnd.palm', + 'pdf' => 'application/pdf', + 'pfa' => 'application/x-font-type1', + 'pfb' => 'application/x-font-type1', + 'pfm' => 'application/x-font-type1', + 'pfr' => 'application/font-tdpfr', + 'pfx' => 'application/x-pkcs12', + 'pgm' => 'image/x-portable-graymap', + 'pgn' => 'application/x-chess-pgn', + 'pgp' => 'application/pgp-encrypted', + 'php' => 'application/x-php', + 'php3' => 'application/x-php', + 'php4' => 'application/x-php', + 'php5' => 'application/x-php', + 'pic' => 'image/x-pict', + 'pkg' => 'application/octet-stream', + 'pki' => 'application/pkixcmp', + 'pkipath' => 'application/pkix-pkipath', + 'plb' => 'application/vnd.3gpp.pic-bw-large', + 'plc' => 'application/vnd.mobius.plc', + 'plf' => 'application/vnd.pocketlearn', + 'pls' => 'application/pls+xml', + 'pml' => 'application/vnd.ctc-posml', + 'png' => 'image/png', + 'pnm' => 'image/x-portable-anymap', + 'portpkg' => 'application/vnd.macports.portpkg', + 'pot' => 'application/vnd.ms-powerpoint', + 'potm' => 'application/vnd.ms-powerpoint.template.macroenabled.12', + 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template', + 'ppam' => 'application/vnd.ms-powerpoint.addin.macroenabled.12', + 'ppd' => 'application/vnd.cups-ppd', + 'ppm' => 'image/x-portable-pixmap', + 'pps' => 'application/vnd.ms-powerpoint', + 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroenabled.12', + 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', + 'ppt' => 'application/vnd.ms-powerpoint', + 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroenabled.12', + 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'pqa' => 'application/vnd.palm', + 'prc' => 'application/x-mobipocket-ebook', + 'pre' => 'application/vnd.lotus-freelance', + 'prf' => 'application/pics-rules', + 'ps' => 'application/postscript', + 'psb' => 'application/vnd.3gpp.pic-bw-small', + 'psd' => 'image/vnd.adobe.photoshop', + 'psf' => 'application/x-font-linux-psf', + 'pskcxml' => 'application/pskc+xml', + 'ptid' => 'application/vnd.pvi.ptid1', + 'pub' => 'application/x-mspublisher', + 'pvb' => 'application/vnd.3gpp.pic-bw-var', + 'pwn' => 'application/vnd.3m.post-it-notes', + 'pya' => 'audio/vnd.ms-playready.media.pya', + 'pyv' => 'video/vnd.ms-playready.media.pyv', + 'qam' => 'application/vnd.epson.quickanime', + 'qbo' => 'application/vnd.intu.qbo', + 'qfx' => 'application/vnd.intu.qfx', + 'qps' => 'application/vnd.publishare-delta-tree', + 'qt' => 'video/quicktime', + 'qwd' => 'application/vnd.quark.quarkxpress', + 'qwt' => 'application/vnd.quark.quarkxpress', + 'qxb' => 'application/vnd.quark.quarkxpress', + 'qxd' => 'application/vnd.quark.quarkxpress', + 'qxl' => 'application/vnd.quark.quarkxpress', + 'qxt' => 'application/vnd.quark.quarkxpress', + 'ra' => 'audio/x-pn-realaudio', + 'ram' => 'audio/x-pn-realaudio', + 'rar' => 'application/x-rar-compressed', + 'ras' => 'image/x-cmu-raster', + 'rcprofile' => 'application/vnd.ipunplugged.rcprofile', + 'rdf' => 'application/rdf+xml', + 'rdz' => 'application/vnd.data-vision.rdz', + 'rep' => 'application/vnd.businessobjects', + 'res' => 'application/x-dtbresource+xml', + 'rgb' => 'image/x-rgb', + 'rif' => 'application/reginfo+xml', + 'rip' => 'audio/vnd.rip', + 'ris' => 'application/x-research-info-systems', + 'rl' => 'application/resource-lists+xml', + 'rlc' => 'image/vnd.fujixerox.edmics-rlc', + 'rld' => 'application/resource-lists-diff+xml', + 'rm' => 'application/vnd.rn-realmedia', + 'rmi' => 'audio/midi', + 'rmp' => 'audio/x-pn-realaudio-plugin', + 'rms' => 'application/vnd.jcp.javame.midlet-rms', + 'rmvb' => 'application/vnd.rn-realmedia-vbr', + 'rnc' => 'application/relax-ng-compact-syntax', + 'roa' => 'application/rpki-roa', + 'roff' => 'text/troff', + 'rp9' => 'application/vnd.cloanto.rp9', + 'rpss' => 'application/vnd.nokia.radio-presets', + 'rpst' => 'application/vnd.nokia.radio-preset', + 'rq' => 'application/sparql-query', + 'rs' => 'application/rls-services+xml', + 'rsd' => 'application/rsd+xml', + 'rss' => 'application/rss+xml', + 'rtf' => 'application/rtf', + 'rtx' => 'text/richtext', + 's' => 'text/x-asm', + 's3m' => 'audio/s3m', + 'saf' => 'application/vnd.yamaha.smaf-audio', + 'sbml' => 'application/sbml+xml', + 'sc' => 'application/vnd.ibm.secure-container', + 'scd' => 'application/x-msschedule', + 'scm' => 'application/vnd.lotus-screencam', + 'scq' => 'application/scvp-cv-request', + 'scs' => 'application/scvp-cv-response', + 'scurl' => 'text/vnd.curl.scurl', + 'sda' => 'application/vnd.stardivision.draw', + 'sdc' => 'application/vnd.stardivision.calc', + 'sdd' => 'application/vnd.stardivision.impress', + 'sdkd' => 'application/vnd.solent.sdkm+xml', + 'sdkm' => 'application/vnd.solent.sdkm+xml', + 'sdp' => 'application/sdp', + 'sdw' => 'application/vnd.stardivision.writer', + 'see' => 'application/vnd.seemail', + 'seed' => 'application/vnd.fdsn.seed', + 'sema' => 'application/vnd.sema', + 'semd' => 'application/vnd.semd', + 'semf' => 'application/vnd.semf', + 'ser' => 'application/java-serialized-object', + 'setpay' => 'application/set-payment-initiation', + 'setreg' => 'application/set-registration-initiation', + 'sfd-hdstx' => 'application/vnd.hydrostatix.sof-data', + 'sfs' => 'application/vnd.spotfire.sfs', + 'sfv' => 'text/x-sfv', + 'sgi' => 'image/sgi', + 'sgl' => 'application/vnd.stardivision.writer-global', + 'sgm' => 'text/sgml', + 'sgml' => 'text/sgml', + 'sh' => 'application/x-sh', + 'shar' => 'application/x-shar', + 'shf' => 'application/shf+xml', + 'sid' => 'image/x-mrsid-image', + 'sig' => 'application/pgp-signature', + 'sil' => 'audio/silk', + 'silo' => 'model/mesh', + 'sis' => 'application/vnd.symbian.install', + 'sisx' => 'application/vnd.symbian.install', + 'sit' => 'application/x-stuffit', + 'sitx' => 'application/x-stuffitx', + 'skd' => 'application/vnd.koan', + 'skm' => 'application/vnd.koan', + 'skp' => 'application/vnd.koan', + 'skt' => 'application/vnd.koan', + 'sldm' => 'application/vnd.ms-powerpoint.slide.macroenabled.12', + 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide', + 'slt' => 'application/vnd.epson.salt', + 'sm' => 'application/vnd.stepmania.stepchart', + 'smf' => 'application/vnd.stardivision.math', + 'smi' => 'application/smil+xml', + 'smil' => 'application/smil+xml', + 'smv' => 'video/x-smv', + 'smzip' => 'application/vnd.stepmania.package', + 'snd' => 'audio/basic', + 'snf' => 'application/x-font-snf', + 'so' => 'application/octet-stream', + 'spc' => 'application/x-pkcs7-certificates', + 'spf' => 'application/vnd.yamaha.smaf-phrase', + 'spl' => 'application/x-futuresplash', + 'spot' => 'text/vnd.in3d.spot', + 'spp' => 'application/scvp-vp-response', + 'spq' => 'application/scvp-vp-request', + 'spx' => 'audio/ogg', + 'sql' => 'application/x-sql', + 'src' => 'application/x-wais-source', + 'srt' => 'application/x-subrip', + 'sru' => 'application/sru+xml', + 'srx' => 'application/sparql-results+xml', + 'ssdl' => 'application/ssdl+xml', + 'sse' => 'application/vnd.kodak-descriptor', + 'ssf' => 'application/vnd.epson.ssf', + 'ssml' => 'application/ssml+xml', + 'st' => 'application/vnd.sailingtracker.track', + 'stc' => 'application/vnd.sun.xml.calc.template', + 'std' => 'application/vnd.sun.xml.draw.template', + 'stf' => 'application/vnd.wt.stf', + 'sti' => 'application/vnd.sun.xml.impress.template', + 'stk' => 'application/hyperstudio', + 'stl' => 'application/vnd.ms-pki.stl', + 'str' => 'application/vnd.pg.format', + 'stw' => 'application/vnd.sun.xml.writer.template', + 'sub' => 'text/vnd.dvb.subtitle', + 'sus' => 'application/vnd.sus-calendar', + 'susp' => 'application/vnd.sus-calendar', + 'sv4cpio' => 'application/x-sv4cpio', + 'sv4crc' => 'application/x-sv4crc', + 'svc' => 'application/vnd.dvb.service', + 'svd' => 'application/vnd.svd', + 'svg' => 'image/svg+xml', + 'svgz' => 'image/svg+xml', + 'swa' => 'application/x-director', + 'swf' => 'application/x-shockwave-flash', + 'swi' => 'application/vnd.aristanetworks.swi', + 'sxc' => 'application/vnd.sun.xml.calc', + 'sxd' => 'application/vnd.sun.xml.draw', + 'sxg' => 'application/vnd.sun.xml.writer.global', + 'sxi' => 'application/vnd.sun.xml.impress', + 'sxm' => 'application/vnd.sun.xml.math', + 'sxw' => 'application/vnd.sun.xml.writer', + 't' => 'text/troff', + 't3' => 'application/x-t3vm-image', + 'taglet' => 'application/vnd.mynfc', + 'tao' => 'application/vnd.tao.intent-module-archive', + 'tar' => 'application/x-tar', + 'tcap' => 'application/vnd.3gpp2.tcap', + 'tcl' => 'application/x-tcl', + 'teacher' => 'application/vnd.smart.teacher', + 'tei' => 'application/tei+xml', + 'teicorpus' => 'application/tei+xml', + 'tex' => 'application/x-tex', + 'texi' => 'application/x-texinfo', + 'texinfo' => 'application/x-texinfo', + 'text' => 'text/plain', + 'tfi' => 'application/thraud+xml', + 'tfm' => 'application/x-tex-tfm', + 'tga' => 'image/x-tga', + 'thmx' => 'application/vnd.ms-officetheme', + 'tif' => 'image/tiff', + 'tiff' => 'image/tiff', + 'tmo' => 'application/vnd.tmobile-livetv', + 'torrent' => 'application/x-bittorrent', + 'tpl' => 'application/vnd.groove-tool-template', + 'tpt' => 'application/vnd.trid.tpt', + 'tr' => 'text/troff', + 'tra' => 'application/vnd.trueapp', + 'trm' => 'application/x-msterminal', + 'tsd' => 'application/timestamped-data', + 'tsv' => 'text/tab-separated-values', + 'ttc' => 'application/x-font-ttf', + 'ttf' => 'application/x-font-ttf', + 'ttl' => 'text/turtle', + 'twd' => 'application/vnd.simtech-mindmapper', + 'twds' => 'application/vnd.simtech-mindmapper', + 'txd' => 'application/vnd.genomatix.tuxedo', + 'txf' => 'application/vnd.mobius.txf', + 'txt' => 'text/plain', + 'u32' => 'application/x-authorware-bin', + 'udeb' => 'application/x-debian-package', + 'ufd' => 'application/vnd.ufdl', + 'ufdl' => 'application/vnd.ufdl', + 'ulx' => 'application/x-glulx', + 'umj' => 'application/vnd.umajin', + 'unityweb' => 'application/vnd.unity', + 'uoml' => 'application/vnd.uoml+xml', + 'uri' => 'text/uri-list', + 'uris' => 'text/uri-list', + 'urls' => 'text/uri-list', + 'ustar' => 'application/x-ustar', + 'utz' => 'application/vnd.uiq.theme', + 'uu' => 'text/x-uuencode', + 'uva' => 'audio/vnd.dece.audio', + 'uvd' => 'application/vnd.dece.data', + 'uvf' => 'application/vnd.dece.data', + 'uvg' => 'image/vnd.dece.graphic', + 'uvh' => 'video/vnd.dece.hd', + 'uvi' => 'image/vnd.dece.graphic', + 'uvm' => 'video/vnd.dece.mobile', + 'uvp' => 'video/vnd.dece.pd', + 'uvs' => 'video/vnd.dece.sd', + 'uvt' => 'application/vnd.dece.ttml+xml', + 'uvu' => 'video/vnd.uvvu.mp4', + 'uvv' => 'video/vnd.dece.video', + 'uvva' => 'audio/vnd.dece.audio', + 'uvvd' => 'application/vnd.dece.data', + 'uvvf' => 'application/vnd.dece.data', + 'uvvg' => 'image/vnd.dece.graphic', + 'uvvh' => 'video/vnd.dece.hd', + 'uvvi' => 'image/vnd.dece.graphic', + 'uvvm' => 'video/vnd.dece.mobile', + 'uvvp' => 'video/vnd.dece.pd', + 'uvvs' => 'video/vnd.dece.sd', + 'uvvt' => 'application/vnd.dece.ttml+xml', + 'uvvu' => 'video/vnd.uvvu.mp4', + 'uvvv' => 'video/vnd.dece.video', + 'uvvx' => 'application/vnd.dece.unspecified', + 'uvvz' => 'application/vnd.dece.zip', + 'uvx' => 'application/vnd.dece.unspecified', + 'uvz' => 'application/vnd.dece.zip', + 'vcard' => 'text/vcard', + 'vcd' => 'application/x-cdlink', + 'vcf' => 'text/x-vcard', + 'vcg' => 'application/vnd.groove-vcard', + 'vcs' => 'text/x-vcalendar', + 'vcx' => 'application/vnd.vcx', + 'vis' => 'application/vnd.visionary', + 'viv' => 'video/vnd.vivo', + 'vob' => 'video/x-ms-vob', + 'vor' => 'application/vnd.stardivision.writer', + 'vox' => 'application/x-authorware-bin', + 'vrml' => 'model/vrml', + 'vsd' => 'application/vnd.visio', + 'vsf' => 'application/vnd.vsf', + 'vss' => 'application/vnd.visio', + 'vst' => 'application/vnd.visio', + 'vsw' => 'application/vnd.visio', + 'vtu' => 'model/vnd.vtu', + 'vxml' => 'application/voicexml+xml', + 'w3d' => 'application/x-director', + 'wad' => 'application/x-doom', + 'wav' => 'audio/x-wav', + 'wax' => 'audio/x-ms-wax', + 'wbmp' => 'image/vnd.wap.wbmp', + 'wbs' => 'application/vnd.criticaltools.wbs+xml', + 'wbxml' => 'application/vnd.wap.wbxml', + 'wcm' => 'application/vnd.ms-works', + 'wdb' => 'application/vnd.ms-works', + 'wdp' => 'image/vnd.ms-photo', + 'weba' => 'audio/webm', + 'webm' => 'video/webm', + 'webp' => 'image/webp', + 'wg' => 'application/vnd.pmi.widget', + 'wgt' => 'application/widget', + 'wks' => 'application/vnd.ms-works', + 'wm' => 'video/x-ms-wm', + 'wma' => 'audio/x-ms-wma', + 'wmd' => 'application/x-ms-wmd', + 'wmf' => 'application/x-msmetafile', + 'wml' => 'text/vnd.wap.wml', + 'wmlc' => 'application/vnd.wap.wmlc', + 'wmls' => 'text/vnd.wap.wmlscript', + 'wmlsc' => 'application/vnd.wap.wmlscriptc', + 'wmv' => 'video/x-ms-wmv', + 'wmx' => 'video/x-ms-wmx', + 'wmz' => 'application/x-msmetafile', + 'woff' => 'application/font-woff', + 'wpd' => 'application/vnd.wordperfect', + 'wpl' => 'application/vnd.ms-wpl', + 'wps' => 'application/vnd.ms-works', + 'wqd' => 'application/vnd.wqd', + 'wri' => 'application/x-mswrite', + 'wrl' => 'model/vrml', + 'wsdl' => 'application/wsdl+xml', + 'wspolicy' => 'application/wspolicy+xml', + 'wtb' => 'application/vnd.webturbo', + 'wvx' => 'video/x-ms-wvx', + 'x32' => 'application/x-authorware-bin', + 'x3d' => 'model/x3d+xml', + 'x3db' => 'model/x3d+binary', + 'x3dbz' => 'model/x3d+binary', + 'x3dv' => 'model/x3d+vrml', + 'x3dvz' => 'model/x3d+vrml', + 'x3dz' => 'model/x3d+xml', + 'xaml' => 'application/xaml+xml', + 'xap' => 'application/x-silverlight-app', + 'xar' => 'application/vnd.xara', + 'xbap' => 'application/x-ms-xbap', + 'xbd' => 'application/vnd.fujixerox.docuworks.binder', + 'xbm' => 'image/x-xbitmap', + 'xdf' => 'application/xcap-diff+xml', + 'xdm' => 'application/vnd.syncml.dm+xml', + 'xdp' => 'application/vnd.adobe.xdp+xml', + 'xdssc' => 'application/dssc+xml', + 'xdw' => 'application/vnd.fujixerox.docuworks', + 'xenc' => 'application/xenc+xml', + 'xer' => 'application/patch-ops-error+xml', + 'xfdf' => 'application/vnd.adobe.xfdf', + 'xfdl' => 'application/vnd.xfdl', + 'xht' => 'application/xhtml+xml', + 'xhtml' => 'application/xhtml+xml', + 'xhvml' => 'application/xv+xml', + 'xif' => 'image/vnd.xiff', + 'xla' => 'application/vnd.ms-excel', + 'xlam' => 'application/vnd.ms-excel.addin.macroenabled.12', + 'xlc' => 'application/vnd.ms-excel', + 'xlf' => 'application/x-xliff+xml', + 'xlm' => 'application/vnd.ms-excel', + 'xls' => 'application/vnd.ms-excel', + 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroenabled.12', + 'xlsm' => 'application/vnd.ms-excel.sheet.macroenabled.12', + 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'xlt' => 'application/vnd.ms-excel', + 'xltm' => 'application/vnd.ms-excel.template.macroenabled.12', + 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', + 'xlw' => 'application/vnd.ms-excel', + 'xm' => 'audio/xm', + 'xml' => 'application/xml', + 'xo' => 'application/vnd.olpc-sugar', + 'xop' => 'application/xop+xml', + 'xpi' => 'application/x-xpinstall', + 'xpl' => 'application/xproc+xml', + 'xpm' => 'image/x-xpixmap', + 'xpr' => 'application/vnd.is-xpr', + 'xps' => 'application/vnd.ms-xpsdocument', + 'xpw' => 'application/vnd.intercon.formnet', + 'xpx' => 'application/vnd.intercon.formnet', + 'xsl' => 'application/xml', + 'xslt' => 'application/xslt+xml', + 'xsm' => 'application/vnd.syncml+xml', + 'xspf' => 'application/xspf+xml', + 'xul' => 'application/vnd.mozilla.xul+xml', + 'xvm' => 'application/xv+xml', + 'xvml' => 'application/xv+xml', + 'xwd' => 'image/x-xwindowdump', + 'xyz' => 'chemical/x-xyz', + 'xz' => 'application/x-xz', + 'yang' => 'application/yang', + 'yin' => 'application/yin+xml', + 'z1' => 'application/x-zmachine', + 'z2' => 'application/x-zmachine', + 'z3' => 'application/x-zmachine', + 'z4' => 'application/x-zmachine', + 'z5' => 'application/x-zmachine', + 'z6' => 'application/x-zmachine', + 'z7' => 'application/x-zmachine', + 'z8' => 'application/x-zmachine', + 'zaz' => 'application/vnd.zzazz.deck+xml', + 'zip' => 'application/zip', + 'zir' => 'application/vnd.zul', + 'zirz' => 'application/vnd.zul', + 'zmm' => 'application/vnd.handheld-entertainment+xml', + '123' => 'application/vnd.lotus-1-2-3', ]; diff --git a/htdocs/includes/swiftmailer/lib/swiftmailer_generate_mimes_config.php b/htdocs/includes/swiftmailer/lib/swiftmailer_generate_mimes_config.php index ad8fd2aa0d5..b3febce4802 100644 --- a/htdocs/includes/swiftmailer/lib/swiftmailer_generate_mimes_config.php +++ b/htdocs/includes/swiftmailer/lib/swiftmailer_generate_mimes_config.php @@ -6,177 +6,177 @@ function generateUpToDateMimeArray() { - $preamble = " 'application/x-php', - 'php3' => 'application/x-php', - 'php4' => 'application/x-php', - 'php5' => 'application/x-php', - 'zip' => 'application/zip', - 'gif' => 'image/gif', - 'png' => 'image/png', - 'css' => 'text/css', - 'js' => 'text/javascript', - 'txt' => 'text/plain', - 'aif' => 'audio/x-aiff', - 'aiff' => 'audio/x-aiff', - 'avi' => 'video/avi', - 'bmp' => 'image/bmp', - 'bz2' => 'application/x-bz2', - 'csv' => 'text/csv', - 'dmg' => 'application/x-apple-diskimage', - 'doc' => 'application/msword', - 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', - 'eml' => 'message/rfc822', - 'aps' => 'application/postscript', - 'exe' => 'application/x-ms-dos-executable', - 'flv' => 'video/x-flv', - 'gz' => 'application/x-gzip', - 'hqx' => 'application/stuffit', - 'htm' => 'text/html', - 'html' => 'text/html', - 'jar' => 'application/x-java-archive', - 'jpeg' => 'image/jpeg', - 'jpg' => 'image/jpeg', - 'm3u' => 'audio/x-mpegurl', - 'm4a' => 'audio/mp4', - 'mdb' => 'application/x-msaccess', - 'mid' => 'audio/midi', - 'midi' => 'audio/midi', - 'mov' => 'video/quicktime', - 'mp3' => 'audio/mpeg', - 'mp4' => 'video/mp4', - 'mpeg' => 'video/mpeg', - 'mpg' => 'video/mpeg', - 'odg' => 'vnd.oasis.opendocument.graphics', - 'odp' => 'vnd.oasis.opendocument.presentation', - 'odt' => 'vnd.oasis.opendocument.text', - 'ods' => 'vnd.oasis.opendocument.spreadsheet', - 'ogg' => 'audio/ogg', - 'pdf' => 'application/pdf', - 'ppt' => 'application/vnd.ms-powerpoint', - 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', - 'ps' => 'application/postscript', - 'rar' => 'application/x-rar-compressed', - 'rtf' => 'application/rtf', - 'tar' => 'application/x-tar', - 'sit' => 'application/x-stuffit', - 'svg' => 'image/svg+xml', - 'tif' => 'image/tiff', - 'tiff' => 'image/tiff', - 'ttf' => 'application/x-font-truetype', - 'vcf' => 'text/x-vcard', - 'wav' => 'audio/wav', - 'wma' => 'audio/x-ms-wma', - 'wmv' => 'audio/x-ms-wmv', - 'xls' => 'application/vnd.ms-excel', - 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', - 'xml' => 'application/xml', - ]; + // split mime type and extensions eg. "video/x-matroska mkv mk3d mks" + if (false !== preg_match_all('/^#?([a-z0-9\-\+\/\.]+)[\t]+(.*)$/miu', $mime_types, $matches)) { + // collection of predefined mimetypes (bugfix for wrong resolved or missing mime types) + $valid_mime_types_preset = [ + 'php' => 'application/x-php', + 'php3' => 'application/x-php', + 'php4' => 'application/x-php', + 'php5' => 'application/x-php', + 'zip' => 'application/zip', + 'gif' => 'image/gif', + 'png' => 'image/png', + 'css' => 'text/css', + 'js' => 'text/javascript', + 'txt' => 'text/plain', + 'aif' => 'audio/x-aiff', + 'aiff' => 'audio/x-aiff', + 'avi' => 'video/avi', + 'bmp' => 'image/bmp', + 'bz2' => 'application/x-bz2', + 'csv' => 'text/csv', + 'dmg' => 'application/x-apple-diskimage', + 'doc' => 'application/msword', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'eml' => 'message/rfc822', + 'aps' => 'application/postscript', + 'exe' => 'application/x-ms-dos-executable', + 'flv' => 'video/x-flv', + 'gz' => 'application/x-gzip', + 'hqx' => 'application/stuffit', + 'htm' => 'text/html', + 'html' => 'text/html', + 'jar' => 'application/x-java-archive', + 'jpeg' => 'image/jpeg', + 'jpg' => 'image/jpeg', + 'm3u' => 'audio/x-mpegurl', + 'm4a' => 'audio/mp4', + 'mdb' => 'application/x-msaccess', + 'mid' => 'audio/midi', + 'midi' => 'audio/midi', + 'mov' => 'video/quicktime', + 'mp3' => 'audio/mpeg', + 'mp4' => 'video/mp4', + 'mpeg' => 'video/mpeg', + 'mpg' => 'video/mpeg', + 'odg' => 'vnd.oasis.opendocument.graphics', + 'odp' => 'vnd.oasis.opendocument.presentation', + 'odt' => 'vnd.oasis.opendocument.text', + 'ods' => 'vnd.oasis.opendocument.spreadsheet', + 'ogg' => 'audio/ogg', + 'pdf' => 'application/pdf', + 'ppt' => 'application/vnd.ms-powerpoint', + 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'ps' => 'application/postscript', + 'rar' => 'application/x-rar-compressed', + 'rtf' => 'application/rtf', + 'tar' => 'application/x-tar', + 'sit' => 'application/x-stuffit', + 'svg' => 'image/svg+xml', + 'tif' => 'image/tiff', + 'tiff' => 'image/tiff', + 'ttf' => 'application/x-font-truetype', + 'vcf' => 'text/x-vcard', + 'wav' => 'audio/wav', + 'wma' => 'audio/x-ms-wma', + 'wmv' => 'audio/x-ms-wmv', + 'xls' => 'application/vnd.ms-excel', + 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'xml' => 'application/xml', + ]; - // wrap array for generating file - foreach ($valid_mime_types_preset as $extension => $mime_type) { - // generate array for mimetype to extension resolver (only first match) - $valid_mime_types[$extension] = "'{$extension}' => '{$mime_type}'"; - } + // wrap array for generating file + foreach ($valid_mime_types_preset as $extension => $mime_type) { + // generate array for mimetype to extension resolver (only first match) + $valid_mime_types[$extension] = "'{$extension}' => '{$mime_type}'"; + } - // all extensions from second match - foreach ($matches[2] as $i => $extensions) { - // explode multiple extensions from string - $extensions = explode(' ', strtolower($extensions ?? '')); + // all extensions from second match + foreach ($matches[2] as $i => $extensions) { + // explode multiple extensions from string + $extensions = explode(' ', strtolower($extensions ?? '')); - // force array for foreach - if (!\is_array($extensions)) { - $extensions = [$extensions]; - } + // force array for foreach + if (!\is_array($extensions)) { + $extensions = [$extensions]; + } - foreach ($extensions as $extension) { - // get mime type - $mime_type = $matches[1][$i]; + foreach ($extensions as $extension) { + // get mime type + $mime_type = $matches[1][$i]; - // check if string length lower than 10 - if (\strlen($extension) < 10) { - if (!isset($valid_mime_types[$mime_type])) { - // generate array for mimetype to extension resolver (only first match) - $valid_mime_types[$extension] = "'{$extension}' => '{$mime_type}'"; - } - } - } - } - } + // check if string length lower than 10 + if (\strlen($extension) < 10) { + if (!isset($valid_mime_types[$mime_type])) { + // generate array for mimetype to extension resolver (only first match) + $valid_mime_types[$extension] = "'{$extension}' => '{$mime_type}'"; + } + } + } + } + } - $xml = simplexml_load_string($mime_xml); + $xml = simplexml_load_string($mime_xml); - foreach ($xml as $node) { - // check if there is no pattern - if (!isset($node->glob['pattern'])) { - continue; - } + foreach ($xml as $node) { + // check if there is no pattern + if (!isset($node->glob['pattern'])) { + continue; + } - // get all matching extensions from match - foreach ((array) $node->glob['pattern'] as $extension) { - // skip none glob extensions - if (false === strpos($extension ?? '', '.')) { - continue; - } + // get all matching extensions from match + foreach ((array) $node->glob['pattern'] as $extension) { + // skip none glob extensions + if (false === strpos($extension ?? '', '.')) { + continue; + } - // remove get only last part - $extension = explode('.', strtolower($extension ?? '')); - $extension = end($extension); - } + // remove get only last part + $extension = explode('.', strtolower($extension ?? '')); + $extension = end($extension); + } - if (isset($node->glob['pattern'][0])) { - // mime type - $mime_type = strtolower((string) $node['type'] ?? ''); + if (isset($node->glob['pattern'][0])) { + // mime type + $mime_type = strtolower((string) $node['type'] ?? ''); - // get first extension - $extension = strtolower(trim($node->glob['ddpattern'][0] ?? '', '*.')); + // get first extension + $extension = strtolower(trim($node->glob['ddpattern'][0] ?? '', '*.')); - // skip none glob extensions and check if string length between 1 and 10 - if (false !== strpos($extension, '.') || \strlen($extension) < 1 || \strlen($extension) > 9) { - continue; - } + // skip none glob extensions and check if string length between 1 and 10 + if (false !== strpos($extension, '.') || \strlen($extension) < 1 || \strlen($extension) > 9) { + continue; + } - // check if string length lower than 10 - if (!isset($valid_mime_types[$mime_type])) { - // generate array for mimetype to extension resolver (only first match) - $valid_mime_types[$extension] = "'{$extension}' => '{$mime_type}'"; - } - } - } + // check if string length lower than 10 + if (!isset($valid_mime_types[$mime_type])) { + // generate array for mimetype to extension resolver (only first match) + $valid_mime_types[$extension] = "'{$extension}' => '{$mime_type}'"; + } + } + } - // full list of valid extensions only - $valid_mime_types = array_unique($valid_mime_types); - ksort($valid_mime_types); + // full list of valid extensions only + $valid_mime_types = array_unique($valid_mime_types); + ksort($valid_mime_types); - // combine mime types and extensions array - $output = "$preamble\$swift_mime_types = array(\n ".implode(",\n ", $valid_mime_types)."\n);"; + // combine mime types and extensions array + $output = "$preamble\$swift_mime_types = array(\n ".implode(",\n ", $valid_mime_types)."\n);"; - // write mime_types.php config file - @file_put_contents('./mime_types.php', $output); + // write mime_types.php config file + @file_put_contents('./mime_types.php', $output); } generateUpToDateMimeArray(); diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index e4ad83e8129..a17e7c2e6be 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -285,7 +285,6 @@ if (($action == 'updateline' || $action == 'updatesplitline') && !$cancel && $us } $result = $object->addTimeSpent($user); - } else { $object->fetch($id, $ref); @@ -1794,7 +1793,6 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser if ($resultFetch < 0) { setEventMessages($product->error, $product->errors, 'errors'); } else { - print $product->getNomUrl(1); } } From db8d8f0b7d806e5fb510de0e6ca2bd5e5ab71fe9 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Mon, 24 Jan 2022 23:27:26 +0100 Subject: [PATCH 009/826] Revert "merge" This reverts commit 8d3d8fe63b2607b7f875fa96e3c7c1ed7bd24b98. --- .../EmailValidator/EmailLexer.php | 494 ++--- .../EmailValidator/EmailParser.php | 196 +- .../EmailValidator/EmailValidator.php | 98 +- .../Exception/DomainAcceptsNoMail.php | 6 +- .../Exception/ExpectingQPair.php | 4 +- .../Exception/LocalOrReservedDomain.php | 6 +- .../EmailValidator/Exception/NoDNSRecord.php | 4 +- .../Exception/UnclosedComment.php | 4 +- .../EmailValidator/Parser/DomainPart.php | 811 +++---- .../EmailValidator/Parser/LocalPart.php | 210 +- .../EmailValidator/Parser/Parser.php | 379 ++-- .../Validation/DNSCheckValidation.php | 246 +- .../Exception/EmptyValidationList.php | 14 +- .../Validation/MultipleErrors.php | 42 +- .../Validation/MultipleValidationWithAnd.php | 196 +- .../Validation/NoRFCWarningsValidation.php | 50 +- .../Validation/RFCValidation.php | 64 +- .../Validation/SpoofCheckValidation.php | 66 +- .../EmailValidator/Warning/QuotedPart.php | 18 +- .../EmailValidator/Warning/QuotedString.php | 18 +- .../EmailValidator/Warning/Warning.php | 68 +- .../Doctrine/Common/Lexer/AbstractLexer.php | 536 ++--- .../swiftmailer/lib/classes/Swift.php | 104 +- .../lib/classes/Swift/AddressEncoder.php | 14 +- .../AddressEncoder/IdnAddressEncoder.php | 40 +- .../AddressEncoder/Utf8AddressEncoder.php | 14 +- .../classes/Swift/AddressEncoderException.php | 20 +- .../lib/classes/Swift/Attachment.php | 68 +- .../AbstractFilterableInputStream.php | 278 +-- .../Swift/ByteStream/ArrayByteStream.php | 288 +-- .../Swift/ByteStream/FileByteStream.php | 342 +-- .../ByteStream/TemporaryFileByteStream.php | 58 +- .../GenericFixedWidthReader.php | 142 +- .../Swift/CharacterReader/UsAsciiReader.php | 122 +- .../Swift/CharacterReader/Utf8Reader.php | 298 +-- .../SimpleCharacterReaderFactory.php | 182 +- .../lib/classes/Swift/CharacterStream.php | 114 +- .../CharacterStream/ArrayCharacterStream.php | 486 ++-- .../CharacterStream/NgCharacterStream.php | 440 ++-- .../lib/classes/Swift/DependencyContainer.php | 644 +++--- .../lib/classes/Swift/EmbeddedFile.php | 66 +- .../classes/Swift/Encoder/Base64Encoder.php | 72 +- .../lib/classes/Swift/Encoder/QpEncoder.php | 504 ++--- .../classes/Swift/Encoder/Rfc2231Encoder.php | 126 +- .../lib/classes/Swift/Events/CommandEvent.php | 84 +- .../classes/Swift/Events/CommandListener.php | 8 +- .../classes/Swift/Events/EventDispatcher.php | 92 +- .../lib/classes/Swift/Events/EventObject.php | 76 +- .../classes/Swift/Events/ResponseEvent.php | 84 +- .../classes/Swift/Events/ResponseListener.php | 8 +- .../lib/classes/Swift/Events/SendEvent.php | 188 +- .../lib/classes/Swift/Events/SendListener.php | 16 +- .../Swift/Events/SimpleEventDispatcher.php | 224 +- .../Swift/Events/TransportChangeListener.php | 32 +- .../Swift/Events/TransportExceptionEvent.php | 46 +- .../Events/TransportExceptionListener.php | 8 +- .../lib/classes/Swift/FailoverTransport.php | 28 +- .../lib/classes/Swift/FileSpool.php | 330 +-- .../lib/classes/Swift/Filterable.php | 24 +- .../lib/classes/Swift/InputByteStream.php | 100 +- .../lib/classes/Swift/IoException.php | 20 +- .../lib/classes/Swift/KeyCache.php | 154 +- .../classes/Swift/KeyCache/ArrayKeyCache.php | 332 +-- .../classes/Swift/KeyCache/DiskKeyCache.php | 508 ++--- .../Swift/KeyCache/KeyCacheInputStream.php | 50 +- .../classes/Swift/KeyCache/NullKeyCache.php | 176 +- .../KeyCache/SimpleKeyCacheInputStream.php | 184 +- .../classes/Swift/LoadBalancedTransport.php | 28 +- .../swiftmailer/lib/classes/Swift/Mailer.php | 142 +- .../Swift/Mailer/ArrayRecipientIterator.php | 64 +- .../lib/classes/Swift/MemorySpool.php | 162 +- .../swiftmailer/lib/classes/Swift/Message.php | 442 ++-- .../lib/classes/Swift/Mime/Attachment.php | 224 +- .../ContentEncoder/Base64ContentEncoder.php | 144 +- .../ContentEncoder/NativeQpContentEncoder.php | 182 +- .../ContentEncoder/NullContentEncoder.php | 110 +- .../ContentEncoder/PlainContentEncoder.php | 252 +-- .../Mime/ContentEncoder/QpContentEncoder.php | 200 +- .../ContentEncoder/QpContentEncoderProxy.php | 134 +- .../Mime/ContentEncoder/RawContentEncoder.php | 80 +- .../lib/classes/Swift/Mime/EmbeddedFile.php | 44 +- .../classes/Swift/Mime/EncodingObserver.php | 8 +- .../lib/classes/Swift/Mime/Header.php | 126 +- .../HeaderEncoder/Base64HeaderEncoder.php | 68 +- .../Mime/HeaderEncoder/QpHeaderEncoder.php | 88 +- .../Swift/Mime/Headers/AbstractHeader.php | 834 +++---- .../classes/Swift/Mime/Headers/DateHeader.php | 174 +- .../Mime/Headers/IdentificationHeader.php | 298 +-- .../Swift/Mime/Headers/MailboxHeader.php | 626 +++--- .../Swift/Mime/Headers/OpenDKIMHeader.php | 208 +- .../Mime/Headers/ParameterizedHeader.php | 426 ++-- .../classes/Swift/Mime/Headers/PathHeader.php | 242 +- .../Swift/Mime/Headers/UnstructuredHeader.php | 166 +- .../lib/classes/Swift/Mime/IdGenerator.php | 68 +- .../lib/classes/Swift/Mime/MimePart.php | 318 +-- .../Swift/Mime/SimpleHeaderFactory.php | 310 +-- .../classes/Swift/Mime/SimpleHeaderSet.php | 674 +++--- .../lib/classes/Swift/Mime/SimpleMessage.php | 1248 +++++------ .../classes/Swift/Mime/SimpleMimeEntity.php | 1616 +++++++------- .../lib/classes/Swift/MimePart.php | 52 +- .../lib/classes/Swift/NullTransport.php | 16 +- .../classes/Swift/Plugins/AntiFloodPlugin.php | 216 +- .../Swift/Plugins/BandwidthMonitorPlugin.php | 244 +- .../classes/Swift/Plugins/DecoratorPlugin.php | 332 +-- .../Swift/Plugins/ImpersonatePlugin.php | 80 +- .../classes/Swift/Plugins/LoggerPlugin.php | 194 +- .../Swift/Plugins/Loggers/ArrayLogger.php | 98 +- .../classes/Swift/Plugins/MessageLogger.php | 92 +- .../Swift/Plugins/PopBeforeSmtpPlugin.php | 376 ++-- .../Swift/Plugins/RedirectingPlugin.php | 314 +-- .../lib/classes/Swift/Plugins/Reporter.php | 22 +- .../classes/Swift/Plugins/ReporterPlugin.php | 72 +- .../Swift/Plugins/Reporters/HitReporter.php | 72 +- .../Swift/Plugins/Reporters/HtmlReporter.php | 40 +- .../classes/Swift/Plugins/ThrottlerPlugin.php | 312 +-- .../lib/classes/Swift/Preferences.php | 142 +- .../lib/classes/Swift/SendmailTransport.php | 28 +- .../swiftmailer/lib/classes/Swift/Signer.php | 2 +- .../lib/classes/Swift/Signers/BodySigner.php | 24 +- .../lib/classes/Swift/Signers/DKIMSigner.php | 1328 +++++------ .../classes/Swift/Signers/DomainKeySigner.php | 860 +++---- .../classes/Swift/Signers/HeaderSigner.php | 76 +- .../classes/Swift/Signers/OpenDKIMSigner.php | 274 +-- .../lib/classes/Swift/Signers/SMimeSigner.php | 1044 ++++----- .../lib/classes/Swift/SmtpTransport.php | 38 +- .../lib/classes/Swift/SpoolTransport.php | 26 +- .../ByteArrayReplacementFilter.php | 268 +-- .../StringReplacementFilterFactory.php | 46 +- .../lib/classes/Swift/SwiftException.php | 20 +- .../lib/classes/Swift/Transport.php | 106 +- .../Swift/Transport/AbstractSmtpTransport.php | 1046 ++++----- .../Esmtp/Auth/CramMd5Authenticator.php | 98 +- .../Esmtp/Auth/LoginAuthenticator.php | 48 +- .../Esmtp/Auth/NTLMAuthenticator.php | 1322 +++++------ .../Esmtp/Auth/PlainAuthenticator.php | 46 +- .../Esmtp/Auth/XOAuth2Authenticator.php | 64 +- .../Swift/Transport/Esmtp/AuthHandler.php | 448 ++-- .../Swift/Transport/Esmtp/Authenticator.php | 34 +- .../Transport/Esmtp/EightBitMimeHandler.php | 156 +- .../Swift/Transport/Esmtp/SmtpUtf8Handler.php | 144 +- .../classes/Swift/Transport/EsmtpHandler.php | 120 +- .../Swift/Transport/EsmtpTransport.php | 768 +++---- .../Swift/Transport/FailoverTransport.php | 146 +- .../lib/classes/Swift/Transport/IoBuffer.php | 82 +- .../Swift/Transport/LoadBalancedTransport.php | 310 +-- .../classes/Swift/Transport/NullTransport.php | 140 +- .../Swift/Transport/SendmailTransport.php | 241 +- .../lib/classes/Swift/Transport/SmtpAgent.php | 34 +- .../Swift/Transport/SpoolTransport.php | 176 +- .../classes/Swift/Transport/StreamBuffer.php | 540 ++--- .../lib/classes/Swift/TransportException.php | 20 +- .../lib/dependency_maps/cache_deps.php | 29 +- .../lib/dependency_maps/mime_deps.php | 207 +- .../lib/dependency_maps/transport_deps.php | 145 +- .../includes/swiftmailer/lib/mime_types.php | 1972 ++++++++--------- .../lib/swiftmailer_generate_mimes_config.php | 304 +-- htdocs/projet/tasks/time.php | 2 + 157 files changed, 17947 insertions(+), 17939 deletions(-) diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/EmailLexer.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/EmailLexer.php index 567002e5e2c..59dcd5876fd 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/EmailLexer.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/EmailLexer.php @@ -6,278 +6,278 @@ use Doctrine\Common\Lexer\AbstractLexer; class EmailLexer extends AbstractLexer { - //ASCII values - const C_DEL = 127; - const C_NUL = 0; - const S_AT = 64; - const S_BACKSLASH = 92; - const S_DOT = 46; - const S_DQUOTE = 34; - const S_SQUOTE = 39; - const S_BACKTICK = 96; - const S_OPENPARENTHESIS = 49; - const S_CLOSEPARENTHESIS = 261; - const S_OPENBRACKET = 262; - const S_CLOSEBRACKET = 263; - const S_HYPHEN = 264; - const S_COLON = 265; - const S_DOUBLECOLON = 266; - const S_SP = 267; - const S_HTAB = 268; - const S_CR = 269; - const S_LF = 270; - const S_IPV6TAG = 271; - const S_LOWERTHAN = 272; - const S_GREATERTHAN = 273; - const S_COMMA = 274; - const S_SEMICOLON = 275; - const S_OPENQBRACKET = 276; - const S_CLOSEQBRACKET = 277; - const S_SLASH = 278; - const S_EMPTY = null; - const GENERIC = 300; - const CRLF = 301; - const INVALID = 302; - const ASCII_INVALID_FROM = 127; - const ASCII_INVALID_TO = 199; + //ASCII values + const C_DEL = 127; + const C_NUL = 0; + const S_AT = 64; + const S_BACKSLASH = 92; + const S_DOT = 46; + const S_DQUOTE = 34; + const S_SQUOTE = 39; + const S_BACKTICK = 96; + const S_OPENPARENTHESIS = 49; + const S_CLOSEPARENTHESIS = 261; + const S_OPENBRACKET = 262; + const S_CLOSEBRACKET = 263; + const S_HYPHEN = 264; + const S_COLON = 265; + const S_DOUBLECOLON = 266; + const S_SP = 267; + const S_HTAB = 268; + const S_CR = 269; + const S_LF = 270; + const S_IPV6TAG = 271; + const S_LOWERTHAN = 272; + const S_GREATERTHAN = 273; + const S_COMMA = 274; + const S_SEMICOLON = 275; + const S_OPENQBRACKET = 276; + const S_CLOSEQBRACKET = 277; + const S_SLASH = 278; + const S_EMPTY = null; + const GENERIC = 300; + const CRLF = 301; + const INVALID = 302; + const ASCII_INVALID_FROM = 127; + const ASCII_INVALID_TO = 199; - /** - * US-ASCII visible characters not valid for atext (@link http://tools.ietf.org/html/rfc5322#section-3.2.3) - * - * @var array - */ - protected $charValue = array( - '(' => self::S_OPENPARENTHESIS, - ')' => self::S_CLOSEPARENTHESIS, - '<' => self::S_LOWERTHAN, - '>' => self::S_GREATERTHAN, - '[' => self::S_OPENBRACKET, - ']' => self::S_CLOSEBRACKET, - ':' => self::S_COLON, - ';' => self::S_SEMICOLON, - '@' => self::S_AT, - '\\' => self::S_BACKSLASH, - '/' => self::S_SLASH, - ',' => self::S_COMMA, - '.' => self::S_DOT, - "'" => self::S_SQUOTE, - "`" => self::S_BACKTICK, - '"' => self::S_DQUOTE, - '-' => self::S_HYPHEN, - '::' => self::S_DOUBLECOLON, - ' ' => self::S_SP, - "\t" => self::S_HTAB, - "\r" => self::S_CR, - "\n" => self::S_LF, - "\r\n" => self::CRLF, - 'IPv6' => self::S_IPV6TAG, - '{' => self::S_OPENQBRACKET, - '}' => self::S_CLOSEQBRACKET, - '' => self::S_EMPTY, - '\0' => self::C_NUL, - ); + /** + * US-ASCII visible characters not valid for atext (@link http://tools.ietf.org/html/rfc5322#section-3.2.3) + * + * @var array + */ + protected $charValue = array( + '(' => self::S_OPENPARENTHESIS, + ')' => self::S_CLOSEPARENTHESIS, + '<' => self::S_LOWERTHAN, + '>' => self::S_GREATERTHAN, + '[' => self::S_OPENBRACKET, + ']' => self::S_CLOSEBRACKET, + ':' => self::S_COLON, + ';' => self::S_SEMICOLON, + '@' => self::S_AT, + '\\' => self::S_BACKSLASH, + '/' => self::S_SLASH, + ',' => self::S_COMMA, + '.' => self::S_DOT, + "'" => self::S_SQUOTE, + "`" => self::S_BACKTICK, + '"' => self::S_DQUOTE, + '-' => self::S_HYPHEN, + '::' => self::S_DOUBLECOLON, + ' ' => self::S_SP, + "\t" => self::S_HTAB, + "\r" => self::S_CR, + "\n" => self::S_LF, + "\r\n" => self::CRLF, + 'IPv6' => self::S_IPV6TAG, + '{' => self::S_OPENQBRACKET, + '}' => self::S_CLOSEQBRACKET, + '' => self::S_EMPTY, + '\0' => self::C_NUL, + ); - /** - * @var bool - */ - protected $hasInvalidTokens = false; + /** + * @var bool + */ + protected $hasInvalidTokens = false; - /** - * @var array - * - * @psalm-var array{value:string, type:null|int, position:int}|array - */ - protected $previous = []; + /** + * @var array + * + * @psalm-var array{value:string, type:null|int, position:int}|array + */ + protected $previous = []; - /** - * The last matched/seen token. - * - * @var array - * - * @psalm-var array{value:string, type:null|int, position:int} - */ - public $token; + /** + * The last matched/seen token. + * + * @var array + * + * @psalm-var array{value:string, type:null|int, position:int} + */ + public $token; - /** - * The next token in the input. - * - * @var array|null - */ - public $lookahead; + /** + * The next token in the input. + * + * @var array|null + */ + public $lookahead; - /** - * @psalm-var array{value:'', type:null, position:0} - */ - private static $nullToken = [ - 'value' => '', - 'type' => null, - 'position' => 0, - ]; + /** + * @psalm-var array{value:'', type:null, position:0} + */ + private static $nullToken = [ + 'value' => '', + 'type' => null, + 'position' => 0, + ]; - public function __construct() - { - $this->previous = $this->token = self::$nullToken; - $this->lookahead = null; - } + public function __construct() + { + $this->previous = $this->token = self::$nullToken; + $this->lookahead = null; + } - /** - * @return void - */ - public function reset() - { - $this->hasInvalidTokens = false; - parent::reset(); - $this->previous = $this->token = self::$nullToken; - } + /** + * @return void + */ + public function reset() + { + $this->hasInvalidTokens = false; + parent::reset(); + $this->previous = $this->token = self::$nullToken; + } - /** - * @return bool - */ - public function hasInvalidTokens() - { - return $this->hasInvalidTokens; - } + /** + * @return bool + */ + public function hasInvalidTokens() + { + return $this->hasInvalidTokens; + } - /** - * @param int $type - * @throws \UnexpectedValueException - * @return boolean - * - * @psalm-suppress InvalidScalarArgument - */ - public function find($type) - { - $search = clone $this; - $search->skipUntil($type); + /** + * @param int $type + * @throws \UnexpectedValueException + * @return boolean + * + * @psalm-suppress InvalidScalarArgument + */ + public function find($type) + { + $search = clone $this; + $search->skipUntil($type); - if (!$search->lookahead) { - throw new \UnexpectedValueException($type . ' not found'); - } - return true; - } + if (!$search->lookahead) { + throw new \UnexpectedValueException($type . ' not found'); + } + return true; + } - /** - * getPrevious - * - * @return array - */ - public function getPrevious() - { - return $this->previous; - } + /** + * getPrevious + * + * @return array + */ + public function getPrevious() + { + return $this->previous; + } - /** - * moveNext - * - * @return boolean - */ - public function moveNext() - { - $this->previous = $this->token; - $hasNext = parent::moveNext(); - $this->token = $this->token ?: self::$nullToken; + /** + * moveNext + * + * @return boolean + */ + public function moveNext() + { + $this->previous = $this->token; + $hasNext = parent::moveNext(); + $this->token = $this->token ?: self::$nullToken; - return $hasNext; - } + return $hasNext; + } - /** - * Lexical catchable patterns. - * - * @return string[] - */ - protected function getCatchablePatterns() - { - return array( - '[a-zA-Z_]+[46]?', //ASCII and domain literal - '[^\x00-\x7F]', //UTF-8 - '[0-9]+', - '\r\n', - '::', - '\s+?', - '.', - ); - } + /** + * Lexical catchable patterns. + * + * @return string[] + */ + protected function getCatchablePatterns() + { + return array( + '[a-zA-Z_]+[46]?', //ASCII and domain literal + '[^\x00-\x7F]', //UTF-8 + '[0-9]+', + '\r\n', + '::', + '\s+?', + '.', + ); + } - /** - * Lexical non-catchable patterns. - * - * @return string[] - */ - protected function getNonCatchablePatterns() - { - return array('[\xA0-\xff]+'); - } + /** + * Lexical non-catchable patterns. + * + * @return string[] + */ + protected function getNonCatchablePatterns() + { + return array('[\xA0-\xff]+'); + } - /** - * Retrieve token type. Also processes the token value if necessary. - * - * @param string $value - * @throws \InvalidArgumentException - * @return integer - */ - protected function getType(&$value) - { - if ($this->isNullType($value)) { - return self::C_NUL; - } + /** + * Retrieve token type. Also processes the token value if necessary. + * + * @param string $value + * @throws \InvalidArgumentException + * @return integer + */ + protected function getType(&$value) + { + if ($this->isNullType($value)) { + return self::C_NUL; + } - if ($this->isValid($value)) { - return $this->charValue[$value]; - } + if ($this->isValid($value)) { + return $this->charValue[$value]; + } - if ($this->isUTF8Invalid($value)) { - $this->hasInvalidTokens = true; - return self::INVALID; - } + if ($this->isUTF8Invalid($value)) { + $this->hasInvalidTokens = true; + return self::INVALID; + } - return self::GENERIC; - } + return self::GENERIC; + } - /** - * @param string $value - * - * @return bool - */ - protected function isValid($value) - { - if (isset($this->charValue[$value])) { - return true; - } + /** + * @param string $value + * + * @return bool + */ + protected function isValid($value) + { + if (isset($this->charValue[$value])) { + return true; + } - return false; - } + return false; + } - /** - * @param string $value - * @return bool - */ - protected function isNullType($value) - { - if ($value === "\0") { - return true; - } + /** + * @param string $value + * @return bool + */ + protected function isNullType($value) + { + if ($value === "\0") { + return true; + } - return false; - } + return false; + } - /** - * @param string $value - * @return bool - */ - protected function isUTF8Invalid($value) - { - if (preg_match('/\p{Cc}+/u', $value)) { - return true; - } + /** + * @param string $value + * @return bool + */ + protected function isUTF8Invalid($value) + { + if (preg_match('/\p{Cc}+/u', $value)) { + return true; + } - return false; - } + return false; + } - /** - * @return string - */ - protected function getModifiers() - { - return 'iu'; - } + /** + * @return string + */ + protected function getModifiers() + { + return 'iu'; + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/EmailParser.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/EmailParser.php index cf9e7652339..6b7bad66927 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/EmailParser.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/EmailParser.php @@ -15,123 +15,123 @@ use Egulias\EmailValidator\Warning\EmailTooLong; */ class EmailParser { - const EMAIL_MAX_LENGTH = 254; + const EMAIL_MAX_LENGTH = 254; - /** - * @var array - */ - protected $warnings = []; + /** + * @var array + */ + protected $warnings = []; - /** - * @var string - */ - protected $domainPart = ''; + /** + * @var string + */ + protected $domainPart = ''; - /** - * @var string - */ - protected $localPart = ''; - /** - * @var EmailLexer - */ - protected $lexer; + /** + * @var string + */ + protected $localPart = ''; + /** + * @var EmailLexer + */ + protected $lexer; - /** - * @var LocalPart - */ - protected $localPartParser; + /** + * @var LocalPart + */ + protected $localPartParser; - /** - * @var DomainPart - */ - protected $domainPartParser; + /** + * @var DomainPart + */ + protected $domainPartParser; - public function __construct(EmailLexer $lexer) - { - $this->lexer = $lexer; - $this->localPartParser = new LocalPart($this->lexer); - $this->domainPartParser = new DomainPart($this->lexer); - } + public function __construct(EmailLexer $lexer) + { + $this->lexer = $lexer; + $this->localPartParser = new LocalPart($this->lexer); + $this->domainPartParser = new DomainPart($this->lexer); + } - /** - * @param string $str - * @return array - */ - public function parse($str) - { - $this->lexer->setInput($str); + /** + * @param string $str + * @return array + */ + public function parse($str) + { + $this->lexer->setInput($str); - if (!$this->hasAtToken()) { - throw new NoLocalPart(); - } + if (!$this->hasAtToken()) { + throw new NoLocalPart(); + } - $this->localPartParser->parse($str); - $this->domainPartParser->parse($str); + $this->localPartParser->parse($str); + $this->domainPartParser->parse($str); - $this->setParts($str); + $this->setParts($str); - if ($this->lexer->hasInvalidTokens()) { - throw new ExpectingATEXT(); - } + if ($this->lexer->hasInvalidTokens()) { + throw new ExpectingATEXT(); + } - return array('local' => $this->localPart, 'domain' => $this->domainPart); - } + return array('local' => $this->localPart, 'domain' => $this->domainPart); + } - /** - * @return Warning\Warning[] - */ - public function getWarnings() - { - $localPartWarnings = $this->localPartParser->getWarnings(); - $domainPartWarnings = $this->domainPartParser->getWarnings(); - $this->warnings = array_merge($localPartWarnings, $domainPartWarnings); + /** + * @return Warning\Warning[] + */ + public function getWarnings() + { + $localPartWarnings = $this->localPartParser->getWarnings(); + $domainPartWarnings = $this->domainPartParser->getWarnings(); + $this->warnings = array_merge($localPartWarnings, $domainPartWarnings); - $this->addLongEmailWarning($this->localPart, $this->domainPart); + $this->addLongEmailWarning($this->localPart, $this->domainPart); - return $this->warnings; - } + return $this->warnings; + } - /** - * @return string - */ - public function getParsedDomainPart() - { - return $this->domainPart; - } + /** + * @return string + */ + public function getParsedDomainPart() + { + return $this->domainPart; + } - /** - * @param string $email - */ - protected function setParts($email) - { - $parts = explode('@', $email); - $this->domainPart = $this->domainPartParser->getDomainPart(); - $this->localPart = $parts[0]; - } + /** + * @param string $email + */ + protected function setParts($email) + { + $parts = explode('@', $email); + $this->domainPart = $this->domainPartParser->getDomainPart(); + $this->localPart = $parts[0]; + } - /** - * @return bool - */ - protected function hasAtToken() - { - $this->lexer->moveNext(); - $this->lexer->moveNext(); - if ($this->lexer->token['type'] === EmailLexer::S_AT) { - return false; - } + /** + * @return bool + */ + protected function hasAtToken() + { + $this->lexer->moveNext(); + $this->lexer->moveNext(); + if ($this->lexer->token['type'] === EmailLexer::S_AT) { + return false; + } - return true; - } + return true; + } - /** - * @param string $localPart - * @param string $parsedDomainPart - */ - protected function addLongEmailWarning($localPart, $parsedDomainPart) - { - if (strlen($localPart . '@' . $parsedDomainPart) > self::EMAIL_MAX_LENGTH) { - $this->warnings[EmailTooLong::CODE] = new EmailTooLong(); - } - } + /** + * @param string $localPart + * @param string $parsedDomainPart + */ + protected function addLongEmailWarning($localPart, $parsedDomainPart) + { + if (strlen($localPart . '@' . $parsedDomainPart) > self::EMAIL_MAX_LENGTH) { + $this->warnings[EmailTooLong::CODE] = new EmailTooLong(); + } + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/EmailValidator.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/EmailValidator.php index e0532e618a6..a30f21dcd30 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/EmailValidator.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/EmailValidator.php @@ -7,61 +7,61 @@ use Egulias\EmailValidator\Validation\EmailValidation; class EmailValidator { - /** - * @var EmailLexer - */ - private $lexer; + /** + * @var EmailLexer + */ + private $lexer; - /** - * @var Warning\Warning[] - */ - protected $warnings = []; + /** + * @var Warning\Warning[] + */ + protected $warnings = []; - /** - * @var InvalidEmail|null - */ - protected $error; + /** + * @var InvalidEmail|null + */ + protected $error; - public function __construct() - { - $this->lexer = new EmailLexer(); - } + public function __construct() + { + $this->lexer = new EmailLexer(); + } - /** - * @param string $email - * @param EmailValidation $emailValidation - * @return bool - */ - public function isValid($email, EmailValidation $emailValidation) - { - $isValid = $emailValidation->isValid($email, $this->lexer); - $this->warnings = $emailValidation->getWarnings(); - $this->error = $emailValidation->getError(); + /** + * @param string $email + * @param EmailValidation $emailValidation + * @return bool + */ + public function isValid($email, EmailValidation $emailValidation) + { + $isValid = $emailValidation->isValid($email, $this->lexer); + $this->warnings = $emailValidation->getWarnings(); + $this->error = $emailValidation->getError(); - return $isValid; - } + return $isValid; + } - /** - * @return boolean - */ - public function hasWarnings() - { - return !empty($this->warnings); - } + /** + * @return boolean + */ + public function hasWarnings() + { + return !empty($this->warnings); + } - /** - * @return array - */ - public function getWarnings() - { - return $this->warnings; - } + /** + * @return array + */ + public function getWarnings() + { + return $this->warnings; + } - /** - * @return InvalidEmail|null - */ - public function getError() - { - return $this->error; - } + /** + * @return InvalidEmail|null + */ + public function getError() + { + return $this->error; + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/DomainAcceptsNoMail.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/DomainAcceptsNoMail.php index 822258f6f07..40a99705ce9 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/DomainAcceptsNoMail.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/DomainAcceptsNoMail.php @@ -4,6 +4,6 @@ namespace Egulias\EmailValidator\Exception; class DomainAcceptsNoMail extends InvalidEmail { - const CODE = 154; - const REASON = 'Domain accepts no mail (Null MX, RFC7505)'; -} + const CODE = 154; + const REASON = 'Domain accepts no mail (Null MX, RFC7505)'; +} \ No newline at end of file diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/ExpectingQPair.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/ExpectingQPair.php index ea9fc690bfa..a738eeb62f0 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/ExpectingQPair.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/ExpectingQPair.php @@ -4,6 +4,6 @@ namespace Egulias\EmailValidator\Exception; class ExpectingQPair extends InvalidEmail { - const CODE = 136; - const REASON = "Expecting QPAIR"; + const CODE = 136; + const REASON = "Expecting QPAIR"; } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/LocalOrReservedDomain.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/LocalOrReservedDomain.php index 964a6406726..695b05a46d4 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/LocalOrReservedDomain.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/LocalOrReservedDomain.php @@ -4,6 +4,6 @@ namespace Egulias\EmailValidator\Exception; class LocalOrReservedDomain extends InvalidEmail { - const CODE = 153; - const REASON = 'Local, mDNS or reserved domain (RFC2606, RFC6762)'; -} + const CODE = 153; + const REASON = 'Local, mDNS or reserved domain (RFC2606, RFC6762)'; +} \ No newline at end of file diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/NoDNSRecord.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/NoDNSRecord.php index 3e551ea6c11..0aa5fa78902 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/NoDNSRecord.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/NoDNSRecord.php @@ -4,6 +4,6 @@ namespace Egulias\EmailValidator\Exception; class NoDNSRecord extends InvalidEmail { - const CODE = 5; - const REASON = 'No MX or A DSN record was found for this email'; + const CODE = 5; + const REASON = 'No MX or A DSN record was found for this email'; } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/UnclosedComment.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/UnclosedComment.php index 40d9ab31fb7..86b2b09622d 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/UnclosedComment.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Exception/UnclosedComment.php @@ -4,6 +4,6 @@ namespace Egulias\EmailValidator\Exception; class UnclosedComment extends InvalidEmail { - const CODE = 146; - const REASON = "No closing comment token found"; + const CODE = 146; + const REASON = "No closing comment token found"; } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Parser/DomainPart.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Parser/DomainPart.php index 8a0a8fe2674..4dadba8af7c 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Parser/DomainPart.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Parser/DomainPart.php @@ -34,409 +34,410 @@ use Egulias\EmailValidator\Warning\TLD; class DomainPart extends Parser { - const DOMAIN_MAX_LENGTH = 254; - const LABEL_MAX_LENGTH = 63; - - /** - * @var string - */ - protected $domainPart = ''; - - public function parse($domainPart) - { - $this->lexer->moveNext(); - - $this->performDomainStartChecks(); - - $domain = $this->doParseDomainPart(); - - $prev = $this->lexer->getPrevious(); - $length = strlen($domain); - - if ($prev['type'] === EmailLexer::S_DOT) { - throw new DotAtEnd(); - } - if ($prev['type'] === EmailLexer::S_HYPHEN) { - throw new DomainHyphened(); - } - if ($length > self::DOMAIN_MAX_LENGTH) { - $this->warnings[DomainTooLong::CODE] = new DomainTooLong(); - } - if ($prev['type'] === EmailLexer::S_CR) { - throw new CRLFAtTheEnd(); - } - $this->domainPart = $domain; - } - - private function performDomainStartChecks() - { - $this->checkInvalidTokensAfterAT(); - $this->checkEmptyDomain(); - - if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) { - $this->warnings[DeprecatedComment::CODE] = new DeprecatedComment(); - $this->parseDomainComments(); - } - } - - private function checkEmptyDomain() - { - $thereIsNoDomain = $this->lexer->token['type'] === EmailLexer::S_EMPTY || - ($this->lexer->token['type'] === EmailLexer::S_SP && - !$this->lexer->isNextToken(EmailLexer::GENERIC)); - - if ($thereIsNoDomain) { - throw new NoDomainPart(); - } - } - - private function checkInvalidTokensAfterAT() - { - if ($this->lexer->token['type'] === EmailLexer::S_DOT) { - throw new DotAtStart(); - } - if ($this->lexer->token['type'] === EmailLexer::S_HYPHEN) { - throw new DomainHyphened(); - } - } - - /** - * @return string - */ - public function getDomainPart() - { - return $this->domainPart; - } - - /** - * @param string $addressLiteral - * @param int $maxGroups - */ - public function checkIPV6Tag($addressLiteral, $maxGroups = 8) - { - $prev = $this->lexer->getPrevious(); - if ($prev['type'] === EmailLexer::S_COLON) { - $this->warnings[IPV6ColonEnd::CODE] = new IPV6ColonEnd(); - } - - $IPv6 = substr($addressLiteral, 5); - //Daniel Marschall's new IPv6 testing strategy - $matchesIP = explode(':', $IPv6); - $groupCount = count($matchesIP); - $colons = strpos($IPv6, '::'); - - if (count(preg_grep('/^[0-9A-Fa-f]{0,4}$/', $matchesIP, PREG_GREP_INVERT)) !== 0) { - $this->warnings[IPV6BadChar::CODE] = new IPV6BadChar(); - } - - if ($colons === false) { - // We need exactly the right number of groups - if ($groupCount !== $maxGroups) { - $this->warnings[IPV6GroupCount::CODE] = new IPV6GroupCount(); - } - return; - } - - if ($colons !== strrpos($IPv6, '::')) { - $this->warnings[IPV6DoubleColon::CODE] = new IPV6DoubleColon(); - return; - } - - if ($colons === 0 || $colons === (strlen($IPv6) - 2)) { - // RFC 4291 allows :: at the start or end of an address - //with 7 other groups in addition - ++$maxGroups; - } - - if ($groupCount > $maxGroups) { - $this->warnings[IPV6MaxGroups::CODE] = new IPV6MaxGroups(); - } elseif ($groupCount === $maxGroups) { - $this->warnings[IPV6Deprecated::CODE] = new IPV6Deprecated(); - } - } - - /** - * @return string - */ - protected function doParseDomainPart() - { - $domain = ''; - $label = ''; - $openedParenthesis = 0; - do { - $prev = $this->lexer->getPrevious(); - - $this->checkNotAllowedChars($this->lexer->token); - - if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) { - $this->parseComments(); - $openedParenthesis += $this->getOpenedParenthesis(); - $this->lexer->moveNext(); - $tmpPrev = $this->lexer->getPrevious(); - if ($tmpPrev['type'] === EmailLexer::S_CLOSEPARENTHESIS) { - $openedParenthesis--; - } - } - if ($this->lexer->token['type'] === EmailLexer::S_CLOSEPARENTHESIS) { - if ($openedParenthesis === 0) { - throw new UnopenedComment(); - } else { - $openedParenthesis--; - } - } - - $this->checkConsecutiveDots(); - $this->checkDomainPartExceptions($prev); - - if ($this->hasBrackets()) { - $this->parseDomainLiteral(); - } - - if ($this->lexer->token['type'] === EmailLexer::S_DOT) { - $this->checkLabelLength($label); - $label = ''; - } else { - $label .= $this->lexer->token['value']; - } - - if ($this->isFWS()) { - $this->parseFWS(); - } - - $domain .= $this->lexer->token['value']; - $this->lexer->moveNext(); - if ($this->lexer->token['type'] === EmailLexer::S_SP) { - throw new CharNotAllowed(); - } - } while (null !== $this->lexer->token['type']); - - $this->checkLabelLength($label); - - return $domain; - } - - private function checkNotAllowedChars(array $token) - { - $notAllowed = [EmailLexer::S_BACKSLASH => true, EmailLexer::S_SLASH=> true]; - if (isset($notAllowed[$token['type']])) { - throw new CharNotAllowed(); - } - } - - /** - * @return string|false - */ - protected function parseDomainLiteral() - { - if ($this->lexer->isNextToken(EmailLexer::S_COLON)) { - $this->warnings[IPV6ColonStart::CODE] = new IPV6ColonStart(); - } - if ($this->lexer->isNextToken(EmailLexer::S_IPV6TAG)) { - $lexer = clone $this->lexer; - $lexer->moveNext(); - if ($lexer->isNextToken(EmailLexer::S_DOUBLECOLON)) { - $this->warnings[IPV6ColonStart::CODE] = new IPV6ColonStart(); - } - } - - return $this->doParseDomainLiteral(); - } - - /** - * @return string|false - */ - protected function doParseDomainLiteral() - { - $IPv6TAG = false; - $addressLiteral = ''; - do { - if ($this->lexer->token['type'] === EmailLexer::C_NUL) { - throw new ExpectingDTEXT(); - } - - if ($this->lexer->token['type'] === EmailLexer::INVALID || - $this->lexer->token['type'] === EmailLexer::C_DEL || - $this->lexer->token['type'] === EmailLexer::S_LF - ) { - $this->warnings[ObsoleteDTEXT::CODE] = new ObsoleteDTEXT(); - } - - if ($this->lexer->isNextTokenAny(array(EmailLexer::S_OPENQBRACKET, EmailLexer::S_OPENBRACKET))) { - throw new ExpectingDTEXT(); - } - - if ($this->lexer->isNextTokenAny( - array(EmailLexer::S_HTAB, EmailLexer::S_SP, $this->lexer->token['type'] === EmailLexer::CRLF) - )) { - $this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS(); - $this->parseFWS(); - } - - if ($this->lexer->isNextToken(EmailLexer::S_CR)) { - throw new CRNoLF(); - } - - if ($this->lexer->token['type'] === EmailLexer::S_BACKSLASH) { - $this->warnings[ObsoleteDTEXT::CODE] = new ObsoleteDTEXT(); - $addressLiteral .= $this->lexer->token['value']; - $this->lexer->moveNext(); - $this->validateQuotedPair(); - } - if ($this->lexer->token['type'] === EmailLexer::S_IPV6TAG) { - $IPv6TAG = true; - } - if ($this->lexer->token['type'] === EmailLexer::S_CLOSEQBRACKET) { - break; - } - - $addressLiteral .= $this->lexer->token['value']; - } while ($this->lexer->moveNext()); - - $addressLiteral = str_replace('[', '', $addressLiteral); - $addressLiteral = $this->checkIPV4Tag($addressLiteral); - - if (false === $addressLiteral) { - return $addressLiteral; - } - - if (!$IPv6TAG) { - $this->warnings[DomainLiteral::CODE] = new DomainLiteral(); - return $addressLiteral; - } - - $this->warnings[AddressLiteral::CODE] = new AddressLiteral(); - - $this->checkIPV6Tag($addressLiteral); - - return $addressLiteral; - } - - /** - * @param string $addressLiteral - * - * @return string|false - */ - protected function checkIPV4Tag($addressLiteral) - { - $matchesIP = array(); - - // Extract IPv4 part from the end of the address-literal (if there is one) - if (preg_match( - '/\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/', - $addressLiteral, - $matchesIP - ) > 0 - ) { - $index = strrpos($addressLiteral, $matchesIP[0]); - if ($index === 0) { - $this->warnings[AddressLiteral::CODE] = new AddressLiteral(); - return false; - } - // Convert IPv4 part to IPv6 format for further testing - $addressLiteral = substr($addressLiteral, 0, (int) $index) . '0:0'; - } - - return $addressLiteral; - } - - protected function checkDomainPartExceptions(array $prev) - { - $invalidDomainTokens = array( - EmailLexer::S_DQUOTE => true, - EmailLexer::S_SQUOTE => true, - EmailLexer::S_BACKTICK => true, - EmailLexer::S_SEMICOLON => true, - EmailLexer::S_GREATERTHAN => true, - EmailLexer::S_LOWERTHAN => true, - ); - - if (isset($invalidDomainTokens[$this->lexer->token['type']])) { - throw new ExpectingATEXT(); - } - - if ($this->lexer->token['type'] === EmailLexer::S_COMMA) { - throw new CommaInDomain(); - } - - if ($this->lexer->token['type'] === EmailLexer::S_AT) { - throw new ConsecutiveAt(); - } - - if ($this->lexer->token['type'] === EmailLexer::S_OPENQBRACKET && $prev['type'] !== EmailLexer::S_AT) { - throw new ExpectingATEXT(); - } - - if ($this->lexer->token['type'] === EmailLexer::S_HYPHEN && $this->lexer->isNextToken(EmailLexer::S_DOT)) { - throw new DomainHyphened(); - } - - if ($this->lexer->token['type'] === EmailLexer::S_BACKSLASH - && $this->lexer->isNextToken(EmailLexer::GENERIC)) { - throw new ExpectingATEXT(); - } - } - - /** - * @return bool - */ - protected function hasBrackets() - { - if ($this->lexer->token['type'] !== EmailLexer::S_OPENBRACKET) { - return false; - } - - try { - $this->lexer->find(EmailLexer::S_CLOSEBRACKET); - } catch (\RuntimeException $e) { - throw new ExpectingDomainLiteralClose(); - } - - return true; - } - - /** - * @param string $label - */ - protected function checkLabelLength($label) - { - if ($this->isLabelTooLong($label)) { - $this->warnings[LabelTooLong::CODE] = new LabelTooLong(); - } - } - - /** - * @param string $label - * @return bool - */ - private function isLabelTooLong($label) - { - if (preg_match('/[^\x00-\x7F]/', $label)) { - idn_to_ascii($label, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46, $idnaInfo); - - return (bool) ($idnaInfo['errors'] & IDNA_ERROR_LABEL_TOO_LONG); - } - - return strlen($label) > self::LABEL_MAX_LENGTH; - } - - protected function parseDomainComments() - { - $this->isUnclosedComment(); - while (!$this->lexer->isNextToken(EmailLexer::S_CLOSEPARENTHESIS)) { - $this->warnEscaping(); - $this->lexer->moveNext(); - } - - $this->lexer->moveNext(); - if ($this->lexer->isNextToken(EmailLexer::S_DOT)) { - throw new ExpectingATEXT(); - } - } - - protected function addTLDWarnings() - { - if ($this->warnings[DomainLiteral::CODE]) { - $this->warnings[TLD::CODE] = new TLD(); - } - } + const DOMAIN_MAX_LENGTH = 254; + const LABEL_MAX_LENGTH = 63; + + /** + * @var string + */ + protected $domainPart = ''; + + public function parse($domainPart) + { + $this->lexer->moveNext(); + + $this->performDomainStartChecks(); + + $domain = $this->doParseDomainPart(); + + $prev = $this->lexer->getPrevious(); + $length = strlen($domain); + + if ($prev['type'] === EmailLexer::S_DOT) { + throw new DotAtEnd(); + } + if ($prev['type'] === EmailLexer::S_HYPHEN) { + throw new DomainHyphened(); + } + if ($length > self::DOMAIN_MAX_LENGTH) { + $this->warnings[DomainTooLong::CODE] = new DomainTooLong(); + } + if ($prev['type'] === EmailLexer::S_CR) { + throw new CRLFAtTheEnd(); + } + $this->domainPart = $domain; + } + + private function performDomainStartChecks() + { + $this->checkInvalidTokensAfterAT(); + $this->checkEmptyDomain(); + + if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) { + $this->warnings[DeprecatedComment::CODE] = new DeprecatedComment(); + $this->parseDomainComments(); + } + } + + private function checkEmptyDomain() + { + $thereIsNoDomain = $this->lexer->token['type'] === EmailLexer::S_EMPTY || + ($this->lexer->token['type'] === EmailLexer::S_SP && + !$this->lexer->isNextToken(EmailLexer::GENERIC)); + + if ($thereIsNoDomain) { + throw new NoDomainPart(); + } + } + + private function checkInvalidTokensAfterAT() + { + if ($this->lexer->token['type'] === EmailLexer::S_DOT) { + throw new DotAtStart(); + } + if ($this->lexer->token['type'] === EmailLexer::S_HYPHEN) { + throw new DomainHyphened(); + } + } + + /** + * @return string + */ + public function getDomainPart() + { + return $this->domainPart; + } + + /** + * @param string $addressLiteral + * @param int $maxGroups + */ + public function checkIPV6Tag($addressLiteral, $maxGroups = 8) + { + $prev = $this->lexer->getPrevious(); + if ($prev['type'] === EmailLexer::S_COLON) { + $this->warnings[IPV6ColonEnd::CODE] = new IPV6ColonEnd(); + } + + $IPv6 = substr($addressLiteral, 5); + //Daniel Marschall's new IPv6 testing strategy + $matchesIP = explode(':', $IPv6); + $groupCount = count($matchesIP); + $colons = strpos($IPv6, '::'); + + if (count(preg_grep('/^[0-9A-Fa-f]{0,4}$/', $matchesIP, PREG_GREP_INVERT)) !== 0) { + $this->warnings[IPV6BadChar::CODE] = new IPV6BadChar(); + } + + if ($colons === false) { + // We need exactly the right number of groups + if ($groupCount !== $maxGroups) { + $this->warnings[IPV6GroupCount::CODE] = new IPV6GroupCount(); + } + return; + } + + if ($colons !== strrpos($IPv6, '::')) { + $this->warnings[IPV6DoubleColon::CODE] = new IPV6DoubleColon(); + return; + } + + if ($colons === 0 || $colons === (strlen($IPv6) - 2)) { + // RFC 4291 allows :: at the start or end of an address + //with 7 other groups in addition + ++$maxGroups; + } + + if ($groupCount > $maxGroups) { + $this->warnings[IPV6MaxGroups::CODE] = new IPV6MaxGroups(); + } elseif ($groupCount === $maxGroups) { + $this->warnings[IPV6Deprecated::CODE] = new IPV6Deprecated(); + } + } + + /** + * @return string + */ + protected function doParseDomainPart() + { + $domain = ''; + $label = ''; + $openedParenthesis = 0; + do { + $prev = $this->lexer->getPrevious(); + + $this->checkNotAllowedChars($this->lexer->token); + + if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) { + $this->parseComments(); + $openedParenthesis += $this->getOpenedParenthesis(); + $this->lexer->moveNext(); + $tmpPrev = $this->lexer->getPrevious(); + if ($tmpPrev['type'] === EmailLexer::S_CLOSEPARENTHESIS) { + $openedParenthesis--; + } + } + if ($this->lexer->token['type'] === EmailLexer::S_CLOSEPARENTHESIS) { + if ($openedParenthesis === 0) { + throw new UnopenedComment(); + } else { + $openedParenthesis--; + } + } + + $this->checkConsecutiveDots(); + $this->checkDomainPartExceptions($prev); + + if ($this->hasBrackets()) { + $this->parseDomainLiteral(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_DOT) { + $this->checkLabelLength($label); + $label = ''; + } else { + $label .= $this->lexer->token['value']; + } + + if ($this->isFWS()) { + $this->parseFWS(); + } + + $domain .= $this->lexer->token['value']; + $this->lexer->moveNext(); + if ($this->lexer->token['type'] === EmailLexer::S_SP) { + throw new CharNotAllowed(); + } + } while (null !== $this->lexer->token['type']); + + $this->checkLabelLength($label); + + return $domain; + } + + private function checkNotAllowedChars(array $token) + { + $notAllowed = [EmailLexer::S_BACKSLASH => true, EmailLexer::S_SLASH=> true]; + if (isset($notAllowed[$token['type']])) { + throw new CharNotAllowed(); + } + } + + /** + * @return string|false + */ + protected function parseDomainLiteral() + { + if ($this->lexer->isNextToken(EmailLexer::S_COLON)) { + $this->warnings[IPV6ColonStart::CODE] = new IPV6ColonStart(); + } + if ($this->lexer->isNextToken(EmailLexer::S_IPV6TAG)) { + $lexer = clone $this->lexer; + $lexer->moveNext(); + if ($lexer->isNextToken(EmailLexer::S_DOUBLECOLON)) { + $this->warnings[IPV6ColonStart::CODE] = new IPV6ColonStart(); + } + } + + return $this->doParseDomainLiteral(); + } + + /** + * @return string|false + */ + protected function doParseDomainLiteral() + { + $IPv6TAG = false; + $addressLiteral = ''; + do { + if ($this->lexer->token['type'] === EmailLexer::C_NUL) { + throw new ExpectingDTEXT(); + } + + if ($this->lexer->token['type'] === EmailLexer::INVALID || + $this->lexer->token['type'] === EmailLexer::C_DEL || + $this->lexer->token['type'] === EmailLexer::S_LF + ) { + $this->warnings[ObsoleteDTEXT::CODE] = new ObsoleteDTEXT(); + } + + if ($this->lexer->isNextTokenAny(array(EmailLexer::S_OPENQBRACKET, EmailLexer::S_OPENBRACKET))) { + throw new ExpectingDTEXT(); + } + + if ($this->lexer->isNextTokenAny( + array(EmailLexer::S_HTAB, EmailLexer::S_SP, $this->lexer->token['type'] === EmailLexer::CRLF) + )) { + $this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS(); + $this->parseFWS(); + } + + if ($this->lexer->isNextToken(EmailLexer::S_CR)) { + throw new CRNoLF(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_BACKSLASH) { + $this->warnings[ObsoleteDTEXT::CODE] = new ObsoleteDTEXT(); + $addressLiteral .= $this->lexer->token['value']; + $this->lexer->moveNext(); + $this->validateQuotedPair(); + } + if ($this->lexer->token['type'] === EmailLexer::S_IPV6TAG) { + $IPv6TAG = true; + } + if ($this->lexer->token['type'] === EmailLexer::S_CLOSEQBRACKET) { + break; + } + + $addressLiteral .= $this->lexer->token['value']; + + } while ($this->lexer->moveNext()); + + $addressLiteral = str_replace('[', '', $addressLiteral); + $addressLiteral = $this->checkIPV4Tag($addressLiteral); + + if (false === $addressLiteral) { + return $addressLiteral; + } + + if (!$IPv6TAG) { + $this->warnings[DomainLiteral::CODE] = new DomainLiteral(); + return $addressLiteral; + } + + $this->warnings[AddressLiteral::CODE] = new AddressLiteral(); + + $this->checkIPV6Tag($addressLiteral); + + return $addressLiteral; + } + + /** + * @param string $addressLiteral + * + * @return string|false + */ + protected function checkIPV4Tag($addressLiteral) + { + $matchesIP = array(); + + // Extract IPv4 part from the end of the address-literal (if there is one) + if (preg_match( + '/\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/', + $addressLiteral, + $matchesIP + ) > 0 + ) { + $index = strrpos($addressLiteral, $matchesIP[0]); + if ($index === 0) { + $this->warnings[AddressLiteral::CODE] = new AddressLiteral(); + return false; + } + // Convert IPv4 part to IPv6 format for further testing + $addressLiteral = substr($addressLiteral, 0, (int) $index) . '0:0'; + } + + return $addressLiteral; + } + + protected function checkDomainPartExceptions(array $prev) + { + $invalidDomainTokens = array( + EmailLexer::S_DQUOTE => true, + EmailLexer::S_SQUOTE => true, + EmailLexer::S_BACKTICK => true, + EmailLexer::S_SEMICOLON => true, + EmailLexer::S_GREATERTHAN => true, + EmailLexer::S_LOWERTHAN => true, + ); + + if (isset($invalidDomainTokens[$this->lexer->token['type']])) { + throw new ExpectingATEXT(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_COMMA) { + throw new CommaInDomain(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_AT) { + throw new ConsecutiveAt(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_OPENQBRACKET && $prev['type'] !== EmailLexer::S_AT) { + throw new ExpectingATEXT(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_HYPHEN && $this->lexer->isNextToken(EmailLexer::S_DOT)) { + throw new DomainHyphened(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_BACKSLASH + && $this->lexer->isNextToken(EmailLexer::GENERIC)) { + throw new ExpectingATEXT(); + } + } + + /** + * @return bool + */ + protected function hasBrackets() + { + if ($this->lexer->token['type'] !== EmailLexer::S_OPENBRACKET) { + return false; + } + + try { + $this->lexer->find(EmailLexer::S_CLOSEBRACKET); + } catch (\RuntimeException $e) { + throw new ExpectingDomainLiteralClose(); + } + + return true; + } + + /** + * @param string $label + */ + protected function checkLabelLength($label) + { + if ($this->isLabelTooLong($label)) { + $this->warnings[LabelTooLong::CODE] = new LabelTooLong(); + } + } + + /** + * @param string $label + * @return bool + */ + private function isLabelTooLong($label) + { + if (preg_match('/[^\x00-\x7F]/', $label)) { + idn_to_ascii($label, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46, $idnaInfo); + + return (bool) ($idnaInfo['errors'] & IDNA_ERROR_LABEL_TOO_LONG); + } + + return strlen($label) > self::LABEL_MAX_LENGTH; + } + + protected function parseDomainComments() + { + $this->isUnclosedComment(); + while (!$this->lexer->isNextToken(EmailLexer::S_CLOSEPARENTHESIS)) { + $this->warnEscaping(); + $this->lexer->moveNext(); + } + + $this->lexer->moveNext(); + if ($this->lexer->isNextToken(EmailLexer::S_DOT)) { + throw new ExpectingATEXT(); + } + } + + protected function addTLDWarnings() + { + if ($this->warnings[DomainLiteral::CODE]) { + $this->warnings[TLD::CODE] = new TLD(); + } + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Parser/LocalPart.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Parser/LocalPart.php index b804b412863..3c21f34ac07 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Parser/LocalPart.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Parser/LocalPart.php @@ -14,132 +14,132 @@ use Egulias\EmailValidator\Warning\LocalTooLong; class LocalPart extends Parser { - public function parse($localPart) - { - $parseDQuote = true; - $closingQuote = false; - $openedParenthesis = 0; - $totalLength = 0; + public function parse($localPart) + { + $parseDQuote = true; + $closingQuote = false; + $openedParenthesis = 0; + $totalLength = 0; - while ($this->lexer->token['type'] !== EmailLexer::S_AT && null !== $this->lexer->token['type']) { - if ($this->lexer->token['type'] === EmailLexer::S_DOT && null === $this->lexer->getPrevious()['type']) { - throw new DotAtStart(); - } + while ($this->lexer->token['type'] !== EmailLexer::S_AT && null !== $this->lexer->token['type']) { + if ($this->lexer->token['type'] === EmailLexer::S_DOT && null === $this->lexer->getPrevious()['type']) { + throw new DotAtStart(); + } - $closingQuote = $this->checkDQUOTE($closingQuote); - if ($closingQuote && $parseDQuote) { - $parseDQuote = $this->parseDoubleQuote(); - } + $closingQuote = $this->checkDQUOTE($closingQuote); + if ($closingQuote && $parseDQuote) { + $parseDQuote = $this->parseDoubleQuote(); + } - if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) { - $this->parseComments(); - $openedParenthesis += $this->getOpenedParenthesis(); - } + if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) { + $this->parseComments(); + $openedParenthesis += $this->getOpenedParenthesis(); + } - if ($this->lexer->token['type'] === EmailLexer::S_CLOSEPARENTHESIS) { - if ($openedParenthesis === 0) { - throw new UnopenedComment(); - } + if ($this->lexer->token['type'] === EmailLexer::S_CLOSEPARENTHESIS) { + if ($openedParenthesis === 0) { + throw new UnopenedComment(); + } - $openedParenthesis--; - } + $openedParenthesis--; + } - $this->checkConsecutiveDots(); + $this->checkConsecutiveDots(); - if ($this->lexer->token['type'] === EmailLexer::S_DOT && - $this->lexer->isNextToken(EmailLexer::S_AT) - ) { - throw new DotAtEnd(); - } + if ($this->lexer->token['type'] === EmailLexer::S_DOT && + $this->lexer->isNextToken(EmailLexer::S_AT) + ) { + throw new DotAtEnd(); + } - $this->warnEscaping(); - $this->isInvalidToken($this->lexer->token, $closingQuote); + $this->warnEscaping(); + $this->isInvalidToken($this->lexer->token, $closingQuote); - if ($this->isFWS()) { - $this->parseFWS(); - } + if ($this->isFWS()) { + $this->parseFWS(); + } - $totalLength += strlen($this->lexer->token['value']); - $this->lexer->moveNext(); - } + $totalLength += strlen($this->lexer->token['value']); + $this->lexer->moveNext(); + } - if ($totalLength > LocalTooLong::LOCAL_PART_LENGTH) { - $this->warnings[LocalTooLong::CODE] = new LocalTooLong(); - } - } + if ($totalLength > LocalTooLong::LOCAL_PART_LENGTH) { + $this->warnings[LocalTooLong::CODE] = new LocalTooLong(); + } + } - /** - * @return bool - */ - protected function parseDoubleQuote() - { - $parseAgain = true; - $special = array( - EmailLexer::S_CR => true, - EmailLexer::S_HTAB => true, - EmailLexer::S_LF => true - ); + /** + * @return bool + */ + protected function parseDoubleQuote() + { + $parseAgain = true; + $special = array( + EmailLexer::S_CR => true, + EmailLexer::S_HTAB => true, + EmailLexer::S_LF => true + ); - $invalid = array( - EmailLexer::C_NUL => true, - EmailLexer::S_HTAB => true, - EmailLexer::S_CR => true, - EmailLexer::S_LF => true - ); - $setSpecialsWarning = true; + $invalid = array( + EmailLexer::C_NUL => true, + EmailLexer::S_HTAB => true, + EmailLexer::S_CR => true, + EmailLexer::S_LF => true + ); + $setSpecialsWarning = true; - $this->lexer->moveNext(); + $this->lexer->moveNext(); - while ($this->lexer->token['type'] !== EmailLexer::S_DQUOTE && null !== $this->lexer->token['type']) { - $parseAgain = false; - if (isset($special[$this->lexer->token['type']]) && $setSpecialsWarning) { - $this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS(); - $setSpecialsWarning = false; - } - if ($this->lexer->token['type'] === EmailLexer::S_BACKSLASH && $this->lexer->isNextToken(EmailLexer::S_DQUOTE)) { - $this->lexer->moveNext(); - } + while ($this->lexer->token['type'] !== EmailLexer::S_DQUOTE && null !== $this->lexer->token['type']) { + $parseAgain = false; + if (isset($special[$this->lexer->token['type']]) && $setSpecialsWarning) { + $this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS(); + $setSpecialsWarning = false; + } + if ($this->lexer->token['type'] === EmailLexer::S_BACKSLASH && $this->lexer->isNextToken(EmailLexer::S_DQUOTE)) { + $this->lexer->moveNext(); + } - $this->lexer->moveNext(); + $this->lexer->moveNext(); - if (!$this->escaped() && isset($invalid[$this->lexer->token['type']])) { - throw new ExpectingATEXT(); - } - } + if (!$this->escaped() && isset($invalid[$this->lexer->token['type']])) { + throw new ExpectingATEXT(); + } + } - $prev = $this->lexer->getPrevious(); + $prev = $this->lexer->getPrevious(); - if ($prev['type'] === EmailLexer::S_BACKSLASH) { - if (!$this->checkDQUOTE(false)) { - throw new UnclosedQuotedString(); - } - } + if ($prev['type'] === EmailLexer::S_BACKSLASH) { + if (!$this->checkDQUOTE(false)) { + throw new UnclosedQuotedString(); + } + } - if (!$this->lexer->isNextToken(EmailLexer::S_AT) && $prev['type'] !== EmailLexer::S_BACKSLASH) { - throw new ExpectingAT(); - } + if (!$this->lexer->isNextToken(EmailLexer::S_AT) && $prev['type'] !== EmailLexer::S_BACKSLASH) { + throw new ExpectingAT(); + } - return $parseAgain; - } + return $parseAgain; + } - /** - * @param bool $closingQuote - */ - protected function isInvalidToken(array $token, $closingQuote) - { - $forbidden = array( - EmailLexer::S_COMMA, - EmailLexer::S_CLOSEBRACKET, - EmailLexer::S_OPENBRACKET, - EmailLexer::S_GREATERTHAN, - EmailLexer::S_LOWERTHAN, - EmailLexer::S_COLON, - EmailLexer::S_SEMICOLON, - EmailLexer::INVALID - ); + /** + * @param bool $closingQuote + */ + protected function isInvalidToken(array $token, $closingQuote) + { + $forbidden = array( + EmailLexer::S_COMMA, + EmailLexer::S_CLOSEBRACKET, + EmailLexer::S_OPENBRACKET, + EmailLexer::S_GREATERTHAN, + EmailLexer::S_LOWERTHAN, + EmailLexer::S_COLON, + EmailLexer::S_SEMICOLON, + EmailLexer::INVALID + ); - if (in_array($token['type'], $forbidden) && !$closingQuote) { - throw new ExpectingATEXT(); - } - } + if (in_array($token['type'], $forbidden) && !$closingQuote) { + throw new ExpectingATEXT(); + } + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Parser/Parser.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Parser/Parser.php index 9ebb95ae0a0..ccdc93889a2 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Parser/Parser.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Parser/Parser.php @@ -21,228 +21,229 @@ use Egulias\EmailValidator\Warning\QuotedString; abstract class Parser { - /** - * @var array - */ - protected $warnings = []; + /** + * @var array + */ + protected $warnings = []; - /** - * @var EmailLexer - */ - protected $lexer; + /** + * @var EmailLexer + */ + protected $lexer; - /** - * @var int - */ - protected $openedParenthesis = 0; + /** + * @var int + */ + protected $openedParenthesis = 0; - public function __construct(EmailLexer $lexer) - { - $this->lexer = $lexer; - } + public function __construct(EmailLexer $lexer) + { + $this->lexer = $lexer; + } - /** - * @return \Egulias\EmailValidator\Warning\Warning[] - */ - public function getWarnings() - { - return $this->warnings; - } + /** + * @return \Egulias\EmailValidator\Warning\Warning[] + */ + public function getWarnings() + { + return $this->warnings; + } - /** - * @param string $str - */ - abstract public function parse($str); + /** + * @param string $str + */ + abstract public function parse($str); - /** @return int */ - public function getOpenedParenthesis() - { - return $this->openedParenthesis; - } + /** @return int */ + public function getOpenedParenthesis() + { + return $this->openedParenthesis; + } - /** - * validateQuotedPair - */ - protected function validateQuotedPair() - { - if (!($this->lexer->token['type'] === EmailLexer::INVALID - || $this->lexer->token['type'] === EmailLexer::C_DEL)) { - throw new ExpectingQPair(); - } + /** + * validateQuotedPair + */ + protected function validateQuotedPair() + { + if (!($this->lexer->token['type'] === EmailLexer::INVALID + || $this->lexer->token['type'] === EmailLexer::C_DEL)) { + throw new ExpectingQPair(); + } - $this->warnings[QuotedPart::CODE] = - new QuotedPart($this->lexer->getPrevious()['type'], $this->lexer->token['type']); - } + $this->warnings[QuotedPart::CODE] = + new QuotedPart($this->lexer->getPrevious()['type'], $this->lexer->token['type']); + } - protected function parseComments() - { - $this->openedParenthesis = 1; - $this->isUnclosedComment(); - $this->warnings[Comment::CODE] = new Comment(); - while (!$this->lexer->isNextToken(EmailLexer::S_CLOSEPARENTHESIS)) { - if ($this->lexer->isNextToken(EmailLexer::S_OPENPARENTHESIS)) { - $this->openedParenthesis++; - } - $this->warnEscaping(); - $this->lexer->moveNext(); - } + protected function parseComments() + { + $this->openedParenthesis = 1; + $this->isUnclosedComment(); + $this->warnings[Comment::CODE] = new Comment(); + while (!$this->lexer->isNextToken(EmailLexer::S_CLOSEPARENTHESIS)) { + if ($this->lexer->isNextToken(EmailLexer::S_OPENPARENTHESIS)) { + $this->openedParenthesis++; + } + $this->warnEscaping(); + $this->lexer->moveNext(); + } - $this->lexer->moveNext(); - if ($this->lexer->isNextTokenAny(array(EmailLexer::GENERIC, EmailLexer::S_EMPTY))) { - throw new ExpectingATEXT(); - } + $this->lexer->moveNext(); + if ($this->lexer->isNextTokenAny(array(EmailLexer::GENERIC, EmailLexer::S_EMPTY))) { + throw new ExpectingATEXT(); + } - if ($this->lexer->isNextToken(EmailLexer::S_AT)) { - $this->warnings[CFWSNearAt::CODE] = new CFWSNearAt(); - } - } + if ($this->lexer->isNextToken(EmailLexer::S_AT)) { + $this->warnings[CFWSNearAt::CODE] = new CFWSNearAt(); + } + } - /** - * @return bool - */ - protected function isUnclosedComment() - { - try { - $this->lexer->find(EmailLexer::S_CLOSEPARENTHESIS); - return true; - } catch (\RuntimeException $e) { - throw new UnclosedComment(); - } - } + /** + * @return bool + */ + protected function isUnclosedComment() + { + try { + $this->lexer->find(EmailLexer::S_CLOSEPARENTHESIS); + return true; + } catch (\RuntimeException $e) { + throw new UnclosedComment(); + } + } - protected function parseFWS() - { - $previous = $this->lexer->getPrevious(); + protected function parseFWS() + { + $previous = $this->lexer->getPrevious(); - $this->checkCRLFInFWS(); + $this->checkCRLFInFWS(); - if ($this->lexer->token['type'] === EmailLexer::S_CR) { - throw new CRNoLF(); - } + if ($this->lexer->token['type'] === EmailLexer::S_CR) { + throw new CRNoLF(); + } - if ($this->lexer->isNextToken(EmailLexer::GENERIC) && $previous['type'] !== EmailLexer::S_AT) { - throw new AtextAfterCFWS(); - } + if ($this->lexer->isNextToken(EmailLexer::GENERIC) && $previous['type'] !== EmailLexer::S_AT) { + throw new AtextAfterCFWS(); + } - if ($this->lexer->token['type'] === EmailLexer::S_LF || $this->lexer->token['type'] === EmailLexer::C_NUL) { - throw new ExpectingCTEXT(); - } + if ($this->lexer->token['type'] === EmailLexer::S_LF || $this->lexer->token['type'] === EmailLexer::C_NUL) { + throw new ExpectingCTEXT(); + } - if ($this->lexer->isNextToken(EmailLexer::S_AT) || $previous['type'] === EmailLexer::S_AT) { - $this->warnings[CFWSNearAt::CODE] = new CFWSNearAt(); - } else { - $this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS(); - } - } + if ($this->lexer->isNextToken(EmailLexer::S_AT) || $previous['type'] === EmailLexer::S_AT) { + $this->warnings[CFWSNearAt::CODE] = new CFWSNearAt(); + } else { + $this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS(); + } + } - protected function checkConsecutiveDots() - { - if ($this->lexer->token['type'] === EmailLexer::S_DOT && $this->lexer->isNextToken(EmailLexer::S_DOT)) { - throw new ConsecutiveDot(); - } - } + protected function checkConsecutiveDots() + { + if ($this->lexer->token['type'] === EmailLexer::S_DOT && $this->lexer->isNextToken(EmailLexer::S_DOT)) { + throw new ConsecutiveDot(); + } + } - /** - * @return bool - */ - protected function isFWS() - { - if ($this->escaped()) { - return false; - } + /** + * @return bool + */ + protected function isFWS() + { + if ($this->escaped()) { + return false; + } - if ($this->lexer->token['type'] === EmailLexer::S_SP || - $this->lexer->token['type'] === EmailLexer::S_HTAB || - $this->lexer->token['type'] === EmailLexer::S_CR || - $this->lexer->token['type'] === EmailLexer::S_LF || - $this->lexer->token['type'] === EmailLexer::CRLF - ) { - return true; - } + if ($this->lexer->token['type'] === EmailLexer::S_SP || + $this->lexer->token['type'] === EmailLexer::S_HTAB || + $this->lexer->token['type'] === EmailLexer::S_CR || + $this->lexer->token['type'] === EmailLexer::S_LF || + $this->lexer->token['type'] === EmailLexer::CRLF + ) { + return true; + } - return false; - } + return false; + } - /** - * @return bool - */ - protected function escaped() - { - $previous = $this->lexer->getPrevious(); + /** + * @return bool + */ + protected function escaped() + { + $previous = $this->lexer->getPrevious(); - if ($previous && $previous['type'] === EmailLexer::S_BACKSLASH - && - $this->lexer->token['type'] !== EmailLexer::GENERIC - ) { - return true; - } + if ($previous && $previous['type'] === EmailLexer::S_BACKSLASH + && + $this->lexer->token['type'] !== EmailLexer::GENERIC + ) { + return true; + } - return false; - } + return false; + } - /** - * @return bool - */ - protected function warnEscaping() - { - if ($this->lexer->token['type'] !== EmailLexer::S_BACKSLASH) { - return false; - } + /** + * @return bool + */ + protected function warnEscaping() + { + if ($this->lexer->token['type'] !== EmailLexer::S_BACKSLASH) { + return false; + } - if ($this->lexer->isNextToken(EmailLexer::GENERIC)) { - throw new ExpectingATEXT(); - } + if ($this->lexer->isNextToken(EmailLexer::GENERIC)) { + throw new ExpectingATEXT(); + } - if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB, EmailLexer::C_DEL))) { - return false; - } + if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB, EmailLexer::C_DEL))) { + return false; + } - $this->warnings[QuotedPart::CODE] = - new QuotedPart($this->lexer->getPrevious()['type'], $this->lexer->token['type']); - return true; - } + $this->warnings[QuotedPart::CODE] = + new QuotedPart($this->lexer->getPrevious()['type'], $this->lexer->token['type']); + return true; - /** - * @param bool $hasClosingQuote - * - * @return bool - */ - protected function checkDQUOTE($hasClosingQuote) - { - if ($this->lexer->token['type'] !== EmailLexer::S_DQUOTE) { - return $hasClosingQuote; - } - if ($hasClosingQuote) { - return $hasClosingQuote; - } - $previous = $this->lexer->getPrevious(); - if ($this->lexer->isNextToken(EmailLexer::GENERIC) && $previous['type'] === EmailLexer::GENERIC) { - throw new ExpectingATEXT(); - } + } - try { - $this->lexer->find(EmailLexer::S_DQUOTE); - $hasClosingQuote = true; - } catch (\Exception $e) { - throw new UnclosedQuotedString(); - } - $this->warnings[QuotedString::CODE] = new QuotedString($previous['value'], $this->lexer->token['value']); + /** + * @param bool $hasClosingQuote + * + * @return bool + */ + protected function checkDQUOTE($hasClosingQuote) + { + if ($this->lexer->token['type'] !== EmailLexer::S_DQUOTE) { + return $hasClosingQuote; + } + if ($hasClosingQuote) { + return $hasClosingQuote; + } + $previous = $this->lexer->getPrevious(); + if ($this->lexer->isNextToken(EmailLexer::GENERIC) && $previous['type'] === EmailLexer::GENERIC) { + throw new ExpectingATEXT(); + } - return $hasClosingQuote; - } + try { + $this->lexer->find(EmailLexer::S_DQUOTE); + $hasClosingQuote = true; + } catch (\Exception $e) { + throw new UnclosedQuotedString(); + } + $this->warnings[QuotedString::CODE] = new QuotedString($previous['value'], $this->lexer->token['value']); - protected function checkCRLFInFWS() - { - if ($this->lexer->token['type'] !== EmailLexer::CRLF) { - return; - } + return $hasClosingQuote; + } - if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB))) { - throw new CRLFX2(); - } + protected function checkCRLFInFWS() + { + if ($this->lexer->token['type'] !== EmailLexer::CRLF) { + return; + } - if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB))) { - throw new CRLFAtTheEnd(); - } - } + if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB))) { + throw new CRLFX2(); + } + + if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB))) { + throw new CRLFAtTheEnd(); + } + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/DNSCheckValidation.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/DNSCheckValidation.php index 0d02f11a0a6..491082a590f 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/DNSCheckValidation.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/DNSCheckValidation.php @@ -11,156 +11,156 @@ use Egulias\EmailValidator\Exception\NoDNSRecord; class DNSCheckValidation implements EmailValidation { - /** - * @var array - */ - private $warnings = []; + /** + * @var array + */ + private $warnings = []; - /** - * @var InvalidEmail|null - */ - private $error; + /** + * @var InvalidEmail|null + */ + private $error; - /** - * @var array - */ - private $mxRecords = []; + /** + * @var array + */ + private $mxRecords = []; - public function __construct() - { - if (!function_exists('idn_to_ascii')) { - throw new \LogicException(sprintf('The %s class requires the Intl extension.', __CLASS__)); - } - } + public function __construct() + { + if (!function_exists('idn_to_ascii')) { + throw new \LogicException(sprintf('The %s class requires the Intl extension.', __CLASS__)); + } + } - public function isValid($email, EmailLexer $emailLexer) - { - // use the input to check DNS if we cannot extract something similar to a domain - $host = $email; + public function isValid($email, EmailLexer $emailLexer) + { + // use the input to check DNS if we cannot extract something similar to a domain + $host = $email; - // Arguable pattern to extract the domain. Not aiming to validate the domain nor the email - if (false !== $lastAtPos = strrpos($email, '@')) { - $host = substr($email, $lastAtPos + 1); - } + // Arguable pattern to extract the domain. Not aiming to validate the domain nor the email + if (false !== $lastAtPos = strrpos($email, '@')) { + $host = substr($email, $lastAtPos + 1); + } - // Get the domain parts - $hostParts = explode('.', $host); + // Get the domain parts + $hostParts = explode('.', $host); - // Reserved Top Level DNS Names (https://tools.ietf.org/html/rfc2606#section-2), - // mDNS and private DNS Namespaces (https://tools.ietf.org/html/rfc6762#appendix-G) - $reservedTopLevelDnsNames = [ - // Reserved Top Level DNS Names - 'test', - 'example', - 'invalid', - 'localhost', + // Reserved Top Level DNS Names (https://tools.ietf.org/html/rfc2606#section-2), + // mDNS and private DNS Namespaces (https://tools.ietf.org/html/rfc6762#appendix-G) + $reservedTopLevelDnsNames = [ + // Reserved Top Level DNS Names + 'test', + 'example', + 'invalid', + 'localhost', - // mDNS - 'local', + // mDNS + 'local', - // Private DNS Namespaces - 'intranet', - 'internal', - 'private', - 'corp', - 'home', - 'lan', - ]; + // Private DNS Namespaces + 'intranet', + 'internal', + 'private', + 'corp', + 'home', + 'lan', + ]; - $isLocalDomain = count($hostParts) <= 1; - $isReservedTopLevel = in_array($hostParts[(count($hostParts) - 1)], $reservedTopLevelDnsNames, true); + $isLocalDomain = count($hostParts) <= 1; + $isReservedTopLevel = in_array($hostParts[(count($hostParts) - 1)], $reservedTopLevelDnsNames, true); - // Exclude reserved top level DNS names - if ($isLocalDomain || $isReservedTopLevel) { - $this->error = new LocalOrReservedDomain(); - return false; - } + // Exclude reserved top level DNS names + if ($isLocalDomain || $isReservedTopLevel) { + $this->error = new LocalOrReservedDomain(); + return false; + } - return $this->checkDns($host); - } + return $this->checkDns($host); + } - public function getError() - { - return $this->error; - } + public function getError() + { + return $this->error; + } - public function getWarnings() - { - return $this->warnings; - } + public function getWarnings() + { + return $this->warnings; + } - /** - * @param string $host - * - * @return bool - */ - protected function checkDns($host) - { - $variant = INTL_IDNA_VARIANT_UTS46; + /** + * @param string $host + * + * @return bool + */ + protected function checkDns($host) + { + $variant = INTL_IDNA_VARIANT_UTS46; - $host = rtrim(idn_to_ascii($host, IDNA_DEFAULT, $variant), '.') . '.'; + $host = rtrim(idn_to_ascii($host, IDNA_DEFAULT, $variant), '.') . '.'; - return $this->validateDnsRecords($host); - } + return $this->validateDnsRecords($host); + } - /** - * Validate the DNS records for given host. - * - * @param string $host A set of DNS records in the format returned by dns_get_record. - * - * @return bool True on success. - */ - private function validateDnsRecords($host) - { - // Get all MX, A and AAAA DNS records for host - // Using @ as workaround to fix https://bugs.php.net/bug.php?id=73149 - $dnsRecords = @dns_get_record($host, DNS_MX + DNS_A + DNS_AAAA); + /** + * Validate the DNS records for given host. + * + * @param string $host A set of DNS records in the format returned by dns_get_record. + * + * @return bool True on success. + */ + private function validateDnsRecords($host) + { + // Get all MX, A and AAAA DNS records for host + // Using @ as workaround to fix https://bugs.php.net/bug.php?id=73149 + $dnsRecords = @dns_get_record($host, DNS_MX + DNS_A + DNS_AAAA); - // No MX, A or AAAA DNS records - if (empty($dnsRecords)) { - $this->error = new NoDNSRecord(); - return false; - } + // No MX, A or AAAA DNS records + if (empty($dnsRecords)) { + $this->error = new NoDNSRecord(); + return false; + } - // For each DNS record - foreach ($dnsRecords as $dnsRecord) { - if (!$this->validateMXRecord($dnsRecord)) { - return false; - } - } + // For each DNS record + foreach ($dnsRecords as $dnsRecord) { + if (!$this->validateMXRecord($dnsRecord)) { + return false; + } + } - // No MX records (fallback to A or AAAA records) - if (empty($this->mxRecords)) { - $this->warnings[NoDNSMXRecord::CODE] = new NoDNSMXRecord(); - } + // No MX records (fallback to A or AAAA records) + if (empty($this->mxRecords)) { + $this->warnings[NoDNSMXRecord::CODE] = new NoDNSMXRecord(); + } - return true; - } + return true; + } - /** - * Validate an MX record - * - * @param array $dnsRecord Given DNS record. - * - * @return bool True if valid. - */ - private function validateMxRecord($dnsRecord) - { - if ($dnsRecord['type'] !== 'MX') { - return true; - } + /** + * Validate an MX record + * + * @param array $dnsRecord Given DNS record. + * + * @return bool True if valid. + */ + private function validateMxRecord($dnsRecord) + { + if ($dnsRecord['type'] !== 'MX') { + return true; + } - // "Null MX" record indicates the domain accepts no mail (https://tools.ietf.org/html/rfc7505) - if (empty($dnsRecord['target']) || $dnsRecord['target'] === '.') { - $this->error = new DomainAcceptsNoMail(); - return false; - } + // "Null MX" record indicates the domain accepts no mail (https://tools.ietf.org/html/rfc7505) + if (empty($dnsRecord['target']) || $dnsRecord['target'] === '.') { + $this->error = new DomainAcceptsNoMail(); + return false; + } - $this->mxRecords[] = $dnsRecord; + $this->mxRecords[] = $dnsRecord; - return true; - } + return true; + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/Exception/EmptyValidationList.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/Exception/EmptyValidationList.php index 98d0d12a6d1..ee7c41aa033 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/Exception/EmptyValidationList.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/Exception/EmptyValidationList.php @@ -6,11 +6,11 @@ use Exception; class EmptyValidationList extends \InvalidArgumentException { - /** - * @param int $code - */ - public function __construct($code = 0, Exception $previous = null) - { - parent::__construct("Empty validation list is not allowed", $code, $previous); - } + /** + * @param int $code + */ + public function __construct($code = 0, Exception $previous = null) + { + parent::__construct("Empty validation list is not allowed", $code, $previous); + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/MultipleErrors.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/MultipleErrors.php index cd10ec7aaf8..3be59732664 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/MultipleErrors.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/MultipleErrors.php @@ -6,27 +6,27 @@ use Egulias\EmailValidator\Exception\InvalidEmail; class MultipleErrors extends InvalidEmail { - const CODE = 999; - const REASON = "Accumulated errors for multiple validations"; - /** - * @var InvalidEmail[] - */ - private $errors = []; + const CODE = 999; + const REASON = "Accumulated errors for multiple validations"; + /** + * @var InvalidEmail[] + */ + private $errors = []; - /** - * @param InvalidEmail[] $errors - */ - public function __construct(array $errors) - { - $this->errors = $errors; - parent::__construct(); - } + /** + * @param InvalidEmail[] $errors + */ + public function __construct(array $errors) + { + $this->errors = $errors; + parent::__construct(); + } - /** - * @return InvalidEmail[] - */ - public function getErrors() - { - return $this->errors; - } + /** + * @return InvalidEmail[] + */ + public function getErrors() + { + return $this->errors; + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/MultipleValidationWithAnd.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/MultipleValidationWithAnd.php index 55aad31459b..feb224023da 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/MultipleValidationWithAnd.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/MultipleValidationWithAnd.php @@ -7,118 +7,118 @@ use Egulias\EmailValidator\Validation\Exception\EmptyValidationList; class MultipleValidationWithAnd implements EmailValidation { - /** - * If one of validations gets failure skips all succeeding validation. - * This means MultipleErrors will only contain a single error which first found. - */ - const STOP_ON_ERROR = 0; + /** + * If one of validations gets failure skips all succeeding validation. + * This means MultipleErrors will only contain a single error which first found. + */ + const STOP_ON_ERROR = 0; - /** - * All of validations will be invoked even if one of them got failure. - * So MultipleErrors will contain all causes. - */ - const ALLOW_ALL_ERRORS = 1; + /** + * All of validations will be invoked even if one of them got failure. + * So MultipleErrors will contain all causes. + */ + const ALLOW_ALL_ERRORS = 1; - /** - * @var EmailValidation[] - */ - private $validations = []; + /** + * @var EmailValidation[] + */ + private $validations = []; - /** - * @var array - */ - private $warnings = []; + /** + * @var array + */ + private $warnings = []; - /** - * @var MultipleErrors|null - */ - private $error; + /** + * @var MultipleErrors|null + */ + private $error; - /** - * @var int - */ - private $mode; + /** + * @var int + */ + private $mode; - /** - * @param EmailValidation[] $validations The validations. - * @param int $mode The validation mode (one of the constants). - */ - public function __construct(array $validations, $mode = self::ALLOW_ALL_ERRORS) - { - if (count($validations) == 0) { - throw new EmptyValidationList(); - } + /** + * @param EmailValidation[] $validations The validations. + * @param int $mode The validation mode (one of the constants). + */ + public function __construct(array $validations, $mode = self::ALLOW_ALL_ERRORS) + { + if (count($validations) == 0) { + throw new EmptyValidationList(); + } - $this->validations = $validations; - $this->mode = $mode; - } + $this->validations = $validations; + $this->mode = $mode; + } - /** - * {@inheritdoc} - */ - public function isValid($email, EmailLexer $emailLexer) - { - $result = true; - $errors = []; - foreach ($this->validations as $validation) { - $emailLexer->reset(); - $validationResult = $validation->isValid($email, $emailLexer); - $result = $result && $validationResult; - $this->warnings = array_merge($this->warnings, $validation->getWarnings()); - $errors = $this->addNewError($validation->getError(), $errors); + /** + * {@inheritdoc} + */ + public function isValid($email, EmailLexer $emailLexer) + { + $result = true; + $errors = []; + foreach ($this->validations as $validation) { + $emailLexer->reset(); + $validationResult = $validation->isValid($email, $emailLexer); + $result = $result && $validationResult; + $this->warnings = array_merge($this->warnings, $validation->getWarnings()); + $errors = $this->addNewError($validation->getError(), $errors); - if ($this->shouldStop($result)) { - break; - } - } + if ($this->shouldStop($result)) { + break; + } + } - if (!empty($errors)) { - $this->error = new MultipleErrors($errors); - } + if (!empty($errors)) { + $this->error = new MultipleErrors($errors); + } - return $result; - } + return $result; + } - /** - * @param \Egulias\EmailValidator\Exception\InvalidEmail|null $possibleError - * @param \Egulias\EmailValidator\Exception\InvalidEmail[] $errors - * - * @return \Egulias\EmailValidator\Exception\InvalidEmail[] - */ - private function addNewError($possibleError, array $errors) - { - if (null !== $possibleError) { - $errors[] = $possibleError; - } + /** + * @param \Egulias\EmailValidator\Exception\InvalidEmail|null $possibleError + * @param \Egulias\EmailValidator\Exception\InvalidEmail[] $errors + * + * @return \Egulias\EmailValidator\Exception\InvalidEmail[] + */ + private function addNewError($possibleError, array $errors) + { + if (null !== $possibleError) { + $errors[] = $possibleError; + } - return $errors; - } + return $errors; + } - /** - * @param bool $result - * - * @return bool - */ - private function shouldStop($result) - { - return !$result && $this->mode === self::STOP_ON_ERROR; - } + /** + * @param bool $result + * + * @return bool + */ + private function shouldStop($result) + { + return !$result && $this->mode === self::STOP_ON_ERROR; + } - /** - * Returns the validation errors. - * - * @return MultipleErrors|null - */ - public function getError() - { - return $this->error; - } + /** + * Returns the validation errors. + * + * @return MultipleErrors|null + */ + public function getError() + { + return $this->error; + } - /** - * {@inheritdoc} - */ - public function getWarnings() - { - return $this->warnings; - } + /** + * {@inheritdoc} + */ + public function getWarnings() + { + return $this->warnings; + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/NoRFCWarningsValidation.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/NoRFCWarningsValidation.php index b7b3bb90910..6b31e5440ec 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/NoRFCWarningsValidation.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/NoRFCWarningsValidation.php @@ -8,34 +8,34 @@ use Egulias\EmailValidator\Validation\Error\RFCWarnings; class NoRFCWarningsValidation extends RFCValidation { - /** - * @var InvalidEmail|null - */ - private $error; + /** + * @var InvalidEmail|null + */ + private $error; - /** - * {@inheritdoc} - */ - public function isValid($email, EmailLexer $emailLexer) - { - if (!parent::isValid($email, $emailLexer)) { - return false; - } + /** + * {@inheritdoc} + */ + public function isValid($email, EmailLexer $emailLexer) + { + if (!parent::isValid($email, $emailLexer)) { + return false; + } - if (empty($this->getWarnings())) { - return true; - } + if (empty($this->getWarnings())) { + return true; + } - $this->error = new RFCWarnings(); + $this->error = new RFCWarnings(); - return false; - } + return false; + } - /** - * {@inheritdoc} - */ - public function getError() - { - return $this->error ?: parent::getError(); - } + /** + * {@inheritdoc} + */ + public function getError() + { + return $this->error ?: parent::getError(); + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/RFCValidation.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/RFCValidation.php index 813da231844..8781e0b62d1 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/RFCValidation.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/RFCValidation.php @@ -8,42 +8,42 @@ use Egulias\EmailValidator\Exception\InvalidEmail; class RFCValidation implements EmailValidation { - /** - * @var EmailParser|null - */ - private $parser; + /** + * @var EmailParser|null + */ + private $parser; - /** - * @var array - */ - private $warnings = []; + /** + * @var array + */ + private $warnings = []; - /** - * @var InvalidEmail|null - */ - private $error; + /** + * @var InvalidEmail|null + */ + private $error; - public function isValid($email, EmailLexer $emailLexer) - { - $this->parser = new EmailParser($emailLexer); - try { - $this->parser->parse((string) $email); - } catch (InvalidEmail $invalid) { - $this->error = $invalid; - return false; - } + public function isValid($email, EmailLexer $emailLexer) + { + $this->parser = new EmailParser($emailLexer); + try { + $this->parser->parse((string)$email); + } catch (InvalidEmail $invalid) { + $this->error = $invalid; + return false; + } - $this->warnings = $this->parser->getWarnings(); - return true; - } + $this->warnings = $this->parser->getWarnings(); + return true; + } - public function getError() - { - return $this->error; - } + public function getError() + { + return $this->error; + } - public function getWarnings() - { - return $this->warnings; - } + public function getWarnings() + { + return $this->warnings; + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/SpoofCheckValidation.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/SpoofCheckValidation.php index 65c017a3ce2..e10bfabd92f 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/SpoofCheckValidation.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Validation/SpoofCheckValidation.php @@ -9,43 +9,43 @@ use \Spoofchecker; class SpoofCheckValidation implements EmailValidation { - /** - * @var InvalidEmail|null - */ - private $error; + /** + * @var InvalidEmail|null + */ + private $error; - public function __construct() - { - if (!extension_loaded('intl')) { - throw new \LogicException(sprintf('The %s class requires the Intl extension.', __CLASS__)); - } - } + public function __construct() + { + if (!extension_loaded('intl')) { + throw new \LogicException(sprintf('The %s class requires the Intl extension.', __CLASS__)); + } + } - /** - * @psalm-suppress InvalidArgument - */ - public function isValid($email, EmailLexer $emailLexer) - { - $checker = new Spoofchecker(); - $checker->setChecks(Spoofchecker::SINGLE_SCRIPT); + /** + * @psalm-suppress InvalidArgument + */ + public function isValid($email, EmailLexer $emailLexer) + { + $checker = new Spoofchecker(); + $checker->setChecks(Spoofchecker::SINGLE_SCRIPT); - if ($checker->isSuspicious($email)) { - $this->error = new SpoofEmail(); - } + if ($checker->isSuspicious($email)) { + $this->error = new SpoofEmail(); + } - return $this->error === null; - } + return $this->error === null; + } - /** - * @return InvalidEmail|null - */ - public function getError() - { - return $this->error; - } + /** + * @return InvalidEmail|null + */ + public function getError() + { + return $this->error; + } - public function getWarnings() - { - return []; - } + public function getWarnings() + { + return []; + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Warning/QuotedPart.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Warning/QuotedPart.php index dd2cf28d0d8..36a4265a515 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Warning/QuotedPart.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Warning/QuotedPart.php @@ -4,14 +4,14 @@ namespace Egulias\EmailValidator\Warning; class QuotedPart extends Warning { - const CODE = 36; + const CODE = 36; - /** - * @param scalar $prevToken - * @param scalar $postToken - */ - public function __construct($prevToken, $postToken) - { - $this->message = "Deprecated Quoted String found between $prevToken and $postToken"; - } + /** + * @param scalar $prevToken + * @param scalar $postToken + */ + public function __construct($prevToken, $postToken) + { + $this->message = "Deprecated Quoted String found between $prevToken and $postToken"; + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Warning/QuotedString.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Warning/QuotedString.php index d1f99b905c6..817e4e84b07 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Warning/QuotedString.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Warning/QuotedString.php @@ -4,14 +4,14 @@ namespace Egulias\EmailValidator\Warning; class QuotedString extends Warning { - const CODE = 11; + const CODE = 11; - /** - * @param scalar $prevToken - * @param scalar $postToken - */ - public function __construct($prevToken, $postToken) - { - $this->message = "Quoted String found between $prevToken and $postToken"; - } + /** + * @param scalar $prevToken + * @param scalar $postToken + */ + public function __construct($prevToken, $postToken) + { + $this->message = "Quoted String found between $prevToken and $postToken"; + } } diff --git a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Warning/Warning.php b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Warning/Warning.php index 0ecd5ab9244..a2ee7b0de1e 100644 --- a/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Warning/Warning.php +++ b/htdocs/includes/swiftmailer/egulias/email-validator/EmailValidator/Warning/Warning.php @@ -4,44 +4,44 @@ namespace Egulias\EmailValidator\Warning; abstract class Warning { - const CODE = 0; + const CODE = 0; - /** - * @var string - */ - protected $message = ''; + /** + * @var string + */ + protected $message = ''; - /** - * @var int - */ - protected $rfcNumber = 0; + /** + * @var int + */ + protected $rfcNumber = 0; - /** - * @return string - */ - public function message() - { - return $this->message; - } + /** + * @return string + */ + public function message() + { + return $this->message; + } - /** - * @return int - */ - public function code() - { - return static::CODE; - } + /** + * @return int + */ + public function code() + { + return static::CODE; + } - /** - * @return int - */ - public function RFCNumber() - { - return $this->rfcNumber; - } + /** + * @return int + */ + public function RFCNumber() + { + return $this->rfcNumber; + } - public function __toString() - { - return $this->message() . " rfc: " . $this->rfcNumber . "interal code: " . static::CODE; - } + public function __toString() + { + return $this->message() . " rfc: " . $this->rfcNumber . "interal code: " . static::CODE; + } } diff --git a/htdocs/includes/swiftmailer/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php b/htdocs/includes/swiftmailer/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php index a561a6678f9..dd3ea768e3b 100644 --- a/htdocs/includes/swiftmailer/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php +++ b/htdocs/includes/swiftmailer/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php @@ -29,304 +29,304 @@ namespace Doctrine\Common\Lexer; */ abstract class AbstractLexer { - /** - * Lexer original input string. - * - * @var string - */ - private $input; + /** + * Lexer original input string. + * + * @var string + */ + private $input; - /** - * Array of scanned tokens. - * - * Each token is an associative array containing three items: - * - 'value' : the string value of the token in the input string - * - 'type' : the type of the token (identifier, numeric, string, input - * parameter, none) - * - 'position' : the position of the token in the input string - * - * @var array - */ - private $tokens = array(); + /** + * Array of scanned tokens. + * + * Each token is an associative array containing three items: + * - 'value' : the string value of the token in the input string + * - 'type' : the type of the token (identifier, numeric, string, input + * parameter, none) + * - 'position' : the position of the token in the input string + * + * @var array + */ + private $tokens = array(); - /** - * Current lexer position in input string. - * - * @var integer - */ - private $position = 0; + /** + * Current lexer position in input string. + * + * @var integer + */ + private $position = 0; - /** - * Current peek of current lexer position. - * - * @var integer - */ - private $peek = 0; + /** + * Current peek of current lexer position. + * + * @var integer + */ + private $peek = 0; - /** - * The next token in the input. - * - * @var array - */ - public $lookahead; + /** + * The next token in the input. + * + * @var array + */ + public $lookahead; - /** - * The last matched/seen token. - * - * @var array - */ - public $token; + /** + * The last matched/seen token. + * + * @var array + */ + public $token; - /** - * Sets the input data to be tokenized. - * - * The Lexer is immediately reset and the new input tokenized. - * Any unprocessed tokens from any previous input are lost. - * - * @param string $input The input to be tokenized. - * - * @return void - */ - public function setInput($input) - { - $this->input = $input; - $this->tokens = array(); + /** + * Sets the input data to be tokenized. + * + * The Lexer is immediately reset and the new input tokenized. + * Any unprocessed tokens from any previous input are lost. + * + * @param string $input The input to be tokenized. + * + * @return void + */ + public function setInput($input) + { + $this->input = $input; + $this->tokens = array(); - $this->reset(); - $this->scan($input); - } + $this->reset(); + $this->scan($input); + } - /** - * Resets the lexer. - * - * @return void - */ - public function reset() - { - $this->lookahead = null; - $this->token = null; - $this->peek = 0; - $this->position = 0; - } + /** + * Resets the lexer. + * + * @return void + */ + public function reset() + { + $this->lookahead = null; + $this->token = null; + $this->peek = 0; + $this->position = 0; + } - /** - * Resets the peek pointer to 0. - * - * @return void - */ - public function resetPeek() - { - $this->peek = 0; - } + /** + * Resets the peek pointer to 0. + * + * @return void + */ + public function resetPeek() + { + $this->peek = 0; + } - /** - * Resets the lexer position on the input to the given position. - * - * @param integer $position Position to place the lexical scanner. - * - * @return void - */ - public function resetPosition($position = 0) - { - $this->position = $position; - } + /** + * Resets the lexer position on the input to the given position. + * + * @param integer $position Position to place the lexical scanner. + * + * @return void + */ + public function resetPosition($position = 0) + { + $this->position = $position; + } - /** - * Retrieve the original lexer's input until a given position. - * - * @param integer $position - * - * @return string - */ - public function getInputUntilPosition($position) - { - return substr($this->input, 0, $position); - } + /** + * Retrieve the original lexer's input until a given position. + * + * @param integer $position + * + * @return string + */ + public function getInputUntilPosition($position) + { + return substr($this->input, 0, $position); + } - /** - * Checks whether a given token matches the current lookahead. - * - * @param integer|string $token - * - * @return boolean - */ - public function isNextToken($token) - { - return null !== $this->lookahead && $this->lookahead['type'] === $token; - } + /** + * Checks whether a given token matches the current lookahead. + * + * @param integer|string $token + * + * @return boolean + */ + public function isNextToken($token) + { + return null !== $this->lookahead && $this->lookahead['type'] === $token; + } - /** - * Checks whether any of the given tokens matches the current lookahead. - * - * @param array $tokens - * - * @return boolean - */ - public function isNextTokenAny(array $tokens) - { - return null !== $this->lookahead && in_array($this->lookahead['type'], $tokens, true); - } + /** + * Checks whether any of the given tokens matches the current lookahead. + * + * @param array $tokens + * + * @return boolean + */ + public function isNextTokenAny(array $tokens) + { + return null !== $this->lookahead && in_array($this->lookahead['type'], $tokens, true); + } - /** - * Moves to the next token in the input string. - * - * @return boolean - */ - public function moveNext() - { - $this->peek = 0; - $this->token = $this->lookahead; - $this->lookahead = (isset($this->tokens[$this->position])) - ? $this->tokens[$this->position++] : null; + /** + * Moves to the next token in the input string. + * + * @return boolean + */ + public function moveNext() + { + $this->peek = 0; + $this->token = $this->lookahead; + $this->lookahead = (isset($this->tokens[$this->position])) + ? $this->tokens[$this->position++] : null; - return $this->lookahead !== null; - } + return $this->lookahead !== null; + } - /** - * Tells the lexer to skip input tokens until it sees a token with the given value. - * - * @param string $type The token type to skip until. - * - * @return void - */ - public function skipUntil($type) - { - while ($this->lookahead !== null && $this->lookahead['type'] !== $type) { - $this->moveNext(); - } - } + /** + * Tells the lexer to skip input tokens until it sees a token with the given value. + * + * @param string $type The token type to skip until. + * + * @return void + */ + public function skipUntil($type) + { + while ($this->lookahead !== null && $this->lookahead['type'] !== $type) { + $this->moveNext(); + } + } - /** - * Checks if given value is identical to the given token. - * - * @param mixed $value - * @param integer $token - * - * @return boolean - */ - public function isA($value, $token) - { - return $this->getType($value) === $token; - } + /** + * Checks if given value is identical to the given token. + * + * @param mixed $value + * @param integer $token + * + * @return boolean + */ + public function isA($value, $token) + { + return $this->getType($value) === $token; + } - /** - * Moves the lookahead token forward. - * - * @return array|null The next token or NULL if there are no more tokens ahead. - */ - public function peek() - { - if (isset($this->tokens[$this->position + $this->peek])) { - return $this->tokens[$this->position + $this->peek++]; - } else { - return null; - } - } + /** + * Moves the lookahead token forward. + * + * @return array|null The next token or NULL if there are no more tokens ahead. + */ + public function peek() + { + if (isset($this->tokens[$this->position + $this->peek])) { + return $this->tokens[$this->position + $this->peek++]; + } else { + return null; + } + } - /** - * Peeks at the next token, returns it and immediately resets the peek. - * - * @return array|null The next token or NULL if there are no more tokens ahead. - */ - public function glimpse() - { - $peek = $this->peek(); - $this->peek = 0; - return $peek; - } + /** + * Peeks at the next token, returns it and immediately resets the peek. + * + * @return array|null The next token or NULL if there are no more tokens ahead. + */ + public function glimpse() + { + $peek = $this->peek(); + $this->peek = 0; + return $peek; + } - /** - * Scans the input string for tokens. - * - * @param string $input A query string. - * - * @return void - */ - protected function scan($input) - { - static $regex; + /** + * Scans the input string for tokens. + * + * @param string $input A query string. + * + * @return void + */ + protected function scan($input) + { + static $regex; - if ( ! isset($regex)) { - $regex = sprintf( - '/(%s)|%s/%s', - implode(')|(', $this->getCatchablePatterns()), - implode('|', $this->getNonCatchablePatterns()), - $this->getModifiers() - ); - } + if ( ! isset($regex)) { + $regex = sprintf( + '/(%s)|%s/%s', + implode(')|(', $this->getCatchablePatterns()), + implode('|', $this->getNonCatchablePatterns()), + $this->getModifiers() + ); + } - $flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE; - $matches = preg_split($regex, $input, -1, $flags); + $flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE; + $matches = preg_split($regex, $input, -1, $flags); - if (false === $matches) { - // Work around https://bugs.php.net/78122 - $matches = array(array($input, 0)); - } + if (false === $matches) { + // Work around https://bugs.php.net/78122 + $matches = array(array($input, 0)); + } - foreach ($matches as $match) { - // Must remain before 'value' assignment since it can change content - $type = $this->getType($match[0]); + foreach ($matches as $match) { + // Must remain before 'value' assignment since it can change content + $type = $this->getType($match[0]); - $this->tokens[] = array( - 'value' => $match[0], - 'type' => $type, - 'position' => $match[1], - ); - } - } + $this->tokens[] = array( + 'value' => $match[0], + 'type' => $type, + 'position' => $match[1], + ); + } + } - /** - * Gets the literal for a given token. - * - * @param integer $token - * - * @return string - */ - public function getLiteral($token) - { - $className = get_class($this); - $reflClass = new \ReflectionClass($className); - $constants = $reflClass->getConstants(); + /** + * Gets the literal for a given token. + * + * @param integer $token + * + * @return string + */ + public function getLiteral($token) + { + $className = get_class($this); + $reflClass = new \ReflectionClass($className); + $constants = $reflClass->getConstants(); - foreach ($constants as $name => $value) { - if ($value === $token) { - return $className . '::' . $name; - } - } + foreach ($constants as $name => $value) { + if ($value === $token) { + return $className . '::' . $name; + } + } - return $token; - } + return $token; + } - /** - * Regex modifiers - * - * @return string - */ - protected function getModifiers() - { - return 'i'; - } + /** + * Regex modifiers + * + * @return string + */ + protected function getModifiers() + { + return 'i'; + } - /** - * Lexical catchable patterns. - * - * @return array - */ - abstract protected function getCatchablePatterns(); + /** + * Lexical catchable patterns. + * + * @return array + */ + abstract protected function getCatchablePatterns(); - /** - * Lexical non-catchable patterns. - * - * @return array - */ - abstract protected function getNonCatchablePatterns(); + /** + * Lexical non-catchable patterns. + * + * @return array + */ + abstract protected function getNonCatchablePatterns(); - /** - * Retrieve token type. Also processes the token value if necessary. - * - * @param string $value - * - * @return integer - */ - abstract protected function getType(&$value); + /** + * Retrieve token type. Also processes the token value if necessary. + * + * @param string $value + * + * @return integer + */ + abstract protected function getType(&$value); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift.php b/htdocs/includes/swiftmailer/lib/classes/Swift.php index 09cdc4fbefd..51b19c9cb4e 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift.php @@ -15,64 +15,64 @@ */ abstract class Swift { - const VERSION = '6.3.0'; + const VERSION = '6.3.0'; - public static $initialized = false; - public static $inits = []; + public static $initialized = false; + public static $inits = []; - /** - * Registers an initializer callable that will be called the first time - * a SwiftMailer class is autoloaded. - * - * This enables you to tweak the default configuration in a lazy way. - * - * @param mixed $callable A valid PHP callable that will be called when autoloading the first Swift class - */ - public static function init($callable) - { - self::$inits[] = $callable; - } + /** + * Registers an initializer callable that will be called the first time + * a SwiftMailer class is autoloaded. + * + * This enables you to tweak the default configuration in a lazy way. + * + * @param mixed $callable A valid PHP callable that will be called when autoloading the first Swift class + */ + public static function init($callable) + { + self::$inits[] = $callable; + } - /** - * Internal autoloader for spl_autoload_register(). - * - * @param string $class - */ - public static function autoload($class) - { - // Don't interfere with other autoloaders - if (0 !== strpos($class, 'Swift_')) { - return; - } + /** + * Internal autoloader for spl_autoload_register(). + * + * @param string $class + */ + public static function autoload($class) + { + // Don't interfere with other autoloaders + if (0 !== strpos($class, 'Swift_')) { + return; + } - $path = __DIR__.'/'.str_replace('_', '/', $class).'.php'; + $path = __DIR__.'/'.str_replace('_', '/', $class).'.php'; - if (!file_exists($path)) { - return; - } + if (!file_exists($path)) { + return; + } - require $path; + require $path; - if (self::$inits && !self::$initialized) { - self::$initialized = true; - foreach (self::$inits as $init) { - \call_user_func($init); - } - } - } + if (self::$inits && !self::$initialized) { + self::$initialized = true; + foreach (self::$inits as $init) { + \call_user_func($init); + } + } + } - /** - * Configure autoloading using Swift Mailer. - * - * This is designed to play nicely with other autoloaders. - * - * @param mixed $callable A valid PHP callable that will be called when autoloading the first Swift class - */ - public static function registerAutoload($callable = null) - { - if (null !== $callable) { - self::$inits[] = $callable; - } - spl_autoload_register(['Swift', 'autoload']); - } + /** + * Configure autoloading using Swift Mailer. + * + * This is designed to play nicely with other autoloaders. + * + * @param mixed $callable A valid PHP callable that will be called when autoloading the first Swift class + */ + public static function registerAutoload($callable = null) + { + if (null !== $callable) { + self::$inits[] = $callable; + } + spl_autoload_register(['Swift', 'autoload']); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoder.php b/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoder.php index 643060e12c1..a1704ffb40a 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoder.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoder.php @@ -15,11 +15,11 @@ */ interface Swift_AddressEncoder { - /** - * Encodes an email address. - * - * @throws Swift_AddressEncoderException if the email cannot be represented in - * the encoding implemented by this class - */ - public function encodeString(string $address): string; + /** + * Encodes an email address. + * + * @throws Swift_AddressEncoderException if the email cannot be represented in + * the encoding implemented by this class + */ + public function encodeString(string $address): string; } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoder/IdnAddressEncoder.php b/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoder/IdnAddressEncoder.php index a00f90efa5e..a373ef9d546 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoder/IdnAddressEncoder.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoder/IdnAddressEncoder.php @@ -24,27 +24,27 @@ */ class Swift_AddressEncoder_IdnAddressEncoder implements Swift_AddressEncoder { - /** - * Encodes the domain part of an address using IDN. - * - * @throws Swift_AddressEncoderException If local-part contains non-ASCII characters - */ - public function encodeString(string $address): string - { - $i = strrpos($address, '@'); - if (false !== $i) { - $local = substr($address, 0, $i); - $domain = substr($address, $i + 1); + /** + * Encodes the domain part of an address using IDN. + * + * @throws Swift_AddressEncoderException If local-part contains non-ASCII characters + */ + public function encodeString(string $address): string + { + $i = strrpos($address, '@'); + if (false !== $i) { + $local = substr($address, 0, $i); + $domain = substr($address, $i + 1); - if (preg_match('/[^\x00-\x7F]/', $local)) { - throw new Swift_AddressEncoderException('Non-ASCII characters not supported in local-part', $address); - } + if (preg_match('/[^\x00-\x7F]/', $local)) { + throw new Swift_AddressEncoderException('Non-ASCII characters not supported in local-part', $address); + } - if (preg_match('/[^\x00-\x7F]/', $domain)) { - $address = sprintf('%s@%s', $local, idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46)); - } - } + if (preg_match('/[^\x00-\x7F]/', $domain)) { + $address = sprintf('%s@%s', $local, idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46)); + } + } - return $address; - } + return $address; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoder/Utf8AddressEncoder.php b/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoder/Utf8AddressEncoder.php index 29de0f5cc93..1b454305678 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoder/Utf8AddressEncoder.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoder/Utf8AddressEncoder.php @@ -26,11 +26,11 @@ */ class Swift_AddressEncoder_Utf8AddressEncoder implements Swift_AddressEncoder { - /** - * Returns the address verbatimly. - */ - public function encodeString(string $address): string - { - return $address; - } + /** + * Returns the address verbatimly. + */ + public function encodeString(string $address): string + { + return $address; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoderException.php b/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoderException.php index 7d499f1deaf..9b405476bcb 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoderException.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/AddressEncoderException.php @@ -16,17 +16,17 @@ */ class Swift_AddressEncoderException extends Swift_RfcComplianceException { - protected $address; + protected $address; - public function __construct(string $message, string $address) - { - parent::__construct($message); + public function __construct(string $message, string $address) + { + parent::__construct($message); - $this->address = $address; - } + $this->address = $address; + } - public function getAddress(): string - { - return $this->address; - } + public function getAddress(): string + { + return $this->address; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Attachment.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Attachment.php index f759001ad4e..7a1420f7986 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Attachment.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Attachment.php @@ -15,40 +15,40 @@ */ class Swift_Attachment extends Swift_Mime_Attachment { - /** - * Create a new Attachment. - * - * Details may be optionally provided to the constructor. - * - * @param string|Swift_OutputByteStream $data - * @param string $filename - * @param string $contentType - */ - public function __construct($data = null, $filename = null, $contentType = null) - { - \call_user_func_array( - [$this, 'Swift_Mime_Attachment::__construct'], - Swift_DependencyContainer::getInstance() - ->createDependenciesFor('mime.attachment') - ); + /** + * Create a new Attachment. + * + * Details may be optionally provided to the constructor. + * + * @param string|Swift_OutputByteStream $data + * @param string $filename + * @param string $contentType + */ + public function __construct($data = null, $filename = null, $contentType = null) + { + \call_user_func_array( + [$this, 'Swift_Mime_Attachment::__construct'], + Swift_DependencyContainer::getInstance() + ->createDependenciesFor('mime.attachment') + ); - $this->setBody($data, $contentType); - $this->setFilename($filename); - } + $this->setBody($data, $contentType); + $this->setFilename($filename); + } - /** - * Create a new Attachment from a filesystem path. - * - * @param string $path - * @param string $contentType optional - * - * @return self - */ - public static function fromPath($path, $contentType = null) - { - return (new self())->setFile( - new Swift_ByteStream_FileByteStream($path), - $contentType - ); - } + /** + * Create a new Attachment from a filesystem path. + * + * @param string $path + * @param string $contentType optional + * + * @return self + */ + public static function fromPath($path, $contentType = null) + { + return (new self())->setFile( + new Swift_ByteStream_FileByteStream($path), + $contentType + ); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/AbstractFilterableInputStream.php b/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/AbstractFilterableInputStream.php index 0f7833c3a19..3a69c15f1c4 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/AbstractFilterableInputStream.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/AbstractFilterableInputStream.php @@ -15,162 +15,162 @@ */ abstract class Swift_ByteStream_AbstractFilterableInputStream implements Swift_InputByteStream, Swift_Filterable { - /** - * Write sequence. - */ - protected $sequence = 0; + /** + * Write sequence. + */ + protected $sequence = 0; - /** - * StreamFilters. - * - * @var Swift_StreamFilter[] - */ - private $filters = []; + /** + * StreamFilters. + * + * @var Swift_StreamFilter[] + */ + private $filters = []; - /** - * A buffer for writing. - */ - private $writeBuffer = ''; + /** + * A buffer for writing. + */ + private $writeBuffer = ''; - /** - * Bound streams. - * - * @var Swift_InputByteStream[] - */ - private $mirrors = []; + /** + * Bound streams. + * + * @var Swift_InputByteStream[] + */ + private $mirrors = []; - /** - * Commit the given bytes to the storage medium immediately. - * - * @param string $bytes - */ - abstract protected function doCommit($bytes); + /** + * Commit the given bytes to the storage medium immediately. + * + * @param string $bytes + */ + abstract protected function doCommit($bytes); - /** - * Flush any buffers/content with immediate effect. - */ - abstract protected function flush(); + /** + * Flush any buffers/content with immediate effect. + */ + abstract protected function flush(); - /** - * Add a StreamFilter to this InputByteStream. - * - * @param string $key - */ - public function addFilter(Swift_StreamFilter $filter, $key) - { - $this->filters[$key] = $filter; - } + /** + * Add a StreamFilter to this InputByteStream. + * + * @param string $key + */ + public function addFilter(Swift_StreamFilter $filter, $key) + { + $this->filters[$key] = $filter; + } - /** - * Remove an already present StreamFilter based on its $key. - * - * @param string $key - */ - public function removeFilter($key) - { - unset($this->filters[$key]); - } + /** + * Remove an already present StreamFilter based on its $key. + * + * @param string $key + */ + public function removeFilter($key) + { + unset($this->filters[$key]); + } - /** - * Writes $bytes to the end of the stream. - * - * @param string $bytes - * - * @throws Swift_IoException - * - * @return int - */ - public function write($bytes) - { - $this->writeBuffer .= $bytes; - foreach ($this->filters as $filter) { - if ($filter->shouldBuffer($this->writeBuffer)) { - return; - } - } - $this->doWrite($this->writeBuffer); + /** + * Writes $bytes to the end of the stream. + * + * @param string $bytes + * + * @throws Swift_IoException + * + * @return int + */ + public function write($bytes) + { + $this->writeBuffer .= $bytes; + foreach ($this->filters as $filter) { + if ($filter->shouldBuffer($this->writeBuffer)) { + return; + } + } + $this->doWrite($this->writeBuffer); - return ++$this->sequence; - } + return ++$this->sequence; + } - /** - * For any bytes that are currently buffered inside the stream, force them - * off the buffer. - * - * @throws Swift_IoException - */ - public function commit() - { - $this->doWrite($this->writeBuffer); - } + /** + * For any bytes that are currently buffered inside the stream, force them + * off the buffer. + * + * @throws Swift_IoException + */ + public function commit() + { + $this->doWrite($this->writeBuffer); + } - /** - * Attach $is to this stream. - * - * The stream acts as an observer, receiving all data that is written. - * All {@link write()} and {@link flushBuffers()} operations will be mirrored. - */ - public function bind(Swift_InputByteStream $is) - { - $this->mirrors[] = $is; - } + /** + * Attach $is to this stream. + * + * The stream acts as an observer, receiving all data that is written. + * All {@link write()} and {@link flushBuffers()} operations will be mirrored. + */ + public function bind(Swift_InputByteStream $is) + { + $this->mirrors[] = $is; + } - /** - * Remove an already bound stream. - * - * If $is is not bound, no errors will be raised. - * If the stream currently has any buffered data it will be written to $is - * before unbinding occurs. - */ - public function unbind(Swift_InputByteStream $is) - { - foreach ($this->mirrors as $k => $stream) { - if ($is === $stream) { - if ('' !== $this->writeBuffer) { - $stream->write($this->writeBuffer); - } - unset($this->mirrors[$k]); - } - } - } + /** + * Remove an already bound stream. + * + * If $is is not bound, no errors will be raised. + * If the stream currently has any buffered data it will be written to $is + * before unbinding occurs. + */ + public function unbind(Swift_InputByteStream $is) + { + foreach ($this->mirrors as $k => $stream) { + if ($is === $stream) { + if ('' !== $this->writeBuffer) { + $stream->write($this->writeBuffer); + } + unset($this->mirrors[$k]); + } + } + } - /** - * Flush the contents of the stream (empty it) and set the internal pointer - * to the beginning. - * - * @throws Swift_IoException - */ - public function flushBuffers() - { - if ('' !== $this->writeBuffer) { - $this->doWrite($this->writeBuffer); - } - $this->flush(); + /** + * Flush the contents of the stream (empty it) and set the internal pointer + * to the beginning. + * + * @throws Swift_IoException + */ + public function flushBuffers() + { + if ('' !== $this->writeBuffer) { + $this->doWrite($this->writeBuffer); + } + $this->flush(); - foreach ($this->mirrors as $stream) { - $stream->flushBuffers(); - } - } + foreach ($this->mirrors as $stream) { + $stream->flushBuffers(); + } + } - /** Run $bytes through all filters */ - private function filter($bytes) - { - foreach ($this->filters as $filter) { - $bytes = $filter->filter($bytes); - } + /** Run $bytes through all filters */ + private function filter($bytes) + { + foreach ($this->filters as $filter) { + $bytes = $filter->filter($bytes); + } - return $bytes; - } + return $bytes; + } - /** Just write the bytes to the stream */ - private function doWrite($bytes) - { - $this->doCommit($this->filter($bytes)); + /** Just write the bytes to the stream */ + private function doWrite($bytes) + { + $this->doCommit($this->filter($bytes)); - foreach ($this->mirrors as $stream) { - $stream->write($bytes); - } + foreach ($this->mirrors as $stream) { + $stream->write($bytes); + } - $this->writeBuffer = ''; - } + $this->writeBuffer = ''; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/ArrayByteStream.php b/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/ArrayByteStream.php index 53d5cef10a0..4f3dcc37745 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/ArrayByteStream.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/ArrayByteStream.php @@ -15,164 +15,164 @@ */ class Swift_ByteStream_ArrayByteStream implements Swift_InputByteStream, Swift_OutputByteStream { - /** - * The internal stack of bytes. - * - * @var string[] - */ - private $array = []; + /** + * The internal stack of bytes. + * + * @var string[] + */ + private $array = []; - /** - * The size of the stack. - * - * @var int - */ - private $arraySize = 0; + /** + * The size of the stack. + * + * @var int + */ + private $arraySize = 0; - /** - * The internal pointer offset. - * - * @var int - */ - private $offset = 0; + /** + * The internal pointer offset. + * + * @var int + */ + private $offset = 0; - /** - * Bound streams. - * - * @var Swift_InputByteStream[] - */ - private $mirrors = []; + /** + * Bound streams. + * + * @var Swift_InputByteStream[] + */ + private $mirrors = []; - /** - * Create a new ArrayByteStream. - * - * If $stack is given the stream will be populated with the bytes it contains. - * - * @param mixed $stack of bytes in string or array form, optional - */ - public function __construct($stack = null) - { - if (\is_array($stack)) { - $this->array = $stack; - $this->arraySize = \count($stack); - } elseif (\is_string($stack)) { - $this->write($stack); - } else { - $this->array = []; - } - } + /** + * Create a new ArrayByteStream. + * + * If $stack is given the stream will be populated with the bytes it contains. + * + * @param mixed $stack of bytes in string or array form, optional + */ + public function __construct($stack = null) + { + if (\is_array($stack)) { + $this->array = $stack; + $this->arraySize = \count($stack); + } elseif (\is_string($stack)) { + $this->write($stack); + } else { + $this->array = []; + } + } - /** - * Reads $length bytes from the stream into a string and moves the pointer - * through the stream by $length. - * - * If less bytes exist than are requested the - * remaining bytes are given instead. If no bytes are remaining at all, boolean - * false is returned. - * - * @param int $length - * - * @return string - */ - public function read($length) - { - if ($this->offset == $this->arraySize) { - return false; - } + /** + * Reads $length bytes from the stream into a string and moves the pointer + * through the stream by $length. + * + * If less bytes exist than are requested the + * remaining bytes are given instead. If no bytes are remaining at all, boolean + * false is returned. + * + * @param int $length + * + * @return string + */ + public function read($length) + { + if ($this->offset == $this->arraySize) { + return false; + } - // Don't use array slice - $end = $length + $this->offset; - $end = $this->arraySize < $end ? $this->arraySize : $end; - $ret = ''; - for (; $this->offset < $end; ++$this->offset) { - $ret .= $this->array[$this->offset]; - } + // Don't use array slice + $end = $length + $this->offset; + $end = $this->arraySize < $end ? $this->arraySize : $end; + $ret = ''; + for (; $this->offset < $end; ++$this->offset) { + $ret .= $this->array[$this->offset]; + } - return $ret; - } + return $ret; + } - /** - * Writes $bytes to the end of the stream. - * - * @param string $bytes - */ - public function write($bytes) - { - $to_add = str_split($bytes); - foreach ($to_add as $value) { - $this->array[] = $value; - } - $this->arraySize = \count($this->array); + /** + * Writes $bytes to the end of the stream. + * + * @param string $bytes + */ + public function write($bytes) + { + $to_add = str_split($bytes); + foreach ($to_add as $value) { + $this->array[] = $value; + } + $this->arraySize = \count($this->array); - foreach ($this->mirrors as $stream) { - $stream->write($bytes); - } - } + foreach ($this->mirrors as $stream) { + $stream->write($bytes); + } + } - /** - * Not used. - */ - public function commit() - { - } + /** + * Not used. + */ + public function commit() + { + } - /** - * Attach $is to this stream. - * - * The stream acts as an observer, receiving all data that is written. - * All {@link write()} and {@link flushBuffers()} operations will be mirrored. - */ - public function bind(Swift_InputByteStream $is) - { - $this->mirrors[] = $is; - } + /** + * Attach $is to this stream. + * + * The stream acts as an observer, receiving all data that is written. + * All {@link write()} and {@link flushBuffers()} operations will be mirrored. + */ + public function bind(Swift_InputByteStream $is) + { + $this->mirrors[] = $is; + } - /** - * Remove an already bound stream. - * - * If $is is not bound, no errors will be raised. - * If the stream currently has any buffered data it will be written to $is - * before unbinding occurs. - */ - public function unbind(Swift_InputByteStream $is) - { - foreach ($this->mirrors as $k => $stream) { - if ($is === $stream) { - unset($this->mirrors[$k]); - } - } - } + /** + * Remove an already bound stream. + * + * If $is is not bound, no errors will be raised. + * If the stream currently has any buffered data it will be written to $is + * before unbinding occurs. + */ + public function unbind(Swift_InputByteStream $is) + { + foreach ($this->mirrors as $k => $stream) { + if ($is === $stream) { + unset($this->mirrors[$k]); + } + } + } - /** - * Move the internal read pointer to $byteOffset in the stream. - * - * @param int $byteOffset - * - * @return bool - */ - public function setReadPointer($byteOffset) - { - if ($byteOffset > $this->arraySize) { - $byteOffset = $this->arraySize; - } elseif ($byteOffset < 0) { - $byteOffset = 0; - } + /** + * Move the internal read pointer to $byteOffset in the stream. + * + * @param int $byteOffset + * + * @return bool + */ + public function setReadPointer($byteOffset) + { + if ($byteOffset > $this->arraySize) { + $byteOffset = $this->arraySize; + } elseif ($byteOffset < 0) { + $byteOffset = 0; + } - $this->offset = $byteOffset; - } + $this->offset = $byteOffset; + } - /** - * Flush the contents of the stream (empty it) and set the internal pointer - * to the beginning. - */ - public function flushBuffers() - { - $this->offset = 0; - $this->array = []; - $this->arraySize = 0; + /** + * Flush the contents of the stream (empty it) and set the internal pointer + * to the beginning. + */ + public function flushBuffers() + { + $this->offset = 0; + $this->array = []; + $this->arraySize = 0; - foreach ($this->mirrors as $stream) { - $stream->flushBuffers(); - } - } + foreach ($this->mirrors as $stream) { + $stream->flushBuffers(); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/FileByteStream.php b/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/FileByteStream.php index b27d96a1760..f6391219e71 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/FileByteStream.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/FileByteStream.php @@ -15,200 +15,200 @@ */ class Swift_ByteStream_FileByteStream extends Swift_ByteStream_AbstractFilterableInputStream implements Swift_FileStream { - /** The internal pointer offset */ - private $offset = 0; + /** The internal pointer offset */ + private $offset = 0; - /** The path to the file */ - private $path; + /** The path to the file */ + private $path; - /** The mode this file is opened in for writing */ - private $mode; + /** The mode this file is opened in for writing */ + private $mode; - /** A lazy-loaded resource handle for reading the file */ - private $reader; + /** A lazy-loaded resource handle for reading the file */ + private $reader; - /** A lazy-loaded resource handle for writing the file */ - private $writer; + /** A lazy-loaded resource handle for writing the file */ + private $writer; - /** If stream is seekable true/false, or null if not known */ - private $seekable = null; + /** If stream is seekable true/false, or null if not known */ + private $seekable = null; - /** - * Create a new FileByteStream for $path. - * - * @param string $path - * @param bool $writable if true - */ - public function __construct($path, $writable = false) - { - if (empty($path)) { - throw new Swift_IoException('The path cannot be empty'); - } - $this->path = $path; - $this->mode = $writable ? 'w+b' : 'rb'; - } + /** + * Create a new FileByteStream for $path. + * + * @param string $path + * @param bool $writable if true + */ + public function __construct($path, $writable = false) + { + if (empty($path)) { + throw new Swift_IoException('The path cannot be empty'); + } + $this->path = $path; + $this->mode = $writable ? 'w+b' : 'rb'; + } - /** - * Get the complete path to the file. - * - * @return string - */ - public function getPath() - { - return $this->path; - } + /** + * Get the complete path to the file. + * + * @return string + */ + public function getPath() + { + return $this->path; + } - /** - * Reads $length bytes from the stream into a string and moves the pointer - * through the stream by $length. - * - * If less bytes exist than are requested the - * remaining bytes are given instead. If no bytes are remaining at all, boolean - * false is returned. - * - * @param int $length - * - * @return string|bool - * - * @throws Swift_IoException - */ - public function read($length) - { - $fp = $this->getReadHandle(); - if (!feof($fp)) { - $bytes = fread($fp, $length); - $this->offset = ftell($fp); + /** + * Reads $length bytes from the stream into a string and moves the pointer + * through the stream by $length. + * + * If less bytes exist than are requested the + * remaining bytes are given instead. If no bytes are remaining at all, boolean + * false is returned. + * + * @param int $length + * + * @return string|bool + * + * @throws Swift_IoException + */ + public function read($length) + { + $fp = $this->getReadHandle(); + if (!feof($fp)) { + $bytes = fread($fp, $length); + $this->offset = ftell($fp); - // If we read one byte after reaching the end of the file - // feof() will return false and an empty string is returned - if ((false === $bytes || '' === $bytes) && feof($fp)) { - $this->resetReadHandle(); + // If we read one byte after reaching the end of the file + // feof() will return false and an empty string is returned + if ((false === $bytes || '' === $bytes) && feof($fp)) { + $this->resetReadHandle(); - return false; - } + return false; + } - return $bytes; - } + return $bytes; + } - $this->resetReadHandle(); + $this->resetReadHandle(); - return false; - } + return false; + } - /** - * Move the internal read pointer to $byteOffset in the stream. - * - * @param int $byteOffset - * - * @return bool - */ - public function setReadPointer($byteOffset) - { - if (isset($this->reader)) { - $this->seekReadStreamToPosition($byteOffset); - } - $this->offset = $byteOffset; - } + /** + * Move the internal read pointer to $byteOffset in the stream. + * + * @param int $byteOffset + * + * @return bool + */ + public function setReadPointer($byteOffset) + { + if (isset($this->reader)) { + $this->seekReadStreamToPosition($byteOffset); + } + $this->offset = $byteOffset; + } - /** Just write the bytes to the file */ - protected function doCommit($bytes) - { - fwrite($this->getWriteHandle(), $bytes); - $this->resetReadHandle(); - } + /** Just write the bytes to the file */ + protected function doCommit($bytes) + { + fwrite($this->getWriteHandle(), $bytes); + $this->resetReadHandle(); + } - /** Not used */ - protected function flush() - { - } + /** Not used */ + protected function flush() + { + } - /** Get the resource for reading */ - private function getReadHandle() - { - if (!isset($this->reader)) { - $pointer = @fopen($this->path, 'rb'); - if (!$pointer) { - throw new Swift_IoException('Unable to open file for reading ['.$this->path.']'); - } - $this->reader = $pointer; - if (0 != $this->offset) { - $this->getReadStreamSeekableStatus(); - $this->seekReadStreamToPosition($this->offset); - } - } + /** Get the resource for reading */ + private function getReadHandle() + { + if (!isset($this->reader)) { + $pointer = @fopen($this->path, 'rb'); + if (!$pointer) { + throw new Swift_IoException('Unable to open file for reading ['.$this->path.']'); + } + $this->reader = $pointer; + if (0 != $this->offset) { + $this->getReadStreamSeekableStatus(); + $this->seekReadStreamToPosition($this->offset); + } + } - return $this->reader; - } + return $this->reader; + } - /** Get the resource for writing */ - private function getWriteHandle() - { - if (!isset($this->writer)) { - if (!$this->writer = fopen($this->path, $this->mode)) { - throw new Swift_IoException('Unable to open file for writing ['.$this->path.']'); - } - } + /** Get the resource for writing */ + private function getWriteHandle() + { + if (!isset($this->writer)) { + if (!$this->writer = fopen($this->path, $this->mode)) { + throw new Swift_IoException('Unable to open file for writing ['.$this->path.']'); + } + } - return $this->writer; - } + return $this->writer; + } - /** Force a reload of the resource for reading */ - private function resetReadHandle() - { - if (isset($this->reader)) { - fclose($this->reader); - $this->reader = null; - } - } + /** Force a reload of the resource for reading */ + private function resetReadHandle() + { + if (isset($this->reader)) { + fclose($this->reader); + $this->reader = null; + } + } - /** Check if ReadOnly Stream is seekable */ - private function getReadStreamSeekableStatus() - { - $metas = stream_get_meta_data($this->reader); - $this->seekable = $metas['seekable']; - } + /** Check if ReadOnly Stream is seekable */ + private function getReadStreamSeekableStatus() + { + $metas = stream_get_meta_data($this->reader); + $this->seekable = $metas['seekable']; + } - /** Streams in a readOnly stream ensuring copy if needed */ - private function seekReadStreamToPosition($offset) - { - if (null === $this->seekable) { - $this->getReadStreamSeekableStatus(); - } - if (false === $this->seekable) { - $currentPos = ftell($this->reader); - if ($currentPos < $offset) { - $toDiscard = $offset - $currentPos; - fread($this->reader, $toDiscard); + /** Streams in a readOnly stream ensuring copy if needed */ + private function seekReadStreamToPosition($offset) + { + if (null === $this->seekable) { + $this->getReadStreamSeekableStatus(); + } + if (false === $this->seekable) { + $currentPos = ftell($this->reader); + if ($currentPos < $offset) { + $toDiscard = $offset - $currentPos; + fread($this->reader, $toDiscard); - return; - } - $this->copyReadStream(); - } - fseek($this->reader, $offset, SEEK_SET); - } + return; + } + $this->copyReadStream(); + } + fseek($this->reader, $offset, SEEK_SET); + } - /** Copy a readOnly Stream to ensure seekability */ - private function copyReadStream() - { - if ($tmpFile = fopen('php://temp/maxmemory:4096', 'w+b')) { - /* We have opened a php:// Stream Should work without problem */ - } elseif (\function_exists('sys_get_temp_dir') && is_writable(sys_get_temp_dir()) && ($tmpFile = tmpfile())) { - /* We have opened a tmpfile */ - } else { - throw new Swift_IoException('Unable to copy the file to make it seekable, sys_temp_dir is not writable, php://memory not available'); - } - $currentPos = ftell($this->reader); - fclose($this->reader); - $source = fopen($this->path, 'rb'); - if (!$source) { - throw new Swift_IoException('Unable to open file for copying ['.$this->path.']'); - } - fseek($tmpFile, 0, SEEK_SET); - while (!feof($source)) { - fwrite($tmpFile, fread($source, 4096)); - } - fseek($tmpFile, $currentPos, SEEK_SET); - fclose($source); - $this->reader = $tmpFile; - } + /** Copy a readOnly Stream to ensure seekability */ + private function copyReadStream() + { + if ($tmpFile = fopen('php://temp/maxmemory:4096', 'w+b')) { + /* We have opened a php:// Stream Should work without problem */ + } elseif (\function_exists('sys_get_temp_dir') && is_writable(sys_get_temp_dir()) && ($tmpFile = tmpfile())) { + /* We have opened a tmpfile */ + } else { + throw new Swift_IoException('Unable to copy the file to make it seekable, sys_temp_dir is not writable, php://memory not available'); + } + $currentPos = ftell($this->reader); + fclose($this->reader); + $source = fopen($this->path, 'rb'); + if (!$source) { + throw new Swift_IoException('Unable to open file for copying ['.$this->path.']'); + } + fseek($tmpFile, 0, SEEK_SET); + while (!feof($source)) { + fwrite($tmpFile, fread($source, 4096)); + } + fseek($tmpFile, $currentPos, SEEK_SET); + fclose($source); + $this->reader = $tmpFile; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/TemporaryFileByteStream.php b/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/TemporaryFileByteStream.php index 5ea62c5a389..0dc61909d31 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/TemporaryFileByteStream.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/ByteStream/TemporaryFileByteStream.php @@ -13,40 +13,40 @@ */ class Swift_ByteStream_TemporaryFileByteStream extends Swift_ByteStream_FileByteStream { - public function __construct() - { - $filePath = tempnam(sys_get_temp_dir(), 'FileByteStream'); + public function __construct() + { + $filePath = tempnam(sys_get_temp_dir(), 'FileByteStream'); - if (false === $filePath) { - throw new Swift_IoException('Failed to retrieve temporary file name.'); - } + if (false === $filePath) { + throw new Swift_IoException('Failed to retrieve temporary file name.'); + } - parent::__construct($filePath, true); - } + parent::__construct($filePath, true); + } - public function getContent() - { - if (false === ($content = file_get_contents($this->getPath()))) { - throw new Swift_IoException('Failed to get temporary file content.'); - } + public function getContent() + { + if (false === ($content = file_get_contents($this->getPath()))) { + throw new Swift_IoException('Failed to get temporary file content.'); + } - return $content; - } + return $content; + } - public function __destruct() - { - if (file_exists($this->getPath())) { - @unlink($this->getPath()); - } - } + public function __destruct() + { + if (file_exists($this->getPath())) { + @unlink($this->getPath()); + } + } - public function __sleep() - { - throw new \BadMethodCallException('Cannot serialize '.__CLASS__); - } + public function __sleep() + { + throw new \BadMethodCallException('Cannot serialize '.__CLASS__); + } - public function __wakeup() - { - throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); - } + public function __wakeup() + { + throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReader/GenericFixedWidthReader.php b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReader/GenericFixedWidthReader.php index 3e074eaf4e9..3e055afd9dc 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReader/GenericFixedWidthReader.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReader/GenericFixedWidthReader.php @@ -16,82 +16,82 @@ */ class Swift_CharacterReader_GenericFixedWidthReader implements Swift_CharacterReader { - /** - * The number of bytes in a single character. - * - * @var int - */ - private $width; + /** + * The number of bytes in a single character. + * + * @var int + */ + private $width; - /** - * Creates a new GenericFixedWidthReader using $width bytes per character. - * - * @param int $width - */ - public function __construct($width) - { - $this->width = $width; - } + /** + * Creates a new GenericFixedWidthReader using $width bytes per character. + * + * @param int $width + */ + public function __construct($width) + { + $this->width = $width; + } - /** - * Returns the complete character map. - * - * @param string $string - * @param int $startOffset - * @param array $currentMap - * @param mixed $ignoredChars - * - * @return int - */ - public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars) - { - $strlen = \strlen($string); - // % and / are CPU intensive, so, maybe find a better way - $ignored = $strlen % $this->width; - $ignoredChars = $ignored ? substr($string, -$ignored) : ''; - $currentMap = $this->width; + /** + * Returns the complete character map. + * + * @param string $string + * @param int $startOffset + * @param array $currentMap + * @param mixed $ignoredChars + * + * @return int + */ + public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars) + { + $strlen = \strlen($string); + // % and / are CPU intensive, so, maybe find a better way + $ignored = $strlen % $this->width; + $ignoredChars = $ignored ? substr($string, -$ignored) : ''; + $currentMap = $this->width; - return ($strlen - $ignored) / $this->width; - } + return ($strlen - $ignored) / $this->width; + } - /** - * Returns the mapType. - * - * @return int - */ - public function getMapType() - { - return self::MAP_TYPE_FIXED_LEN; - } + /** + * Returns the mapType. + * + * @return int + */ + public function getMapType() + { + return self::MAP_TYPE_FIXED_LEN; + } - /** - * Returns an integer which specifies how many more bytes to read. - * - * A positive integer indicates the number of more bytes to fetch before invoking - * this method again. - * - * A value of zero means this is already a valid character. - * A value of -1 means this cannot possibly be a valid character. - * - * @param string $bytes - * @param int $size - * - * @return int - */ - public function validateByteSequence($bytes, $size) - { - $needed = $this->width - $size; + /** + * Returns an integer which specifies how many more bytes to read. + * + * A positive integer indicates the number of more bytes to fetch before invoking + * this method again. + * + * A value of zero means this is already a valid character. + * A value of -1 means this cannot possibly be a valid character. + * + * @param string $bytes + * @param int $size + * + * @return int + */ + public function validateByteSequence($bytes, $size) + { + $needed = $this->width - $size; - return $needed > -1 ? $needed : -1; - } + return $needed > -1 ? $needed : -1; + } - /** - * Returns the number of bytes which should be read to start each character. - * - * @return int - */ - public function getInitialByteSize() - { - return $this->width; - } + /** + * Returns the number of bytes which should be read to start each character. + * + * @return int + */ + public function getInitialByteSize() + { + return $this->width; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReader/UsAsciiReader.php b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReader/UsAsciiReader.php index 7ddc72a6610..ffc05f7166a 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReader/UsAsciiReader.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReader/UsAsciiReader.php @@ -15,70 +15,70 @@ */ class Swift_CharacterReader_UsAsciiReader implements Swift_CharacterReader { - /** - * Returns the complete character map. - * - * @param string $string - * @param int $startOffset - * @param array $currentMap - * @param string $ignoredChars - * - * @return int - */ - public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars) - { - $strlen = \strlen($string); - $ignoredChars = ''; - for ($i = 0; $i < $strlen; ++$i) { - if ($string[$i] > "\x07F") { - // Invalid char - $currentMap[$i + $startOffset] = $string[$i]; - } - } + /** + * Returns the complete character map. + * + * @param string $string + * @param int $startOffset + * @param array $currentMap + * @param string $ignoredChars + * + * @return int + */ + public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars) + { + $strlen = \strlen($string); + $ignoredChars = ''; + for ($i = 0; $i < $strlen; ++$i) { + if ($string[$i] > "\x07F") { + // Invalid char + $currentMap[$i + $startOffset] = $string[$i]; + } + } - return $strlen; - } + return $strlen; + } - /** - * Returns mapType. - * - * @return int mapType - */ - public function getMapType() - { - return self::MAP_TYPE_INVALID; - } + /** + * Returns mapType. + * + * @return int mapType + */ + public function getMapType() + { + return self::MAP_TYPE_INVALID; + } - /** - * Returns an integer which specifies how many more bytes to read. - * - * A positive integer indicates the number of more bytes to fetch before invoking - * this method again. - * A value of zero means this is already a valid character. - * A value of -1 means this cannot possibly be a valid character. - * - * @param string $bytes - * @param int $size - * - * @return int - */ - public function validateByteSequence($bytes, $size) - { - $byte = reset($bytes); - if (1 == \count($bytes) && $byte >= 0x00 && $byte <= 0x7F) { - return 0; - } + /** + * Returns an integer which specifies how many more bytes to read. + * + * A positive integer indicates the number of more bytes to fetch before invoking + * this method again. + * A value of zero means this is already a valid character. + * A value of -1 means this cannot possibly be a valid character. + * + * @param string $bytes + * @param int $size + * + * @return int + */ + public function validateByteSequence($bytes, $size) + { + $byte = reset($bytes); + if (1 == \count($bytes) && $byte >= 0x00 && $byte <= 0x7F) { + return 0; + } - return -1; - } + return -1; + } - /** - * Returns the number of bytes which should be read to start each character. - * - * @return int - */ - public function getInitialByteSize() - { - return 1; - } + /** + * Returns the number of bytes which should be read to start each character. + * + * @return int + */ + public function getInitialByteSize() + { + return 1; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReader/Utf8Reader.php b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReader/Utf8Reader.php index f828f151121..da37e0da9ab 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReader/Utf8Reader.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReader/Utf8Reader.php @@ -16,161 +16,161 @@ */ class Swift_CharacterReader_Utf8Reader implements Swift_CharacterReader { - /** Pre-computed for optimization */ - private static $length_map = [ - // N=0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x0N - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x1N - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x2N - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x3N - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x4N - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x5N - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x6N - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x7N - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x8N - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x9N - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xAN - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xBN - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xCN - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xDN - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xEN - 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0, // 0xFN - ]; + /** Pre-computed for optimization */ + private static $length_map = [ + // N=0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x0N + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x1N + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x2N + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x3N + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x4N + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x5N + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x6N + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x7N + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x8N + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x9N + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xAN + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xBN + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xCN + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xDN + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xEN + 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0, // 0xFN + ]; - private static $s_length_map = [ - "\x00" => 1, "\x01" => 1, "\x02" => 1, "\x03" => 1, "\x04" => 1, "\x05" => 1, "\x06" => 1, "\x07" => 1, - "\x08" => 1, "\x09" => 1, "\x0a" => 1, "\x0b" => 1, "\x0c" => 1, "\x0d" => 1, "\x0e" => 1, "\x0f" => 1, - "\x10" => 1, "\x11" => 1, "\x12" => 1, "\x13" => 1, "\x14" => 1, "\x15" => 1, "\x16" => 1, "\x17" => 1, - "\x18" => 1, "\x19" => 1, "\x1a" => 1, "\x1b" => 1, "\x1c" => 1, "\x1d" => 1, "\x1e" => 1, "\x1f" => 1, - "\x20" => 1, "\x21" => 1, "\x22" => 1, "\x23" => 1, "\x24" => 1, "\x25" => 1, "\x26" => 1, "\x27" => 1, - "\x28" => 1, "\x29" => 1, "\x2a" => 1, "\x2b" => 1, "\x2c" => 1, "\x2d" => 1, "\x2e" => 1, "\x2f" => 1, - "\x30" => 1, "\x31" => 1, "\x32" => 1, "\x33" => 1, "\x34" => 1, "\x35" => 1, "\x36" => 1, "\x37" => 1, - "\x38" => 1, "\x39" => 1, "\x3a" => 1, "\x3b" => 1, "\x3c" => 1, "\x3d" => 1, "\x3e" => 1, "\x3f" => 1, - "\x40" => 1, "\x41" => 1, "\x42" => 1, "\x43" => 1, "\x44" => 1, "\x45" => 1, "\x46" => 1, "\x47" => 1, - "\x48" => 1, "\x49" => 1, "\x4a" => 1, "\x4b" => 1, "\x4c" => 1, "\x4d" => 1, "\x4e" => 1, "\x4f" => 1, - "\x50" => 1, "\x51" => 1, "\x52" => 1, "\x53" => 1, "\x54" => 1, "\x55" => 1, "\x56" => 1, "\x57" => 1, - "\x58" => 1, "\x59" => 1, "\x5a" => 1, "\x5b" => 1, "\x5c" => 1, "\x5d" => 1, "\x5e" => 1, "\x5f" => 1, - "\x60" => 1, "\x61" => 1, "\x62" => 1, "\x63" => 1, "\x64" => 1, "\x65" => 1, "\x66" => 1, "\x67" => 1, - "\x68" => 1, "\x69" => 1, "\x6a" => 1, "\x6b" => 1, "\x6c" => 1, "\x6d" => 1, "\x6e" => 1, "\x6f" => 1, - "\x70" => 1, "\x71" => 1, "\x72" => 1, "\x73" => 1, "\x74" => 1, "\x75" => 1, "\x76" => 1, "\x77" => 1, - "\x78" => 1, "\x79" => 1, "\x7a" => 1, "\x7b" => 1, "\x7c" => 1, "\x7d" => 1, "\x7e" => 1, "\x7f" => 1, - "\x80" => 0, "\x81" => 0, "\x82" => 0, "\x83" => 0, "\x84" => 0, "\x85" => 0, "\x86" => 0, "\x87" => 0, - "\x88" => 0, "\x89" => 0, "\x8a" => 0, "\x8b" => 0, "\x8c" => 0, "\x8d" => 0, "\x8e" => 0, "\x8f" => 0, - "\x90" => 0, "\x91" => 0, "\x92" => 0, "\x93" => 0, "\x94" => 0, "\x95" => 0, "\x96" => 0, "\x97" => 0, - "\x98" => 0, "\x99" => 0, "\x9a" => 0, "\x9b" => 0, "\x9c" => 0, "\x9d" => 0, "\x9e" => 0, "\x9f" => 0, - "\xa0" => 0, "\xa1" => 0, "\xa2" => 0, "\xa3" => 0, "\xa4" => 0, "\xa5" => 0, "\xa6" => 0, "\xa7" => 0, - "\xa8" => 0, "\xa9" => 0, "\xaa" => 0, "\xab" => 0, "\xac" => 0, "\xad" => 0, "\xae" => 0, "\xaf" => 0, - "\xb0" => 0, "\xb1" => 0, "\xb2" => 0, "\xb3" => 0, "\xb4" => 0, "\xb5" => 0, "\xb6" => 0, "\xb7" => 0, - "\xb8" => 0, "\xb9" => 0, "\xba" => 0, "\xbb" => 0, "\xbc" => 0, "\xbd" => 0, "\xbe" => 0, "\xbf" => 0, - "\xc0" => 2, "\xc1" => 2, "\xc2" => 2, "\xc3" => 2, "\xc4" => 2, "\xc5" => 2, "\xc6" => 2, "\xc7" => 2, - "\xc8" => 2, "\xc9" => 2, "\xca" => 2, "\xcb" => 2, "\xcc" => 2, "\xcd" => 2, "\xce" => 2, "\xcf" => 2, - "\xd0" => 2, "\xd1" => 2, "\xd2" => 2, "\xd3" => 2, "\xd4" => 2, "\xd5" => 2, "\xd6" => 2, "\xd7" => 2, - "\xd8" => 2, "\xd9" => 2, "\xda" => 2, "\xdb" => 2, "\xdc" => 2, "\xdd" => 2, "\xde" => 2, "\xdf" => 2, - "\xe0" => 3, "\xe1" => 3, "\xe2" => 3, "\xe3" => 3, "\xe4" => 3, "\xe5" => 3, "\xe6" => 3, "\xe7" => 3, - "\xe8" => 3, "\xe9" => 3, "\xea" => 3, "\xeb" => 3, "\xec" => 3, "\xed" => 3, "\xee" => 3, "\xef" => 3, - "\xf0" => 4, "\xf1" => 4, "\xf2" => 4, "\xf3" => 4, "\xf4" => 4, "\xf5" => 4, "\xf6" => 4, "\xf7" => 4, - "\xf8" => 5, "\xf9" => 5, "\xfa" => 5, "\xfb" => 5, "\xfc" => 6, "\xfd" => 6, "\xfe" => 0, "\xff" => 0, - ]; + private static $s_length_map = [ + "\x00" => 1, "\x01" => 1, "\x02" => 1, "\x03" => 1, "\x04" => 1, "\x05" => 1, "\x06" => 1, "\x07" => 1, + "\x08" => 1, "\x09" => 1, "\x0a" => 1, "\x0b" => 1, "\x0c" => 1, "\x0d" => 1, "\x0e" => 1, "\x0f" => 1, + "\x10" => 1, "\x11" => 1, "\x12" => 1, "\x13" => 1, "\x14" => 1, "\x15" => 1, "\x16" => 1, "\x17" => 1, + "\x18" => 1, "\x19" => 1, "\x1a" => 1, "\x1b" => 1, "\x1c" => 1, "\x1d" => 1, "\x1e" => 1, "\x1f" => 1, + "\x20" => 1, "\x21" => 1, "\x22" => 1, "\x23" => 1, "\x24" => 1, "\x25" => 1, "\x26" => 1, "\x27" => 1, + "\x28" => 1, "\x29" => 1, "\x2a" => 1, "\x2b" => 1, "\x2c" => 1, "\x2d" => 1, "\x2e" => 1, "\x2f" => 1, + "\x30" => 1, "\x31" => 1, "\x32" => 1, "\x33" => 1, "\x34" => 1, "\x35" => 1, "\x36" => 1, "\x37" => 1, + "\x38" => 1, "\x39" => 1, "\x3a" => 1, "\x3b" => 1, "\x3c" => 1, "\x3d" => 1, "\x3e" => 1, "\x3f" => 1, + "\x40" => 1, "\x41" => 1, "\x42" => 1, "\x43" => 1, "\x44" => 1, "\x45" => 1, "\x46" => 1, "\x47" => 1, + "\x48" => 1, "\x49" => 1, "\x4a" => 1, "\x4b" => 1, "\x4c" => 1, "\x4d" => 1, "\x4e" => 1, "\x4f" => 1, + "\x50" => 1, "\x51" => 1, "\x52" => 1, "\x53" => 1, "\x54" => 1, "\x55" => 1, "\x56" => 1, "\x57" => 1, + "\x58" => 1, "\x59" => 1, "\x5a" => 1, "\x5b" => 1, "\x5c" => 1, "\x5d" => 1, "\x5e" => 1, "\x5f" => 1, + "\x60" => 1, "\x61" => 1, "\x62" => 1, "\x63" => 1, "\x64" => 1, "\x65" => 1, "\x66" => 1, "\x67" => 1, + "\x68" => 1, "\x69" => 1, "\x6a" => 1, "\x6b" => 1, "\x6c" => 1, "\x6d" => 1, "\x6e" => 1, "\x6f" => 1, + "\x70" => 1, "\x71" => 1, "\x72" => 1, "\x73" => 1, "\x74" => 1, "\x75" => 1, "\x76" => 1, "\x77" => 1, + "\x78" => 1, "\x79" => 1, "\x7a" => 1, "\x7b" => 1, "\x7c" => 1, "\x7d" => 1, "\x7e" => 1, "\x7f" => 1, + "\x80" => 0, "\x81" => 0, "\x82" => 0, "\x83" => 0, "\x84" => 0, "\x85" => 0, "\x86" => 0, "\x87" => 0, + "\x88" => 0, "\x89" => 0, "\x8a" => 0, "\x8b" => 0, "\x8c" => 0, "\x8d" => 0, "\x8e" => 0, "\x8f" => 0, + "\x90" => 0, "\x91" => 0, "\x92" => 0, "\x93" => 0, "\x94" => 0, "\x95" => 0, "\x96" => 0, "\x97" => 0, + "\x98" => 0, "\x99" => 0, "\x9a" => 0, "\x9b" => 0, "\x9c" => 0, "\x9d" => 0, "\x9e" => 0, "\x9f" => 0, + "\xa0" => 0, "\xa1" => 0, "\xa2" => 0, "\xa3" => 0, "\xa4" => 0, "\xa5" => 0, "\xa6" => 0, "\xa7" => 0, + "\xa8" => 0, "\xa9" => 0, "\xaa" => 0, "\xab" => 0, "\xac" => 0, "\xad" => 0, "\xae" => 0, "\xaf" => 0, + "\xb0" => 0, "\xb1" => 0, "\xb2" => 0, "\xb3" => 0, "\xb4" => 0, "\xb5" => 0, "\xb6" => 0, "\xb7" => 0, + "\xb8" => 0, "\xb9" => 0, "\xba" => 0, "\xbb" => 0, "\xbc" => 0, "\xbd" => 0, "\xbe" => 0, "\xbf" => 0, + "\xc0" => 2, "\xc1" => 2, "\xc2" => 2, "\xc3" => 2, "\xc4" => 2, "\xc5" => 2, "\xc6" => 2, "\xc7" => 2, + "\xc8" => 2, "\xc9" => 2, "\xca" => 2, "\xcb" => 2, "\xcc" => 2, "\xcd" => 2, "\xce" => 2, "\xcf" => 2, + "\xd0" => 2, "\xd1" => 2, "\xd2" => 2, "\xd3" => 2, "\xd4" => 2, "\xd5" => 2, "\xd6" => 2, "\xd7" => 2, + "\xd8" => 2, "\xd9" => 2, "\xda" => 2, "\xdb" => 2, "\xdc" => 2, "\xdd" => 2, "\xde" => 2, "\xdf" => 2, + "\xe0" => 3, "\xe1" => 3, "\xe2" => 3, "\xe3" => 3, "\xe4" => 3, "\xe5" => 3, "\xe6" => 3, "\xe7" => 3, + "\xe8" => 3, "\xe9" => 3, "\xea" => 3, "\xeb" => 3, "\xec" => 3, "\xed" => 3, "\xee" => 3, "\xef" => 3, + "\xf0" => 4, "\xf1" => 4, "\xf2" => 4, "\xf3" => 4, "\xf4" => 4, "\xf5" => 4, "\xf6" => 4, "\xf7" => 4, + "\xf8" => 5, "\xf9" => 5, "\xfa" => 5, "\xfb" => 5, "\xfc" => 6, "\xfd" => 6, "\xfe" => 0, "\xff" => 0, + ]; - /** - * Returns the complete character map. - * - * @param string $string - * @param int $startOffset - * @param array $currentMap - * @param mixed $ignoredChars - * - * @return int - */ - public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars) - { - if (!isset($currentMap['i']) || !isset($currentMap['p'])) { - $currentMap['p'] = $currentMap['i'] = []; - } + /** + * Returns the complete character map. + * + * @param string $string + * @param int $startOffset + * @param array $currentMap + * @param mixed $ignoredChars + * + * @return int + */ + public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars) + { + if (!isset($currentMap['i']) || !isset($currentMap['p'])) { + $currentMap['p'] = $currentMap['i'] = []; + } - $strlen = \strlen($string); - $charPos = \count($currentMap['p']); - $foundChars = 0; - $invalid = false; - for ($i = 0; $i < $strlen; ++$i) { - $char = $string[$i]; - $size = self::$s_length_map[$char]; - if (0 == $size) { - /* char is invalid, we must wait for a resync */ - $invalid = true; - continue; - } else { - if (true === $invalid) { - /* We mark the chars as invalid and start a new char */ - $currentMap['p'][$charPos + $foundChars] = $startOffset + $i; - $currentMap['i'][$charPos + $foundChars] = true; - ++$foundChars; - $invalid = false; - } - if (($i + $size) > $strlen) { - $ignoredChars = substr($string, $i); - break; - } - for ($j = 1; $j < $size; ++$j) { - $char = $string[$i + $j]; - if ($char > "\x7F" && $char < "\xC0") { - // Valid - continue parsing - } else { - /* char is invalid, we must wait for a resync */ - $invalid = true; - continue 2; - } - } - /* Ok we got a complete char here */ - $currentMap['p'][$charPos + $foundChars] = $startOffset + $i + $size; - $i += $j - 1; - ++$foundChars; - } - } + $strlen = \strlen($string); + $charPos = \count($currentMap['p']); + $foundChars = 0; + $invalid = false; + for ($i = 0; $i < $strlen; ++$i) { + $char = $string[$i]; + $size = self::$s_length_map[$char]; + if (0 == $size) { + /* char is invalid, we must wait for a resync */ + $invalid = true; + continue; + } else { + if (true === $invalid) { + /* We mark the chars as invalid and start a new char */ + $currentMap['p'][$charPos + $foundChars] = $startOffset + $i; + $currentMap['i'][$charPos + $foundChars] = true; + ++$foundChars; + $invalid = false; + } + if (($i + $size) > $strlen) { + $ignoredChars = substr($string, $i); + break; + } + for ($j = 1; $j < $size; ++$j) { + $char = $string[$i + $j]; + if ($char > "\x7F" && $char < "\xC0") { + // Valid - continue parsing + } else { + /* char is invalid, we must wait for a resync */ + $invalid = true; + continue 2; + } + } + /* Ok we got a complete char here */ + $currentMap['p'][$charPos + $foundChars] = $startOffset + $i + $size; + $i += $j - 1; + ++$foundChars; + } + } - return $foundChars; - } + return $foundChars; + } - /** - * Returns mapType. - * - * @return int mapType - */ - public function getMapType() - { - return self::MAP_TYPE_POSITIONS; - } + /** + * Returns mapType. + * + * @return int mapType + */ + public function getMapType() + { + return self::MAP_TYPE_POSITIONS; + } - /** - * Returns an integer which specifies how many more bytes to read. - * - * A positive integer indicates the number of more bytes to fetch before invoking - * this method again. - * A value of zero means this is already a valid character. - * A value of -1 means this cannot possibly be a valid character. - * - * @param string $bytes - * @param int $size - * - * @return int - */ - public function validateByteSequence($bytes, $size) - { - if ($size < 1) { - return -1; - } - $needed = self::$length_map[$bytes[0]] - $size; + /** + * Returns an integer which specifies how many more bytes to read. + * + * A positive integer indicates the number of more bytes to fetch before invoking + * this method again. + * A value of zero means this is already a valid character. + * A value of -1 means this cannot possibly be a valid character. + * + * @param string $bytes + * @param int $size + * + * @return int + */ + public function validateByteSequence($bytes, $size) + { + if ($size < 1) { + return -1; + } + $needed = self::$length_map[$bytes[0]] - $size; - return $needed > -1 ? $needed : -1; - } + return $needed > -1 ? $needed : -1; + } - /** - * Returns the number of bytes which should be read to start each character. - * - * @return int - */ - public function getInitialByteSize() - { - return 1; - } + /** + * Returns the number of bytes which should be read to start each character. + * + * @return int + */ + public function getInitialByteSize() + { + return 1; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReaderFactory/SimpleCharacterReaderFactory.php b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReaderFactory/SimpleCharacterReaderFactory.php index 97b3b097f3d..86900894ab1 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReaderFactory/SimpleCharacterReaderFactory.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterReaderFactory/SimpleCharacterReaderFactory.php @@ -15,110 +15,110 @@ */ class Swift_CharacterReaderFactory_SimpleCharacterReaderFactory implements Swift_CharacterReaderFactory { - /** - * A map of charset patterns to their implementation classes. - * - * @var array - */ - private static $map = []; + /** + * A map of charset patterns to their implementation classes. + * + * @var array + */ + private static $map = []; - /** - * Factories which have already been loaded. - * - * @var Swift_CharacterReaderFactory[] - */ - private static $loaded = []; + /** + * Factories which have already been loaded. + * + * @var Swift_CharacterReaderFactory[] + */ + private static $loaded = []; - /** - * Creates a new CharacterReaderFactory. - */ - public function __construct() - { - $this->init(); - } + /** + * Creates a new CharacterReaderFactory. + */ + public function __construct() + { + $this->init(); + } - public function __wakeup() - { - $this->init(); - } + public function __wakeup() + { + $this->init(); + } - public function init() - { - if (\count(self::$map) > 0) { - return; - } + public function init() + { + if (\count(self::$map) > 0) { + return; + } - $prefix = 'Swift_CharacterReader_'; + $prefix = 'Swift_CharacterReader_'; - $singleByte = [ - 'class' => $prefix.'GenericFixedWidthReader', - 'constructor' => [1], - ]; + $singleByte = [ + 'class' => $prefix.'GenericFixedWidthReader', + 'constructor' => [1], + ]; - $doubleByte = [ - 'class' => $prefix.'GenericFixedWidthReader', - 'constructor' => [2], - ]; + $doubleByte = [ + 'class' => $prefix.'GenericFixedWidthReader', + 'constructor' => [2], + ]; - $fourBytes = [ - 'class' => $prefix.'GenericFixedWidthReader', - 'constructor' => [4], - ]; + $fourBytes = [ + 'class' => $prefix.'GenericFixedWidthReader', + 'constructor' => [4], + ]; - // Utf-8 - self::$map['utf-?8'] = [ - 'class' => $prefix.'Utf8Reader', - 'constructor' => [], - ]; + // Utf-8 + self::$map['utf-?8'] = [ + 'class' => $prefix.'Utf8Reader', + 'constructor' => [], + ]; - //7-8 bit charsets - self::$map['(us-)?ascii'] = $singleByte; - self::$map['(iso|iec)-?8859-?[0-9]+'] = $singleByte; - self::$map['windows-?125[0-9]'] = $singleByte; - self::$map['cp-?[0-9]+'] = $singleByte; - self::$map['ansi'] = $singleByte; - self::$map['macintosh'] = $singleByte; - self::$map['koi-?7'] = $singleByte; - self::$map['koi-?8-?.+'] = $singleByte; - self::$map['mik'] = $singleByte; - self::$map['(cork|t1)'] = $singleByte; - self::$map['v?iscii'] = $singleByte; + //7-8 bit charsets + self::$map['(us-)?ascii'] = $singleByte; + self::$map['(iso|iec)-?8859-?[0-9]+'] = $singleByte; + self::$map['windows-?125[0-9]'] = $singleByte; + self::$map['cp-?[0-9]+'] = $singleByte; + self::$map['ansi'] = $singleByte; + self::$map['macintosh'] = $singleByte; + self::$map['koi-?7'] = $singleByte; + self::$map['koi-?8-?.+'] = $singleByte; + self::$map['mik'] = $singleByte; + self::$map['(cork|t1)'] = $singleByte; + self::$map['v?iscii'] = $singleByte; - //16 bits - self::$map['(ucs-?2|utf-?16)'] = $doubleByte; + //16 bits + self::$map['(ucs-?2|utf-?16)'] = $doubleByte; - //32 bits - self::$map['(ucs-?4|utf-?32)'] = $fourBytes; + //32 bits + self::$map['(ucs-?4|utf-?32)'] = $fourBytes; - // Fallback - self::$map['.*'] = $singleByte; - } + // Fallback + self::$map['.*'] = $singleByte; + } - /** - * Returns a CharacterReader suitable for the charset applied. - * - * @param string $charset - * - * @return Swift_CharacterReader - */ - public function getReaderFor($charset) - { - $charset = strtolower(trim($charset ?? '')); - foreach (self::$map as $pattern => $spec) { - $re = '/^'.$pattern.'$/D'; - if (preg_match($re, $charset)) { - if (!\array_key_exists($pattern, self::$loaded)) { - $reflector = new ReflectionClass($spec['class']); - if ($reflector->getConstructor()) { - $reader = $reflector->newInstanceArgs($spec['constructor']); - } else { - $reader = $reflector->newInstance(); - } - self::$loaded[$pattern] = $reader; - } + /** + * Returns a CharacterReader suitable for the charset applied. + * + * @param string $charset + * + * @return Swift_CharacterReader + */ + public function getReaderFor($charset) + { + $charset = strtolower(trim($charset ?? '')); + foreach (self::$map as $pattern => $spec) { + $re = '/^'.$pattern.'$/D'; + if (preg_match($re, $charset)) { + if (!\array_key_exists($pattern, self::$loaded)) { + $reflector = new ReflectionClass($spec['class']); + if ($reflector->getConstructor()) { + $reader = $reflector->newInstanceArgs($spec['constructor']); + } else { + $reader = $reflector->newInstance(); + } + self::$loaded[$pattern] = $reader; + } - return self::$loaded[$pattern]; - } - } - } + return self::$loaded[$pattern]; + } + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterStream.php b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterStream.php index 04e2d433934..c9d8a078ee0 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterStream.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterStream.php @@ -19,69 +19,69 @@ */ interface Swift_CharacterStream { - /** - * Set the character set used in this CharacterStream. - * - * @param string $charset - */ - public function setCharacterSet($charset); + /** + * Set the character set used in this CharacterStream. + * + * @param string $charset + */ + public function setCharacterSet($charset); - /** - * Set the CharacterReaderFactory for multi charset support. - */ - public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory); + /** + * Set the CharacterReaderFactory for multi charset support. + */ + public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory); - /** - * Overwrite this character stream using the byte sequence in the byte stream. - * - * @param Swift_OutputByteStream $os output stream to read from - */ - public function importByteStream(Swift_OutputByteStream $os); + /** + * Overwrite this character stream using the byte sequence in the byte stream. + * + * @param Swift_OutputByteStream $os output stream to read from + */ + public function importByteStream(Swift_OutputByteStream $os); - /** - * Import a string a bytes into this CharacterStream, overwriting any existing - * data in the stream. - * - * @param string $string - */ - public function importString($string); + /** + * Import a string a bytes into this CharacterStream, overwriting any existing + * data in the stream. + * + * @param string $string + */ + public function importString($string); - /** - * Read $length characters from the stream and move the internal pointer - * $length further into the stream. - * - * @param int $length - * - * @return string - */ - public function read($length); + /** + * Read $length characters from the stream and move the internal pointer + * $length further into the stream. + * + * @param int $length + * + * @return string + */ + public function read($length); - /** - * Read $length characters from the stream and return a 1-dimensional array - * containing there octet values. - * - * @param int $length - * - * @return int[] - */ - public function readBytes($length); + /** + * Read $length characters from the stream and return a 1-dimensional array + * containing there octet values. + * + * @param int $length + * + * @return int[] + */ + public function readBytes($length); - /** - * Write $chars to the end of the stream. - * - * @param string $chars - */ - public function write($chars); + /** + * Write $chars to the end of the stream. + * + * @param string $chars + */ + public function write($chars); - /** - * Move the internal pointer to $charOffset in the stream. - * - * @param int $charOffset - */ - public function setPointer($charOffset); + /** + * Move the internal pointer to $charOffset in the stream. + * + * @param int $charOffset + */ + public function setPointer($charOffset); - /** - * Empty the stream and reset the internal pointer. - */ - public function flushContents(); + /** + * Empty the stream and reset the internal pointer. + */ + public function flushContents(); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterStream/ArrayCharacterStream.php b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterStream/ArrayCharacterStream.php index 6f6a22e393e..5c2869455b8 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterStream/ArrayCharacterStream.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterStream/ArrayCharacterStream.php @@ -15,277 +15,277 @@ */ class Swift_CharacterStream_ArrayCharacterStream implements Swift_CharacterStream { - /** A map of byte values and their respective characters */ - private static $charMap; + /** A map of byte values and their respective characters */ + private static $charMap; - /** A map of characters and their derivative byte values */ - private static $byteMap; + /** A map of characters and their derivative byte values */ + private static $byteMap; - /** The char reader (lazy-loaded) for the current charset */ - private $charReader; + /** The char reader (lazy-loaded) for the current charset */ + private $charReader; - /** A factory for creating CharacterReader instances */ - private $charReaderFactory; + /** A factory for creating CharacterReader instances */ + private $charReaderFactory; - /** The character set this stream is using */ - private $charset; + /** The character set this stream is using */ + private $charset; - /** Array of characters */ - private $array = []; + /** Array of characters */ + private $array = []; - /** Size of the array of character */ - private $array_size = []; + /** Size of the array of character */ + private $array_size = []; - /** The current character offset in the stream */ - private $offset = 0; + /** The current character offset in the stream */ + private $offset = 0; - /** - * Create a new CharacterStream with the given $chars, if set. - * - * @param Swift_CharacterReaderFactory $factory for loading validators - * @param string $charset used in the stream - */ - public function __construct(Swift_CharacterReaderFactory $factory, $charset) - { - self::initializeMaps(); - $this->setCharacterReaderFactory($factory); - $this->setCharacterSet($charset); - } + /** + * Create a new CharacterStream with the given $chars, if set. + * + * @param Swift_CharacterReaderFactory $factory for loading validators + * @param string $charset used in the stream + */ + public function __construct(Swift_CharacterReaderFactory $factory, $charset) + { + self::initializeMaps(); + $this->setCharacterReaderFactory($factory); + $this->setCharacterSet($charset); + } - /** - * Set the character set used in this CharacterStream. - * - * @param string $charset - */ - public function setCharacterSet($charset) - { - $this->charset = $charset; - $this->charReader = null; - } + /** + * Set the character set used in this CharacterStream. + * + * @param string $charset + */ + public function setCharacterSet($charset) + { + $this->charset = $charset; + $this->charReader = null; + } - /** - * Set the CharacterReaderFactory for multi charset support. - */ - public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory) - { - $this->charReaderFactory = $factory; - } + /** + * Set the CharacterReaderFactory for multi charset support. + */ + public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory) + { + $this->charReaderFactory = $factory; + } - /** - * Overwrite this character stream using the byte sequence in the byte stream. - * - * @param Swift_OutputByteStream $os output stream to read from - */ - public function importByteStream(Swift_OutputByteStream $os) - { - if (!isset($this->charReader)) { - $this->charReader = $this->charReaderFactory - ->getReaderFor($this->charset); - } + /** + * Overwrite this character stream using the byte sequence in the byte stream. + * + * @param Swift_OutputByteStream $os output stream to read from + */ + public function importByteStream(Swift_OutputByteStream $os) + { + if (!isset($this->charReader)) { + $this->charReader = $this->charReaderFactory + ->getReaderFor($this->charset); + } - $startLength = $this->charReader->getInitialByteSize(); - while (false !== $bytes = $os->read($startLength)) { - $c = []; - for ($i = 0, $len = \strlen($bytes); $i < $len; ++$i) { - $c[] = self::$byteMap[$bytes[$i]]; - } - $size = \count($c); - $need = $this->charReader - ->validateByteSequence($c, $size); - if ($need > 0 && - false !== $bytes = $os->read($need)) { - for ($i = 0, $len = \strlen($bytes); $i < $len; ++$i) { - $c[] = self::$byteMap[$bytes[$i]]; - } - } - $this->array[] = $c; - ++$this->array_size; - } - } + $startLength = $this->charReader->getInitialByteSize(); + while (false !== $bytes = $os->read($startLength)) { + $c = []; + for ($i = 0, $len = \strlen($bytes); $i < $len; ++$i) { + $c[] = self::$byteMap[$bytes[$i]]; + } + $size = \count($c); + $need = $this->charReader + ->validateByteSequence($c, $size); + if ($need > 0 && + false !== $bytes = $os->read($need)) { + for ($i = 0, $len = \strlen($bytes); $i < $len; ++$i) { + $c[] = self::$byteMap[$bytes[$i]]; + } + } + $this->array[] = $c; + ++$this->array_size; + } + } - /** - * Import a string a bytes into this CharacterStream, overwriting any existing - * data in the stream. - * - * @param string $string - */ - public function importString($string) - { - $this->flushContents(); - $this->write($string); - } + /** + * Import a string a bytes into this CharacterStream, overwriting any existing + * data in the stream. + * + * @param string $string + */ + public function importString($string) + { + $this->flushContents(); + $this->write($string); + } - /** - * Read $length characters from the stream and move the internal pointer - * $length further into the stream. - * - * @param int $length - * - * @return string - */ - public function read($length) - { - if ($this->offset == $this->array_size) { - return false; - } + /** + * Read $length characters from the stream and move the internal pointer + * $length further into the stream. + * + * @param int $length + * + * @return string + */ + public function read($length) + { + if ($this->offset == $this->array_size) { + return false; + } - // Don't use array slice - $arrays = []; - $end = $length + $this->offset; - for ($i = $this->offset; $i < $end; ++$i) { - if (!isset($this->array[$i])) { - break; - } - $arrays[] = $this->array[$i]; - } - $this->offset += $i - $this->offset; // Limit function calls - $chars = false; - foreach ($arrays as $array) { - $chars .= implode('', array_map('chr', $array)); - } + // Don't use array slice + $arrays = []; + $end = $length + $this->offset; + for ($i = $this->offset; $i < $end; ++$i) { + if (!isset($this->array[$i])) { + break; + } + $arrays[] = $this->array[$i]; + } + $this->offset += $i - $this->offset; // Limit function calls + $chars = false; + foreach ($arrays as $array) { + $chars .= implode('', array_map('chr', $array)); + } - return $chars; - } + return $chars; + } - /** - * Read $length characters from the stream and return a 1-dimensional array - * containing there octet values. - * - * @param int $length - * - * @return int[] - */ - public function readBytes($length) - { - if ($this->offset == $this->array_size) { - return false; - } - $arrays = []; - $end = $length + $this->offset; - for ($i = $this->offset; $i < $end; ++$i) { - if (!isset($this->array[$i])) { - break; - } - $arrays[] = $this->array[$i]; - } - $this->offset += ($i - $this->offset); // Limit function calls + /** + * Read $length characters from the stream and return a 1-dimensional array + * containing there octet values. + * + * @param int $length + * + * @return int[] + */ + public function readBytes($length) + { + if ($this->offset == $this->array_size) { + return false; + } + $arrays = []; + $end = $length + $this->offset; + for ($i = $this->offset; $i < $end; ++$i) { + if (!isset($this->array[$i])) { + break; + } + $arrays[] = $this->array[$i]; + } + $this->offset += ($i - $this->offset); // Limit function calls - return array_merge(...$arrays); - } + return array_merge(...$arrays); + } - /** - * Write $chars to the end of the stream. - * - * @param string $chars - */ - public function write($chars) - { - if (!isset($this->charReader)) { - $this->charReader = $this->charReaderFactory->getReaderFor( - $this->charset); - } + /** + * Write $chars to the end of the stream. + * + * @param string $chars + */ + public function write($chars) + { + if (!isset($this->charReader)) { + $this->charReader = $this->charReaderFactory->getReaderFor( + $this->charset); + } - $startLength = $this->charReader->getInitialByteSize(); + $startLength = $this->charReader->getInitialByteSize(); - $fp = fopen('php://memory', 'w+b'); - fwrite($fp, $chars); - unset($chars); - fseek($fp, 0, SEEK_SET); + $fp = fopen('php://memory', 'w+b'); + fwrite($fp, $chars); + unset($chars); + fseek($fp, 0, SEEK_SET); - $buffer = [0]; - $buf_pos = 1; - $buf_len = 1; - $has_datas = true; - do { - $bytes = []; - // Buffer Filing - if ($buf_len - $buf_pos < $startLength) { - $buf = array_splice($buffer, $buf_pos); - $new = $this->reloadBuffer($fp, 100); - if ($new) { - $buffer = array_merge($buf, $new); - $buf_len = \count($buffer); - $buf_pos = 0; - } else { - $has_datas = false; - } - } - if ($buf_len - $buf_pos > 0) { - $size = 0; - for ($i = 0; $i < $startLength && isset($buffer[$buf_pos]); ++$i) { - ++$size; - $bytes[] = $buffer[$buf_pos++]; - } - $need = $this->charReader->validateByteSequence( - $bytes, $size); - if ($need > 0) { - if ($buf_len - $buf_pos < $need) { - $new = $this->reloadBuffer($fp, $need); + $buffer = [0]; + $buf_pos = 1; + $buf_len = 1; + $has_datas = true; + do { + $bytes = []; + // Buffer Filing + if ($buf_len - $buf_pos < $startLength) { + $buf = array_splice($buffer, $buf_pos); + $new = $this->reloadBuffer($fp, 100); + if ($new) { + $buffer = array_merge($buf, $new); + $buf_len = \count($buffer); + $buf_pos = 0; + } else { + $has_datas = false; + } + } + if ($buf_len - $buf_pos > 0) { + $size = 0; + for ($i = 0; $i < $startLength && isset($buffer[$buf_pos]); ++$i) { + ++$size; + $bytes[] = $buffer[$buf_pos++]; + } + $need = $this->charReader->validateByteSequence( + $bytes, $size); + if ($need > 0) { + if ($buf_len - $buf_pos < $need) { + $new = $this->reloadBuffer($fp, $need); - if ($new) { - $buffer = array_merge($buffer, $new); - $buf_len = \count($buffer); - } - } - for ($i = 0; $i < $need && isset($buffer[$buf_pos]); ++$i) { - $bytes[] = $buffer[$buf_pos++]; - } - } - $this->array[] = $bytes; - ++$this->array_size; - } - } while ($has_datas); + if ($new) { + $buffer = array_merge($buffer, $new); + $buf_len = \count($buffer); + } + } + for ($i = 0; $i < $need && isset($buffer[$buf_pos]); ++$i) { + $bytes[] = $buffer[$buf_pos++]; + } + } + $this->array[] = $bytes; + ++$this->array_size; + } + } while ($has_datas); - fclose($fp); - } + fclose($fp); + } - /** - * Move the internal pointer to $charOffset in the stream. - * - * @param int $charOffset - */ - public function setPointer($charOffset) - { - if ($charOffset > $this->array_size) { - $charOffset = $this->array_size; - } elseif ($charOffset < 0) { - $charOffset = 0; - } - $this->offset = $charOffset; - } + /** + * Move the internal pointer to $charOffset in the stream. + * + * @param int $charOffset + */ + public function setPointer($charOffset) + { + if ($charOffset > $this->array_size) { + $charOffset = $this->array_size; + } elseif ($charOffset < 0) { + $charOffset = 0; + } + $this->offset = $charOffset; + } - /** - * Empty the stream and reset the internal pointer. - */ - public function flushContents() - { - $this->offset = 0; - $this->array = []; - $this->array_size = 0; - } + /** + * Empty the stream and reset the internal pointer. + */ + public function flushContents() + { + $this->offset = 0; + $this->array = []; + $this->array_size = 0; + } - private function reloadBuffer($fp, $len) - { - if (!feof($fp) && false !== ($bytes = fread($fp, $len))) { - $buf = []; - for ($i = 0, $len = \strlen($bytes); $i < $len; ++$i) { - $buf[] = self::$byteMap[$bytes[$i]]; - } + private function reloadBuffer($fp, $len) + { + if (!feof($fp) && false !== ($bytes = fread($fp, $len))) { + $buf = []; + for ($i = 0, $len = \strlen($bytes); $i < $len; ++$i) { + $buf[] = self::$byteMap[$bytes[$i]]; + } - return $buf; - } + return $buf; + } - return false; - } + return false; + } - private static function initializeMaps() - { - if (!isset(self::$charMap)) { - self::$charMap = []; - for ($byte = 0; $byte < 256; ++$byte) { - self::$charMap[$byte] = \chr($byte); - } - self::$byteMap = array_flip(self::$charMap); - } - } + private static function initializeMaps() + { + if (!isset(self::$charMap)) { + self::$charMap = []; + for ($byte = 0; $byte < 256; ++$byte) { + self::$charMap[$byte] = \chr($byte); + } + self::$byteMap = array_flip(self::$charMap); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterStream/NgCharacterStream.php b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterStream/NgCharacterStream.php index d7110ff16ef..7578dda9cac 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterStream/NgCharacterStream.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/CharacterStream/NgCharacterStream.php @@ -15,248 +15,248 @@ */ class Swift_CharacterStream_NgCharacterStream implements Swift_CharacterStream { - /** - * The char reader (lazy-loaded) for the current charset. - * - * @var Swift_CharacterReader - */ - private $charReader; + /** + * The char reader (lazy-loaded) for the current charset. + * + * @var Swift_CharacterReader + */ + private $charReader; - /** - * A factory for creating CharacterReader instances. - * - * @var Swift_CharacterReaderFactory - */ - private $charReaderFactory; + /** + * A factory for creating CharacterReader instances. + * + * @var Swift_CharacterReaderFactory + */ + private $charReaderFactory; - /** - * The character set this stream is using. - * - * @var string - */ - private $charset; + /** + * The character set this stream is using. + * + * @var string + */ + private $charset; - /** - * The data's stored as-is. - * - * @var string - */ - private $datas = ''; + /** + * The data's stored as-is. + * + * @var string + */ + private $datas = ''; - /** - * Number of bytes in the stream. - * - * @var int - */ - private $datasSize = 0; + /** + * Number of bytes in the stream. + * + * @var int + */ + private $datasSize = 0; - /** - * Map. - * - * @var mixed - */ - private $map; + /** + * Map. + * + * @var mixed + */ + private $map; - /** - * Map Type. - * - * @var int - */ - private $mapType = 0; + /** + * Map Type. + * + * @var int + */ + private $mapType = 0; - /** - * Number of characters in the stream. - * - * @var int - */ - private $charCount = 0; + /** + * Number of characters in the stream. + * + * @var int + */ + private $charCount = 0; - /** - * Position in the stream. - * - * @var int - */ - private $currentPos = 0; + /** + * Position in the stream. + * + * @var int + */ + private $currentPos = 0; - /** - * Constructor. - * - * @param string $charset - */ - public function __construct(Swift_CharacterReaderFactory $factory, $charset) - { - $this->setCharacterReaderFactory($factory); - $this->setCharacterSet($charset); - } + /** + * Constructor. + * + * @param string $charset + */ + public function __construct(Swift_CharacterReaderFactory $factory, $charset) + { + $this->setCharacterReaderFactory($factory); + $this->setCharacterSet($charset); + } - /* -- Changing parameters of the stream -- */ + /* -- Changing parameters of the stream -- */ - /** - * Set the character set used in this CharacterStream. - * - * @param string $charset - */ - public function setCharacterSet($charset) - { - $this->charset = $charset; - $this->charReader = null; - $this->mapType = 0; - } + /** + * Set the character set used in this CharacterStream. + * + * @param string $charset + */ + public function setCharacterSet($charset) + { + $this->charset = $charset; + $this->charReader = null; + $this->mapType = 0; + } - /** - * Set the CharacterReaderFactory for multi charset support. - */ - public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory) - { - $this->charReaderFactory = $factory; - } + /** + * Set the CharacterReaderFactory for multi charset support. + */ + public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory) + { + $this->charReaderFactory = $factory; + } - /** - * @see Swift_CharacterStream::flushContents() - */ - public function flushContents() - { - $this->datas = null; - $this->map = null; - $this->charCount = 0; - $this->currentPos = 0; - $this->datasSize = 0; - } + /** + * @see Swift_CharacterStream::flushContents() + */ + public function flushContents() + { + $this->datas = null; + $this->map = null; + $this->charCount = 0; + $this->currentPos = 0; + $this->datasSize = 0; + } - /** - * @see Swift_CharacterStream::importByteStream() - */ - public function importByteStream(Swift_OutputByteStream $os) - { - $this->flushContents(); - $blocks = 512; - $os->setReadPointer(0); - while (false !== ($read = $os->read($blocks))) { - $this->write($read); - } - } + /** + * @see Swift_CharacterStream::importByteStream() + */ + public function importByteStream(Swift_OutputByteStream $os) + { + $this->flushContents(); + $blocks = 512; + $os->setReadPointer(0); + while (false !== ($read = $os->read($blocks))) { + $this->write($read); + } + } - /** - * @see Swift_CharacterStream::importString() - * - * @param string $string - */ - public function importString($string) - { - $this->flushContents(); - $this->write($string); - } + /** + * @see Swift_CharacterStream::importString() + * + * @param string $string + */ + public function importString($string) + { + $this->flushContents(); + $this->write($string); + } - /** - * @see Swift_CharacterStream::read() - * - * @param int $length - * - * @return string - */ - public function read($length) - { - if ($this->currentPos >= $this->charCount) { - return false; - } - $ret = false; - $length = ($this->currentPos + $length > $this->charCount) ? $this->charCount - $this->currentPos : $length; - switch ($this->mapType) { - case Swift_CharacterReader::MAP_TYPE_FIXED_LEN: - $len = $length * $this->map; - $ret = substr($this->datas, - $this->currentPos * $this->map, - $len); - $this->currentPos += $length; - break; + /** + * @see Swift_CharacterStream::read() + * + * @param int $length + * + * @return string + */ + public function read($length) + { + if ($this->currentPos >= $this->charCount) { + return false; + } + $ret = false; + $length = ($this->currentPos + $length > $this->charCount) ? $this->charCount - $this->currentPos : $length; + switch ($this->mapType) { + case Swift_CharacterReader::MAP_TYPE_FIXED_LEN: + $len = $length * $this->map; + $ret = substr($this->datas, + $this->currentPos * $this->map, + $len); + $this->currentPos += $length; + break; - case Swift_CharacterReader::MAP_TYPE_INVALID: - $ret = ''; - for (; $this->currentPos < $length; ++$this->currentPos) { - if (isset($this->map[$this->currentPos])) { - $ret .= '?'; - } else { - $ret .= $this->datas[$this->currentPos]; - } - } - break; + case Swift_CharacterReader::MAP_TYPE_INVALID: + $ret = ''; + for (; $this->currentPos < $length; ++$this->currentPos) { + if (isset($this->map[$this->currentPos])) { + $ret .= '?'; + } else { + $ret .= $this->datas[$this->currentPos]; + } + } + break; - case Swift_CharacterReader::MAP_TYPE_POSITIONS: - $end = $this->currentPos + $length; - $end = $end > $this->charCount ? $this->charCount : $end; - $ret = ''; - $start = 0; - if ($this->currentPos > 0) { - $start = $this->map['p'][$this->currentPos - 1]; - } - $to = $start; - for (; $this->currentPos < $end; ++$this->currentPos) { - if (isset($this->map['i'][$this->currentPos])) { - $ret .= substr($this->datas, $start, $to - $start).'?'; - $start = $this->map['p'][$this->currentPos]; - } else { - $to = $this->map['p'][$this->currentPos]; - } - } - $ret .= substr($this->datas, $start, $to - $start); - break; - } + case Swift_CharacterReader::MAP_TYPE_POSITIONS: + $end = $this->currentPos + $length; + $end = $end > $this->charCount ? $this->charCount : $end; + $ret = ''; + $start = 0; + if ($this->currentPos > 0) { + $start = $this->map['p'][$this->currentPos - 1]; + } + $to = $start; + for (; $this->currentPos < $end; ++$this->currentPos) { + if (isset($this->map['i'][$this->currentPos])) { + $ret .= substr($this->datas, $start, $to - $start).'?'; + $start = $this->map['p'][$this->currentPos]; + } else { + $to = $this->map['p'][$this->currentPos]; + } + } + $ret .= substr($this->datas, $start, $to - $start); + break; + } - return $ret; - } + return $ret; + } - /** - * @see Swift_CharacterStream::readBytes() - * - * @param int $length - * - * @return int[] - */ - public function readBytes($length) - { - $read = $this->read($length); - if (false !== $read) { - $ret = array_map('ord', str_split($read, 1)); + /** + * @see Swift_CharacterStream::readBytes() + * + * @param int $length + * + * @return int[] + */ + public function readBytes($length) + { + $read = $this->read($length); + if (false !== $read) { + $ret = array_map('ord', str_split($read, 1)); - return $ret; - } + return $ret; + } - return false; - } + return false; + } - /** - * @see Swift_CharacterStream::setPointer() - * - * @param int $charOffset - */ - public function setPointer($charOffset) - { - if ($this->charCount < $charOffset) { - $charOffset = $this->charCount; - } - $this->currentPos = $charOffset; - } + /** + * @see Swift_CharacterStream::setPointer() + * + * @param int $charOffset + */ + public function setPointer($charOffset) + { + if ($this->charCount < $charOffset) { + $charOffset = $this->charCount; + } + $this->currentPos = $charOffset; + } - /** - * @see Swift_CharacterStream::write() - * - * @param string $chars - */ - public function write($chars) - { - if (!isset($this->charReader)) { - $this->charReader = $this->charReaderFactory->getReaderFor( - $this->charset); - $this->map = []; - $this->mapType = $this->charReader->getMapType(); - } - $ignored = ''; - $this->datas .= $chars; - $this->charCount += $this->charReader->getCharPositions(substr($this->datas, $this->datasSize), $this->datasSize, $this->map, $ignored); - if (false !== $ignored) { - $this->datasSize = \strlen($this->datas) - \strlen($ignored); - } else { - $this->datasSize = \strlen($this->datas); - } - } + /** + * @see Swift_CharacterStream::write() + * + * @param string $chars + */ + public function write($chars) + { + if (!isset($this->charReader)) { + $this->charReader = $this->charReaderFactory->getReaderFor( + $this->charset); + $this->map = []; + $this->mapType = $this->charReader->getMapType(); + } + $ignored = ''; + $this->datas .= $chars; + $this->charCount += $this->charReader->getCharPositions(substr($this->datas, $this->datasSize), $this->datasSize, $this->map, $ignored); + if (false !== $ignored) { + $this->datasSize = \strlen($this->datas) - \strlen($ignored); + } else { + $this->datasSize = \strlen($this->datas); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/DependencyContainer.php b/htdocs/includes/swiftmailer/lib/classes/Swift/DependencyContainer.php index c617290d311..3cc885ec03b 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/DependencyContainer.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/DependencyContainer.php @@ -15,373 +15,373 @@ */ class Swift_DependencyContainer { - /** Constant for literal value types */ - const TYPE_VALUE = 0x00001; + /** Constant for literal value types */ + const TYPE_VALUE = 0x00001; - /** Constant for new instance types */ - const TYPE_INSTANCE = 0x00010; + /** Constant for new instance types */ + const TYPE_INSTANCE = 0x00010; - /** Constant for shared instance types */ - const TYPE_SHARED = 0x00100; + /** Constant for shared instance types */ + const TYPE_SHARED = 0x00100; - /** Constant for aliases */ - const TYPE_ALIAS = 0x01000; + /** Constant for aliases */ + const TYPE_ALIAS = 0x01000; - /** Constant for arrays */ - const TYPE_ARRAY = 0x10000; + /** Constant for arrays */ + const TYPE_ARRAY = 0x10000; - /** Singleton instance */ - private static $instance = null; + /** Singleton instance */ + private static $instance = null; - /** The data container */ - private $store = []; + /** The data container */ + private $store = []; - /** The current endpoint in the data container */ - private $endPoint; + /** The current endpoint in the data container */ + private $endPoint; - /** - * Constructor should not be used. - * - * Use {@link getInstance()} instead. - */ - public function __construct() - { - } + /** + * Constructor should not be used. + * + * Use {@link getInstance()} instead. + */ + public function __construct() + { + } - /** - * Returns a singleton of the DependencyContainer. - * - * @return self - */ - public static function getInstance() - { - if (!isset(self::$instance)) { - self::$instance = new self(); - } + /** + * Returns a singleton of the DependencyContainer. + * + * @return self + */ + public static function getInstance() + { + if (!isset(self::$instance)) { + self::$instance = new self(); + } - return self::$instance; - } + return self::$instance; + } - /** - * List the names of all items stored in the Container. - * - * @return array - */ - public function listItems() - { - return array_keys($this->store); - } + /** + * List the names of all items stored in the Container. + * + * @return array + */ + public function listItems() + { + return array_keys($this->store); + } - /** - * Test if an item is registered in this container with the given name. - * - * @see register() - * - * @param string $itemName - * - * @return bool - */ - public function has($itemName) - { - return \array_key_exists($itemName, $this->store) - && isset($this->store[$itemName]['lookupType']); - } + /** + * Test if an item is registered in this container with the given name. + * + * @see register() + * + * @param string $itemName + * + * @return bool + */ + public function has($itemName) + { + return \array_key_exists($itemName, $this->store) + && isset($this->store[$itemName]['lookupType']); + } - /** - * Lookup the item with the given $itemName. - * - * @see register() - * - * @param string $itemName - * - * @return mixed - * - * @throws Swift_DependencyException If the dependency is not found - */ - public function lookup($itemName) - { - if (!$this->has($itemName)) { - throw new Swift_DependencyException('Cannot lookup dependency "'.$itemName.'" since it is not registered.'); - } + /** + * Lookup the item with the given $itemName. + * + * @see register() + * + * @param string $itemName + * + * @return mixed + * + * @throws Swift_DependencyException If the dependency is not found + */ + public function lookup($itemName) + { + if (!$this->has($itemName)) { + throw new Swift_DependencyException('Cannot lookup dependency "'.$itemName.'" since it is not registered.'); + } - switch ($this->store[$itemName]['lookupType']) { - case self::TYPE_ALIAS: - return $this->createAlias($itemName); - case self::TYPE_VALUE: - return $this->getValue($itemName); - case self::TYPE_INSTANCE: - return $this->createNewInstance($itemName); - case self::TYPE_SHARED: - return $this->createSharedInstance($itemName); - case self::TYPE_ARRAY: - return $this->createDependenciesFor($itemName); - } - } + switch ($this->store[$itemName]['lookupType']) { + case self::TYPE_ALIAS: + return $this->createAlias($itemName); + case self::TYPE_VALUE: + return $this->getValue($itemName); + case self::TYPE_INSTANCE: + return $this->createNewInstance($itemName); + case self::TYPE_SHARED: + return $this->createSharedInstance($itemName); + case self::TYPE_ARRAY: + return $this->createDependenciesFor($itemName); + } + } - /** - * Create an array of arguments passed to the constructor of $itemName. - * - * @param string $itemName - * - * @return array - */ - public function createDependenciesFor($itemName) - { - $args = []; - if (isset($this->store[$itemName]['args'])) { - $args = $this->resolveArgs($this->store[$itemName]['args']); - } + /** + * Create an array of arguments passed to the constructor of $itemName. + * + * @param string $itemName + * + * @return array + */ + public function createDependenciesFor($itemName) + { + $args = []; + if (isset($this->store[$itemName]['args'])) { + $args = $this->resolveArgs($this->store[$itemName]['args']); + } - return $args; - } + return $args; + } - /** - * Register a new dependency with $itemName. - * - * This method returns the current DependencyContainer instance because it - * requires the use of the fluid interface to set the specific details for the - * dependency. - * - * @see asNewInstanceOf(), asSharedInstanceOf(), asValue() - * - * @param string $itemName - * - * @return $this - */ - public function register($itemName) - { - $this->store[$itemName] = []; - $this->endPoint = &$this->store[$itemName]; + /** + * Register a new dependency with $itemName. + * + * This method returns the current DependencyContainer instance because it + * requires the use of the fluid interface to set the specific details for the + * dependency. + * + * @see asNewInstanceOf(), asSharedInstanceOf(), asValue() + * + * @param string $itemName + * + * @return $this + */ + public function register($itemName) + { + $this->store[$itemName] = []; + $this->endPoint = &$this->store[$itemName]; - return $this; - } + return $this; + } - /** - * Specify the previously registered item as a literal value. - * - * {@link register()} must be called before this will work. - * - * @param mixed $value - * - * @return $this - */ - public function asValue($value) - { - $endPoint = &$this->getEndPoint(); - $endPoint['lookupType'] = self::TYPE_VALUE; - $endPoint['value'] = $value; + /** + * Specify the previously registered item as a literal value. + * + * {@link register()} must be called before this will work. + * + * @param mixed $value + * + * @return $this + */ + public function asValue($value) + { + $endPoint = &$this->getEndPoint(); + $endPoint['lookupType'] = self::TYPE_VALUE; + $endPoint['value'] = $value; - return $this; - } + return $this; + } - /** - * Specify the previously registered item as an alias of another item. - * - * @param string $lookup - * - * @return $this - */ - public function asAliasOf($lookup) - { - $endPoint = &$this->getEndPoint(); - $endPoint['lookupType'] = self::TYPE_ALIAS; - $endPoint['ref'] = $lookup; + /** + * Specify the previously registered item as an alias of another item. + * + * @param string $lookup + * + * @return $this + */ + public function asAliasOf($lookup) + { + $endPoint = &$this->getEndPoint(); + $endPoint['lookupType'] = self::TYPE_ALIAS; + $endPoint['ref'] = $lookup; - return $this; - } + return $this; + } - /** - * Specify the previously registered item as a new instance of $className. - * - * {@link register()} must be called before this will work. - * Any arguments can be set with {@link withDependencies()}, - * {@link addConstructorValue()} or {@link addConstructorLookup()}. - * - * @see withDependencies(), addConstructorValue(), addConstructorLookup() - * - * @param string $className - * - * @return $this - */ - public function asNewInstanceOf($className) - { - $endPoint = &$this->getEndPoint(); - $endPoint['lookupType'] = self::TYPE_INSTANCE; - $endPoint['className'] = $className; + /** + * Specify the previously registered item as a new instance of $className. + * + * {@link register()} must be called before this will work. + * Any arguments can be set with {@link withDependencies()}, + * {@link addConstructorValue()} or {@link addConstructorLookup()}. + * + * @see withDependencies(), addConstructorValue(), addConstructorLookup() + * + * @param string $className + * + * @return $this + */ + public function asNewInstanceOf($className) + { + $endPoint = &$this->getEndPoint(); + $endPoint['lookupType'] = self::TYPE_INSTANCE; + $endPoint['className'] = $className; - return $this; - } + return $this; + } - /** - * Specify the previously registered item as a shared instance of $className. - * - * {@link register()} must be called before this will work. - * - * @param string $className - * - * @return $this - */ - public function asSharedInstanceOf($className) - { - $endPoint = &$this->getEndPoint(); - $endPoint['lookupType'] = self::TYPE_SHARED; - $endPoint['className'] = $className; + /** + * Specify the previously registered item as a shared instance of $className. + * + * {@link register()} must be called before this will work. + * + * @param string $className + * + * @return $this + */ + public function asSharedInstanceOf($className) + { + $endPoint = &$this->getEndPoint(); + $endPoint['lookupType'] = self::TYPE_SHARED; + $endPoint['className'] = $className; - return $this; - } + return $this; + } - /** - * Specify the previously registered item as array of dependencies. - * - * {@link register()} must be called before this will work. - * - * @return $this - */ - public function asArray() - { - $endPoint = &$this->getEndPoint(); - $endPoint['lookupType'] = self::TYPE_ARRAY; + /** + * Specify the previously registered item as array of dependencies. + * + * {@link register()} must be called before this will work. + * + * @return $this + */ + public function asArray() + { + $endPoint = &$this->getEndPoint(); + $endPoint['lookupType'] = self::TYPE_ARRAY; - return $this; - } + return $this; + } - /** - * Specify a list of injected dependencies for the previously registered item. - * - * This method takes an array of lookup names. - * - * @see addConstructorValue(), addConstructorLookup() - * - * @return $this - */ - public function withDependencies(array $lookups) - { - $endPoint = &$this->getEndPoint(); - $endPoint['args'] = []; - foreach ($lookups as $lookup) { - $this->addConstructorLookup($lookup); - } + /** + * Specify a list of injected dependencies for the previously registered item. + * + * This method takes an array of lookup names. + * + * @see addConstructorValue(), addConstructorLookup() + * + * @return $this + */ + public function withDependencies(array $lookups) + { + $endPoint = &$this->getEndPoint(); + $endPoint['args'] = []; + foreach ($lookups as $lookup) { + $this->addConstructorLookup($lookup); + } - return $this; - } + return $this; + } - /** - * Specify a literal (non looked up) value for the constructor of the - * previously registered item. - * - * @see withDependencies(), addConstructorLookup() - * - * @param mixed $value - * - * @return $this - */ - public function addConstructorValue($value) - { - $endPoint = &$this->getEndPoint(); - if (!isset($endPoint['args'])) { - $endPoint['args'] = []; - } - $endPoint['args'][] = ['type' => 'value', 'item' => $value]; + /** + * Specify a literal (non looked up) value for the constructor of the + * previously registered item. + * + * @see withDependencies(), addConstructorLookup() + * + * @param mixed $value + * + * @return $this + */ + public function addConstructorValue($value) + { + $endPoint = &$this->getEndPoint(); + if (!isset($endPoint['args'])) { + $endPoint['args'] = []; + } + $endPoint['args'][] = ['type' => 'value', 'item' => $value]; - return $this; - } + return $this; + } - /** - * Specify a dependency lookup for the constructor of the previously - * registered item. - * - * @see withDependencies(), addConstructorValue() - * - * @param string $lookup - * - * @return $this - */ - public function addConstructorLookup($lookup) - { - $endPoint = &$this->getEndPoint(); - if (!isset($this->endPoint['args'])) { - $endPoint['args'] = []; - } - $endPoint['args'][] = ['type' => 'lookup', 'item' => $lookup]; + /** + * Specify a dependency lookup for the constructor of the previously + * registered item. + * + * @see withDependencies(), addConstructorValue() + * + * @param string $lookup + * + * @return $this + */ + public function addConstructorLookup($lookup) + { + $endPoint = &$this->getEndPoint(); + if (!isset($this->endPoint['args'])) { + $endPoint['args'] = []; + } + $endPoint['args'][] = ['type' => 'lookup', 'item' => $lookup]; - return $this; - } + return $this; + } - /** Get the literal value with $itemName */ - private function getValue($itemName) - { - return $this->store[$itemName]['value']; - } + /** Get the literal value with $itemName */ + private function getValue($itemName) + { + return $this->store[$itemName]['value']; + } - /** Resolve an alias to another item */ - private function createAlias($itemName) - { - return $this->lookup($this->store[$itemName]['ref']); - } + /** Resolve an alias to another item */ + private function createAlias($itemName) + { + return $this->lookup($this->store[$itemName]['ref']); + } - /** Create a fresh instance of $itemName */ - private function createNewInstance($itemName) - { - $reflector = new ReflectionClass($this->store[$itemName]['className']); - if ($reflector->getConstructor()) { - return $reflector->newInstanceArgs( - $this->createDependenciesFor($itemName) - ); - } + /** Create a fresh instance of $itemName */ + private function createNewInstance($itemName) + { + $reflector = new ReflectionClass($this->store[$itemName]['className']); + if ($reflector->getConstructor()) { + return $reflector->newInstanceArgs( + $this->createDependenciesFor($itemName) + ); + } - return $reflector->newInstance(); - } + return $reflector->newInstance(); + } - /** Create and register a shared instance of $itemName */ - private function createSharedInstance($itemName) - { - if (!isset($this->store[$itemName]['instance'])) { - $this->store[$itemName]['instance'] = $this->createNewInstance($itemName); - } + /** Create and register a shared instance of $itemName */ + private function createSharedInstance($itemName) + { + if (!isset($this->store[$itemName]['instance'])) { + $this->store[$itemName]['instance'] = $this->createNewInstance($itemName); + } - return $this->store[$itemName]['instance']; - } + return $this->store[$itemName]['instance']; + } - /** Get the current endpoint in the store */ - private function &getEndPoint() - { - if (!isset($this->endPoint)) { - throw new BadMethodCallException('Component must first be registered by calling register()'); - } + /** Get the current endpoint in the store */ + private function &getEndPoint() + { + if (!isset($this->endPoint)) { + throw new BadMethodCallException('Component must first be registered by calling register()'); + } - return $this->endPoint; - } + return $this->endPoint; + } - /** Get an argument list with dependencies resolved */ - private function resolveArgs(array $args) - { - $resolved = []; - foreach ($args as $argDefinition) { - switch ($argDefinition['type']) { - case 'lookup': - $resolved[] = $this->lookupRecursive($argDefinition['item']); - break; - case 'value': - $resolved[] = $argDefinition['item']; - break; - } - } + /** Get an argument list with dependencies resolved */ + private function resolveArgs(array $args) + { + $resolved = []; + foreach ($args as $argDefinition) { + switch ($argDefinition['type']) { + case 'lookup': + $resolved[] = $this->lookupRecursive($argDefinition['item']); + break; + case 'value': + $resolved[] = $argDefinition['item']; + break; + } + } - return $resolved; - } + return $resolved; + } - /** Resolve a single dependency with an collections */ - private function lookupRecursive($item) - { - if (\is_array($item)) { - $collection = []; - foreach ($item as $k => $v) { - $collection[$k] = $this->lookupRecursive($v); - } + /** Resolve a single dependency with an collections */ + private function lookupRecursive($item) + { + if (\is_array($item)) { + $collection = []; + foreach ($item as $k => $v) { + $collection[$k] = $this->lookupRecursive($v); + } - return $collection; - } + return $collection; + } - return $this->lookup($item); - } + return $this->lookup($item); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/EmbeddedFile.php b/htdocs/includes/swiftmailer/lib/classes/Swift/EmbeddedFile.php index 0ed8a23d566..30fc68ab03e 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/EmbeddedFile.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/EmbeddedFile.php @@ -15,39 +15,39 @@ */ class Swift_EmbeddedFile extends Swift_Mime_EmbeddedFile { - /** - * Create a new EmbeddedFile. - * - * Details may be optionally provided to the constructor. - * - * @param string|Swift_OutputByteStream $data - * @param string $filename - * @param string $contentType - */ - public function __construct($data = null, $filename = null, $contentType = null) - { - \call_user_func_array( - [$this, 'Swift_Mime_EmbeddedFile::__construct'], - Swift_DependencyContainer::getInstance() - ->createDependenciesFor('mime.embeddedfile') - ); + /** + * Create a new EmbeddedFile. + * + * Details may be optionally provided to the constructor. + * + * @param string|Swift_OutputByteStream $data + * @param string $filename + * @param string $contentType + */ + public function __construct($data = null, $filename = null, $contentType = null) + { + \call_user_func_array( + [$this, 'Swift_Mime_EmbeddedFile::__construct'], + Swift_DependencyContainer::getInstance() + ->createDependenciesFor('mime.embeddedfile') + ); - $this->setBody($data); - $this->setFilename($filename); - if ($contentType) { - $this->setContentType($contentType); - } - } + $this->setBody($data); + $this->setFilename($filename); + if ($contentType) { + $this->setContentType($contentType); + } + } - /** - * Create a new EmbeddedFile from a filesystem path. - * - * @param string $path - * - * @return Swift_Mime_EmbeddedFile - */ - public static function fromPath($path) - { - return (new self())->setFile(new Swift_ByteStream_FileByteStream($path)); - } + /** + * Create a new EmbeddedFile from a filesystem path. + * + * @param string $path + * + * @return Swift_Mime_EmbeddedFile + */ + public static function fromPath($path) + { + return (new self())->setFile(new Swift_ByteStream_FileByteStream($path)); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Encoder/Base64Encoder.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Encoder/Base64Encoder.php index f89e74dc222..b1eedaa051b 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Encoder/Base64Encoder.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Encoder/Base64Encoder.php @@ -15,44 +15,44 @@ */ class Swift_Encoder_Base64Encoder implements Swift_Encoder { - /** - * Takes an unencoded string and produces a Base64 encoded string from it. - * - * Base64 encoded strings have a maximum line length of 76 characters. - * If the first line needs to be shorter, indicate the difference with - * $firstLineOffset. - * - * @param string $string to encode - * @param int $firstLineOffset - * @param int $maxLineLength optional, 0 indicates the default of 76 bytes - * - * @return string - */ - public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) - { - if (0 >= $maxLineLength || 76 < $maxLineLength) { - $maxLineLength = 76; - } + /** + * Takes an unencoded string and produces a Base64 encoded string from it. + * + * Base64 encoded strings have a maximum line length of 76 characters. + * If the first line needs to be shorter, indicate the difference with + * $firstLineOffset. + * + * @param string $string to encode + * @param int $firstLineOffset + * @param int $maxLineLength optional, 0 indicates the default of 76 bytes + * + * @return string + */ + public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) + { + if (0 >= $maxLineLength || 76 < $maxLineLength) { + $maxLineLength = 76; + } - $encodedString = base64_encode($string ?? ''); - $firstLine = ''; + $encodedString = base64_encode($string ?? ''); + $firstLine = ''; - if (0 != $firstLineOffset) { - $firstLine = substr( - $encodedString, 0, $maxLineLength - $firstLineOffset - )."\r\n"; - $encodedString = substr( - $encodedString, $maxLineLength - $firstLineOffset - ); - } + if (0 != $firstLineOffset) { + $firstLine = substr( + $encodedString, 0, $maxLineLength - $firstLineOffset + )."\r\n"; + $encodedString = substr( + $encodedString, $maxLineLength - $firstLineOffset + ); + } - return $firstLine.trim(chunk_split($encodedString, $maxLineLength, "\r\n")); - } + return $firstLine.trim(chunk_split($encodedString, $maxLineLength, "\r\n")); + } - /** - * Does nothing. - */ - public function charsetChanged($charset) - { - } + /** + * Does nothing. + */ + public function charsetChanged($charset) + { + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Encoder/QpEncoder.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Encoder/QpEncoder.php index 24ad727f95b..f078d6d7c38 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Encoder/QpEncoder.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Encoder/QpEncoder.php @@ -17,284 +17,284 @@ */ class Swift_Encoder_QpEncoder implements Swift_Encoder { - /** - * The CharacterStream used for reading characters (as opposed to bytes). - * - * @var Swift_CharacterStream - */ - protected $charStream; + /** + * The CharacterStream used for reading characters (as opposed to bytes). + * + * @var Swift_CharacterStream + */ + protected $charStream; - /** - * A filter used if input should be canonicalized. - * - * @var Swift_StreamFilter - */ - protected $filter; + /** + * A filter used if input should be canonicalized. + * + * @var Swift_StreamFilter + */ + protected $filter; - /** - * Pre-computed QP for HUGE optimization. - * - * @var string[] - */ - protected static $qpMap = [ - 0 => '=00', 1 => '=01', 2 => '=02', 3 => '=03', 4 => '=04', - 5 => '=05', 6 => '=06', 7 => '=07', 8 => '=08', 9 => '=09', - 10 => '=0A', 11 => '=0B', 12 => '=0C', 13 => '=0D', 14 => '=0E', - 15 => '=0F', 16 => '=10', 17 => '=11', 18 => '=12', 19 => '=13', - 20 => '=14', 21 => '=15', 22 => '=16', 23 => '=17', 24 => '=18', - 25 => '=19', 26 => '=1A', 27 => '=1B', 28 => '=1C', 29 => '=1D', - 30 => '=1E', 31 => '=1F', 32 => '=20', 33 => '=21', 34 => '=22', - 35 => '=23', 36 => '=24', 37 => '=25', 38 => '=26', 39 => '=27', - 40 => '=28', 41 => '=29', 42 => '=2A', 43 => '=2B', 44 => '=2C', - 45 => '=2D', 46 => '=2E', 47 => '=2F', 48 => '=30', 49 => '=31', - 50 => '=32', 51 => '=33', 52 => '=34', 53 => '=35', 54 => '=36', - 55 => '=37', 56 => '=38', 57 => '=39', 58 => '=3A', 59 => '=3B', - 60 => '=3C', 61 => '=3D', 62 => '=3E', 63 => '=3F', 64 => '=40', - 65 => '=41', 66 => '=42', 67 => '=43', 68 => '=44', 69 => '=45', - 70 => '=46', 71 => '=47', 72 => '=48', 73 => '=49', 74 => '=4A', - 75 => '=4B', 76 => '=4C', 77 => '=4D', 78 => '=4E', 79 => '=4F', - 80 => '=50', 81 => '=51', 82 => '=52', 83 => '=53', 84 => '=54', - 85 => '=55', 86 => '=56', 87 => '=57', 88 => '=58', 89 => '=59', - 90 => '=5A', 91 => '=5B', 92 => '=5C', 93 => '=5D', 94 => '=5E', - 95 => '=5F', 96 => '=60', 97 => '=61', 98 => '=62', 99 => '=63', - 100 => '=64', 101 => '=65', 102 => '=66', 103 => '=67', 104 => '=68', - 105 => '=69', 106 => '=6A', 107 => '=6B', 108 => '=6C', 109 => '=6D', - 110 => '=6E', 111 => '=6F', 112 => '=70', 113 => '=71', 114 => '=72', - 115 => '=73', 116 => '=74', 117 => '=75', 118 => '=76', 119 => '=77', - 120 => '=78', 121 => '=79', 122 => '=7A', 123 => '=7B', 124 => '=7C', - 125 => '=7D', 126 => '=7E', 127 => '=7F', 128 => '=80', 129 => '=81', - 130 => '=82', 131 => '=83', 132 => '=84', 133 => '=85', 134 => '=86', - 135 => '=87', 136 => '=88', 137 => '=89', 138 => '=8A', 139 => '=8B', - 140 => '=8C', 141 => '=8D', 142 => '=8E', 143 => '=8F', 144 => '=90', - 145 => '=91', 146 => '=92', 147 => '=93', 148 => '=94', 149 => '=95', - 150 => '=96', 151 => '=97', 152 => '=98', 153 => '=99', 154 => '=9A', - 155 => '=9B', 156 => '=9C', 157 => '=9D', 158 => '=9E', 159 => '=9F', - 160 => '=A0', 161 => '=A1', 162 => '=A2', 163 => '=A3', 164 => '=A4', - 165 => '=A5', 166 => '=A6', 167 => '=A7', 168 => '=A8', 169 => '=A9', - 170 => '=AA', 171 => '=AB', 172 => '=AC', 173 => '=AD', 174 => '=AE', - 175 => '=AF', 176 => '=B0', 177 => '=B1', 178 => '=B2', 179 => '=B3', - 180 => '=B4', 181 => '=B5', 182 => '=B6', 183 => '=B7', 184 => '=B8', - 185 => '=B9', 186 => '=BA', 187 => '=BB', 188 => '=BC', 189 => '=BD', - 190 => '=BE', 191 => '=BF', 192 => '=C0', 193 => '=C1', 194 => '=C2', - 195 => '=C3', 196 => '=C4', 197 => '=C5', 198 => '=C6', 199 => '=C7', - 200 => '=C8', 201 => '=C9', 202 => '=CA', 203 => '=CB', 204 => '=CC', - 205 => '=CD', 206 => '=CE', 207 => '=CF', 208 => '=D0', 209 => '=D1', - 210 => '=D2', 211 => '=D3', 212 => '=D4', 213 => '=D5', 214 => '=D6', - 215 => '=D7', 216 => '=D8', 217 => '=D9', 218 => '=DA', 219 => '=DB', - 220 => '=DC', 221 => '=DD', 222 => '=DE', 223 => '=DF', 224 => '=E0', - 225 => '=E1', 226 => '=E2', 227 => '=E3', 228 => '=E4', 229 => '=E5', - 230 => '=E6', 231 => '=E7', 232 => '=E8', 233 => '=E9', 234 => '=EA', - 235 => '=EB', 236 => '=EC', 237 => '=ED', 238 => '=EE', 239 => '=EF', - 240 => '=F0', 241 => '=F1', 242 => '=F2', 243 => '=F3', 244 => '=F4', - 245 => '=F5', 246 => '=F6', 247 => '=F7', 248 => '=F8', 249 => '=F9', - 250 => '=FA', 251 => '=FB', 252 => '=FC', 253 => '=FD', 254 => '=FE', - 255 => '=FF', - ]; + /** + * Pre-computed QP for HUGE optimization. + * + * @var string[] + */ + protected static $qpMap = [ + 0 => '=00', 1 => '=01', 2 => '=02', 3 => '=03', 4 => '=04', + 5 => '=05', 6 => '=06', 7 => '=07', 8 => '=08', 9 => '=09', + 10 => '=0A', 11 => '=0B', 12 => '=0C', 13 => '=0D', 14 => '=0E', + 15 => '=0F', 16 => '=10', 17 => '=11', 18 => '=12', 19 => '=13', + 20 => '=14', 21 => '=15', 22 => '=16', 23 => '=17', 24 => '=18', + 25 => '=19', 26 => '=1A', 27 => '=1B', 28 => '=1C', 29 => '=1D', + 30 => '=1E', 31 => '=1F', 32 => '=20', 33 => '=21', 34 => '=22', + 35 => '=23', 36 => '=24', 37 => '=25', 38 => '=26', 39 => '=27', + 40 => '=28', 41 => '=29', 42 => '=2A', 43 => '=2B', 44 => '=2C', + 45 => '=2D', 46 => '=2E', 47 => '=2F', 48 => '=30', 49 => '=31', + 50 => '=32', 51 => '=33', 52 => '=34', 53 => '=35', 54 => '=36', + 55 => '=37', 56 => '=38', 57 => '=39', 58 => '=3A', 59 => '=3B', + 60 => '=3C', 61 => '=3D', 62 => '=3E', 63 => '=3F', 64 => '=40', + 65 => '=41', 66 => '=42', 67 => '=43', 68 => '=44', 69 => '=45', + 70 => '=46', 71 => '=47', 72 => '=48', 73 => '=49', 74 => '=4A', + 75 => '=4B', 76 => '=4C', 77 => '=4D', 78 => '=4E', 79 => '=4F', + 80 => '=50', 81 => '=51', 82 => '=52', 83 => '=53', 84 => '=54', + 85 => '=55', 86 => '=56', 87 => '=57', 88 => '=58', 89 => '=59', + 90 => '=5A', 91 => '=5B', 92 => '=5C', 93 => '=5D', 94 => '=5E', + 95 => '=5F', 96 => '=60', 97 => '=61', 98 => '=62', 99 => '=63', + 100 => '=64', 101 => '=65', 102 => '=66', 103 => '=67', 104 => '=68', + 105 => '=69', 106 => '=6A', 107 => '=6B', 108 => '=6C', 109 => '=6D', + 110 => '=6E', 111 => '=6F', 112 => '=70', 113 => '=71', 114 => '=72', + 115 => '=73', 116 => '=74', 117 => '=75', 118 => '=76', 119 => '=77', + 120 => '=78', 121 => '=79', 122 => '=7A', 123 => '=7B', 124 => '=7C', + 125 => '=7D', 126 => '=7E', 127 => '=7F', 128 => '=80', 129 => '=81', + 130 => '=82', 131 => '=83', 132 => '=84', 133 => '=85', 134 => '=86', + 135 => '=87', 136 => '=88', 137 => '=89', 138 => '=8A', 139 => '=8B', + 140 => '=8C', 141 => '=8D', 142 => '=8E', 143 => '=8F', 144 => '=90', + 145 => '=91', 146 => '=92', 147 => '=93', 148 => '=94', 149 => '=95', + 150 => '=96', 151 => '=97', 152 => '=98', 153 => '=99', 154 => '=9A', + 155 => '=9B', 156 => '=9C', 157 => '=9D', 158 => '=9E', 159 => '=9F', + 160 => '=A0', 161 => '=A1', 162 => '=A2', 163 => '=A3', 164 => '=A4', + 165 => '=A5', 166 => '=A6', 167 => '=A7', 168 => '=A8', 169 => '=A9', + 170 => '=AA', 171 => '=AB', 172 => '=AC', 173 => '=AD', 174 => '=AE', + 175 => '=AF', 176 => '=B0', 177 => '=B1', 178 => '=B2', 179 => '=B3', + 180 => '=B4', 181 => '=B5', 182 => '=B6', 183 => '=B7', 184 => '=B8', + 185 => '=B9', 186 => '=BA', 187 => '=BB', 188 => '=BC', 189 => '=BD', + 190 => '=BE', 191 => '=BF', 192 => '=C0', 193 => '=C1', 194 => '=C2', + 195 => '=C3', 196 => '=C4', 197 => '=C5', 198 => '=C6', 199 => '=C7', + 200 => '=C8', 201 => '=C9', 202 => '=CA', 203 => '=CB', 204 => '=CC', + 205 => '=CD', 206 => '=CE', 207 => '=CF', 208 => '=D0', 209 => '=D1', + 210 => '=D2', 211 => '=D3', 212 => '=D4', 213 => '=D5', 214 => '=D6', + 215 => '=D7', 216 => '=D8', 217 => '=D9', 218 => '=DA', 219 => '=DB', + 220 => '=DC', 221 => '=DD', 222 => '=DE', 223 => '=DF', 224 => '=E0', + 225 => '=E1', 226 => '=E2', 227 => '=E3', 228 => '=E4', 229 => '=E5', + 230 => '=E6', 231 => '=E7', 232 => '=E8', 233 => '=E9', 234 => '=EA', + 235 => '=EB', 236 => '=EC', 237 => '=ED', 238 => '=EE', 239 => '=EF', + 240 => '=F0', 241 => '=F1', 242 => '=F2', 243 => '=F3', 244 => '=F4', + 245 => '=F5', 246 => '=F6', 247 => '=F7', 248 => '=F8', 249 => '=F9', + 250 => '=FA', 251 => '=FB', 252 => '=FC', 253 => '=FD', 254 => '=FE', + 255 => '=FF', + ]; - protected static $safeMapShare = []; + protected static $safeMapShare = []; - /** - * A map of non-encoded ascii characters. - * - * @var string[] - */ - protected $safeMap = []; + /** + * A map of non-encoded ascii characters. + * + * @var string[] + */ + protected $safeMap = []; - /** - * Creates a new QpEncoder for the given CharacterStream. - * - * @param Swift_CharacterStream $charStream to use for reading characters - * @param Swift_StreamFilter $filter if input should be canonicalized - */ - public function __construct(Swift_CharacterStream $charStream, Swift_StreamFilter $filter = null) - { - $this->charStream = $charStream; - if (!isset(self::$safeMapShare[$this->getSafeMapShareId()])) { - $this->initSafeMap(); - self::$safeMapShare[$this->getSafeMapShareId()] = $this->safeMap; - } else { - $this->safeMap = self::$safeMapShare[$this->getSafeMapShareId()]; - } - $this->filter = $filter; - } + /** + * Creates a new QpEncoder for the given CharacterStream. + * + * @param Swift_CharacterStream $charStream to use for reading characters + * @param Swift_StreamFilter $filter if input should be canonicalized + */ + public function __construct(Swift_CharacterStream $charStream, Swift_StreamFilter $filter = null) + { + $this->charStream = $charStream; + if (!isset(self::$safeMapShare[$this->getSafeMapShareId()])) { + $this->initSafeMap(); + self::$safeMapShare[$this->getSafeMapShareId()] = $this->safeMap; + } else { + $this->safeMap = self::$safeMapShare[$this->getSafeMapShareId()]; + } + $this->filter = $filter; + } - public function __sleep() - { - return ['charStream', 'filter']; - } + public function __sleep() + { + return ['charStream', 'filter']; + } - public function __wakeup() - { - if (!isset(self::$safeMapShare[$this->getSafeMapShareId()])) { - $this->initSafeMap(); - self::$safeMapShare[$this->getSafeMapShareId()] = $this->safeMap; - } else { - $this->safeMap = self::$safeMapShare[$this->getSafeMapShareId()]; - } - } + public function __wakeup() + { + if (!isset(self::$safeMapShare[$this->getSafeMapShareId()])) { + $this->initSafeMap(); + self::$safeMapShare[$this->getSafeMapShareId()] = $this->safeMap; + } else { + $this->safeMap = self::$safeMapShare[$this->getSafeMapShareId()]; + } + } - protected function getSafeMapShareId() - { - return static::class; - } + protected function getSafeMapShareId() + { + return static::class; + } - protected function initSafeMap() - { - foreach (array_merge( - [0x09, 0x20], range(0x21, 0x3C), range(0x3E, 0x7E)) as $byte) { - $this->safeMap[$byte] = \chr($byte); - } - } + protected function initSafeMap() + { + foreach (array_merge( + [0x09, 0x20], range(0x21, 0x3C), range(0x3E, 0x7E)) as $byte) { + $this->safeMap[$byte] = \chr($byte); + } + } - /** - * Takes an unencoded string and produces a QP encoded string from it. - * - * QP encoded strings have a maximum line length of 76 characters. - * If the first line needs to be shorter, indicate the difference with - * $firstLineOffset. - * - * @param string $string to encode - * @param int $firstLineOffset optional - * @param int $maxLineLength optional 0 indicates the default of 76 chars - * - * @return string - */ - public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) - { - if ($maxLineLength > 76 || $maxLineLength <= 0) { - $maxLineLength = 76; - } + /** + * Takes an unencoded string and produces a QP encoded string from it. + * + * QP encoded strings have a maximum line length of 76 characters. + * If the first line needs to be shorter, indicate the difference with + * $firstLineOffset. + * + * @param string $string to encode + * @param int $firstLineOffset optional + * @param int $maxLineLength optional 0 indicates the default of 76 chars + * + * @return string + */ + public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) + { + if ($maxLineLength > 76 || $maxLineLength <= 0) { + $maxLineLength = 76; + } - $thisLineLength = $maxLineLength - $firstLineOffset; + $thisLineLength = $maxLineLength - $firstLineOffset; - $lines = []; - $lNo = 0; - $lines[$lNo] = ''; - $currentLine = &$lines[$lNo++]; - $size = $lineLen = 0; + $lines = []; + $lNo = 0; + $lines[$lNo] = ''; + $currentLine = &$lines[$lNo++]; + $size = $lineLen = 0; - $this->charStream->flushContents(); - $this->charStream->importString($string); + $this->charStream->flushContents(); + $this->charStream->importString($string); - // Fetching more than 4 chars at one is slower, as is fetching fewer bytes - // Conveniently 4 chars is the UTF-8 safe number since UTF-8 has up to 6 - // bytes per char and (6 * 4 * 3 = 72 chars per line) * =NN is 3 bytes - while (false !== $bytes = $this->nextSequence()) { - // If we're filtering the input - if (isset($this->filter)) { - // If we can't filter because we need more bytes - while ($this->filter->shouldBuffer($bytes)) { - // Then collect bytes into the buffer - if (false === $moreBytes = $this->nextSequence(1)) { - break; - } + // Fetching more than 4 chars at one is slower, as is fetching fewer bytes + // Conveniently 4 chars is the UTF-8 safe number since UTF-8 has up to 6 + // bytes per char and (6 * 4 * 3 = 72 chars per line) * =NN is 3 bytes + while (false !== $bytes = $this->nextSequence()) { + // If we're filtering the input + if (isset($this->filter)) { + // If we can't filter because we need more bytes + while ($this->filter->shouldBuffer($bytes)) { + // Then collect bytes into the buffer + if (false === $moreBytes = $this->nextSequence(1)) { + break; + } - foreach ($moreBytes as $b) { - $bytes[] = $b; - } - } - // And filter them - $bytes = $this->filter->filter($bytes); - } + foreach ($moreBytes as $b) { + $bytes[] = $b; + } + } + // And filter them + $bytes = $this->filter->filter($bytes); + } - $enc = $this->encodeByteSequence($bytes, $size); + $enc = $this->encodeByteSequence($bytes, $size); - $i = strpos($enc, '=0D=0A'); - $newLineLength = $lineLen + (false === $i ? $size : $i); + $i = strpos($enc, '=0D=0A'); + $newLineLength = $lineLen + (false === $i ? $size : $i); - if ($currentLine && $newLineLength >= $thisLineLength) { - $lines[$lNo] = ''; - $currentLine = &$lines[$lNo++]; - $thisLineLength = $maxLineLength; - $lineLen = 0; - } + if ($currentLine && $newLineLength >= $thisLineLength) { + $lines[$lNo] = ''; + $currentLine = &$lines[$lNo++]; + $thisLineLength = $maxLineLength; + $lineLen = 0; + } - $currentLine .= $enc; + $currentLine .= $enc; - if (false === $i) { - $lineLen += $size; - } else { - // 6 is the length of '=0D=0A'. - $lineLen = $size - strrpos($enc, '=0D=0A') - 6; - } - } + if (false === $i) { + $lineLen += $size; + } else { + // 6 is the length of '=0D=0A'. + $lineLen = $size - strrpos($enc, '=0D=0A') - 6; + } + } - return $this->standardize(implode("=\r\n", $lines)); - } + return $this->standardize(implode("=\r\n", $lines)); + } - /** - * Updates the charset used. - * - * @param string $charset - */ - public function charsetChanged($charset) - { - $this->charStream->setCharacterSet($charset); - } + /** + * Updates the charset used. + * + * @param string $charset + */ + public function charsetChanged($charset) + { + $this->charStream->setCharacterSet($charset); + } - /** - * Encode the given byte array into a verbatim QP form. - * - * @param int[] $bytes - * @param int $size - * - * @return string - */ - protected function encodeByteSequence(array $bytes, &$size) - { - $ret = ''; - $size = 0; - foreach ($bytes as $b) { - if (isset($this->safeMap[$b])) { - $ret .= $this->safeMap[$b]; - ++$size; - } else { - $ret .= self::$qpMap[$b]; - $size += 3; - } - } + /** + * Encode the given byte array into a verbatim QP form. + * + * @param int[] $bytes + * @param int $size + * + * @return string + */ + protected function encodeByteSequence(array $bytes, &$size) + { + $ret = ''; + $size = 0; + foreach ($bytes as $b) { + if (isset($this->safeMap[$b])) { + $ret .= $this->safeMap[$b]; + ++$size; + } else { + $ret .= self::$qpMap[$b]; + $size += 3; + } + } - return $ret; - } + return $ret; + } - /** - * Get the next sequence of bytes to read from the char stream. - * - * @param int $size number of bytes to read - * - * @return int[] - */ - protected function nextSequence($size = 4) - { - return $this->charStream->readBytes($size); - } + /** + * Get the next sequence of bytes to read from the char stream. + * + * @param int $size number of bytes to read + * + * @return int[] + */ + protected function nextSequence($size = 4) + { + return $this->charStream->readBytes($size); + } - /** - * Make sure CRLF is correct and HT/SPACE are in valid places. - * - * @param string $string - * - * @return string - */ - protected function standardize($string) - { - $string = str_replace(["\t=0D=0A", ' =0D=0A', '=0D=0A'], - ["=09\r\n", "=20\r\n", "\r\n"], $string - ); - switch ($end = \ord(substr($string, -1))) { - case 0x09: - case 0x20: - $string = substr_replace($string, self::$qpMap[$end], -1); - } + /** + * Make sure CRLF is correct and HT/SPACE are in valid places. + * + * @param string $string + * + * @return string + */ + protected function standardize($string) + { + $string = str_replace(["\t=0D=0A", ' =0D=0A', '=0D=0A'], + ["=09\r\n", "=20\r\n", "\r\n"], $string + ); + switch ($end = \ord(substr($string, -1))) { + case 0x09: + case 0x20: + $string = substr_replace($string, self::$qpMap[$end], -1); + } - return $string; - } + return $string; + } - /** - * Make a deep copy of object. - */ - public function __clone() - { - $this->charStream = clone $this->charStream; - } + /** + * Make a deep copy of object. + */ + public function __clone() + { + $this->charStream = clone $this->charStream; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Encoder/Rfc2231Encoder.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Encoder/Rfc2231Encoder.php index 488fcfd4717..7eac36813e0 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Encoder/Rfc2231Encoder.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Encoder/Rfc2231Encoder.php @@ -15,76 +15,76 @@ */ class Swift_Encoder_Rfc2231Encoder implements Swift_Encoder { - /** - * A character stream to use when reading a string as characters instead of bytes. - * - * @var Swift_CharacterStream - */ - private $charStream; + /** + * A character stream to use when reading a string as characters instead of bytes. + * + * @var Swift_CharacterStream + */ + private $charStream; - /** - * Creates a new Rfc2231Encoder using the given character stream instance. - */ - public function __construct(Swift_CharacterStream $charStream) - { - $this->charStream = $charStream; - } + /** + * Creates a new Rfc2231Encoder using the given character stream instance. + */ + public function __construct(Swift_CharacterStream $charStream) + { + $this->charStream = $charStream; + } - /** - * Takes an unencoded string and produces a string encoded according to - * RFC 2231 from it. - * - * @param string $string - * @param int $firstLineOffset - * @param int $maxLineLength optional, 0 indicates the default of 75 bytes - * - * @return string - */ - public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) - { - $lines = []; - $lineCount = 0; - $lines[] = ''; - $currentLine = &$lines[$lineCount++]; + /** + * Takes an unencoded string and produces a string encoded according to + * RFC 2231 from it. + * + * @param string $string + * @param int $firstLineOffset + * @param int $maxLineLength optional, 0 indicates the default of 75 bytes + * + * @return string + */ + public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) + { + $lines = []; + $lineCount = 0; + $lines[] = ''; + $currentLine = &$lines[$lineCount++]; - if (0 >= $maxLineLength) { - $maxLineLength = 75; - } + if (0 >= $maxLineLength) { + $maxLineLength = 75; + } - $this->charStream->flushContents(); - $this->charStream->importString($string); + $this->charStream->flushContents(); + $this->charStream->importString($string); - $thisLineLength = $maxLineLength - $firstLineOffset; + $thisLineLength = $maxLineLength - $firstLineOffset; - while (false !== $char = $this->charStream->read(4)) { - $encodedChar = rawurlencode($char); - if (0 != \strlen($currentLine) - && \strlen($currentLine.$encodedChar) > $thisLineLength) { - $lines[] = ''; - $currentLine = &$lines[$lineCount++]; - $thisLineLength = $maxLineLength; - } - $currentLine .= $encodedChar; - } + while (false !== $char = $this->charStream->read(4)) { + $encodedChar = rawurlencode($char); + if (0 != \strlen($currentLine) + && \strlen($currentLine.$encodedChar) > $thisLineLength) { + $lines[] = ''; + $currentLine = &$lines[$lineCount++]; + $thisLineLength = $maxLineLength; + } + $currentLine .= $encodedChar; + } - return implode("\r\n", $lines); - } + return implode("\r\n", $lines); + } - /** - * Updates the charset used. - * - * @param string $charset - */ - public function charsetChanged($charset) - { - $this->charStream->setCharacterSet($charset); - } + /** + * Updates the charset used. + * + * @param string $charset + */ + public function charsetChanged($charset) + { + $this->charStream->setCharacterSet($charset); + } - /** - * Make a deep copy of object. - */ - public function __clone() - { - $this->charStream = clone $this->charStream; - } + /** + * Make a deep copy of object. + */ + public function __clone() + { + $this->charStream = clone $this->charStream; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/CommandEvent.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/CommandEvent.php index 1524fda752a..18994c184f3 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/CommandEvent.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/CommandEvent.php @@ -15,50 +15,50 @@ */ class Swift_Events_CommandEvent extends Swift_Events_EventObject { - /** - * The command sent to the server. - * - * @var string - */ - private $command; + /** + * The command sent to the server. + * + * @var string + */ + private $command; - /** - * An array of codes which a successful response will contain. - * - * @var int[] - */ - private $successCodes = []; + /** + * An array of codes which a successful response will contain. + * + * @var int[] + */ + private $successCodes = []; - /** - * Create a new CommandEvent for $source with $command. - * - * @param string $command - * @param array $successCodes - */ - public function __construct(Swift_Transport $source, $command, $successCodes = []) - { - parent::__construct($source); - $this->command = $command; - $this->successCodes = $successCodes; - } + /** + * Create a new CommandEvent for $source with $command. + * + * @param string $command + * @param array $successCodes + */ + public function __construct(Swift_Transport $source, $command, $successCodes = []) + { + parent::__construct($source); + $this->command = $command; + $this->successCodes = $successCodes; + } - /** - * Get the command which was sent to the server. - * - * @return string - */ - public function getCommand() - { - return $this->command; - } + /** + * Get the command which was sent to the server. + * + * @return string + */ + public function getCommand() + { + return $this->command; + } - /** - * Get the numeric response codes which indicate success for this command. - * - * @return int[] - */ - public function getSuccessCodes() - { - return $this->successCodes; - } + /** + * Get the numeric response codes which indicate success for this command. + * + * @return int[] + */ + public function getSuccessCodes() + { + return $this->successCodes; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/CommandListener.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/CommandListener.php index 7dff32b4ee6..b158eab462a 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/CommandListener.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/CommandListener.php @@ -15,8 +15,8 @@ */ interface Swift_Events_CommandListener extends Swift_Events_EventListener { - /** - * Invoked immediately following a command being sent. - */ - public function commandSent(Swift_Events_CommandEvent $evt); + /** + * Invoked immediately following a command being sent. + */ + public function commandSent(Swift_Events_CommandEvent $evt); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/EventDispatcher.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/EventDispatcher.php index 1de97381930..df25a124863 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/EventDispatcher.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/EventDispatcher.php @@ -15,56 +15,56 @@ */ interface Swift_Events_EventDispatcher { - /** - * Create a new SendEvent for $source and $message. - * - * @return Swift_Events_SendEvent - */ - public function createSendEvent(Swift_Transport $source, Swift_Mime_SimpleMessage $message); + /** + * Create a new SendEvent for $source and $message. + * + * @return Swift_Events_SendEvent + */ + public function createSendEvent(Swift_Transport $source, Swift_Mime_SimpleMessage $message); - /** - * Create a new CommandEvent for $source and $command. - * - * @param string $command That will be executed - * @param array $successCodes That are needed - * - * @return Swift_Events_CommandEvent - */ - public function createCommandEvent(Swift_Transport $source, $command, $successCodes = []); + /** + * Create a new CommandEvent for $source and $command. + * + * @param string $command That will be executed + * @param array $successCodes That are needed + * + * @return Swift_Events_CommandEvent + */ + public function createCommandEvent(Swift_Transport $source, $command, $successCodes = []); - /** - * Create a new ResponseEvent for $source and $response. - * - * @param string $response - * @param bool $valid If the response is valid - * - * @return Swift_Events_ResponseEvent - */ - public function createResponseEvent(Swift_Transport $source, $response, $valid); + /** + * Create a new ResponseEvent for $source and $response. + * + * @param string $response + * @param bool $valid If the response is valid + * + * @return Swift_Events_ResponseEvent + */ + public function createResponseEvent(Swift_Transport $source, $response, $valid); - /** - * Create a new TransportChangeEvent for $source. - * - * @return Swift_Events_TransportChangeEvent - */ - public function createTransportChangeEvent(Swift_Transport $source); + /** + * Create a new TransportChangeEvent for $source. + * + * @return Swift_Events_TransportChangeEvent + */ + public function createTransportChangeEvent(Swift_Transport $source); - /** - * Create a new TransportExceptionEvent for $source. - * - * @return Swift_Events_TransportExceptionEvent - */ - public function createTransportExceptionEvent(Swift_Transport $source, Swift_TransportException $ex); + /** + * Create a new TransportExceptionEvent for $source. + * + * @return Swift_Events_TransportExceptionEvent + */ + public function createTransportExceptionEvent(Swift_Transport $source, Swift_TransportException $ex); - /** - * Bind an event listener to this dispatcher. - */ - public function bindEventListener(Swift_Events_EventListener $listener); + /** + * Bind an event listener to this dispatcher. + */ + public function bindEventListener(Swift_Events_EventListener $listener); - /** - * Dispatch the given Event to all suitable listeners. - * - * @param string $target method - */ - public function dispatchEvent(Swift_Events_EventObject $evt, $target); + /** + * Dispatch the given Event to all suitable listeners. + * + * @param string $target method + */ + public function dispatchEvent(Swift_Events_EventObject $evt, $target); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/EventObject.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/EventObject.php index 8e3f672cdeb..24a11f44e23 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/EventObject.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/EventObject.php @@ -15,47 +15,47 @@ */ class Swift_Events_EventObject implements Swift_Events_Event { - /** The source of this Event */ - private $source; + /** The source of this Event */ + private $source; - /** The state of this Event (should it bubble up the stack?) */ - private $bubbleCancelled = false; + /** The state of this Event (should it bubble up the stack?) */ + private $bubbleCancelled = false; - /** - * Create a new EventObject originating at $source. - * - * @param object $source - */ - public function __construct($source) - { - $this->source = $source; - } + /** + * Create a new EventObject originating at $source. + * + * @param object $source + */ + public function __construct($source) + { + $this->source = $source; + } - /** - * Get the source object of this event. - * - * @return object - */ - public function getSource() - { - return $this->source; - } + /** + * Get the source object of this event. + * + * @return object + */ + public function getSource() + { + return $this->source; + } - /** - * Prevent this Event from bubbling any further up the stack. - */ - public function cancelBubble($cancel = true) - { - $this->bubbleCancelled = $cancel; - } + /** + * Prevent this Event from bubbling any further up the stack. + */ + public function cancelBubble($cancel = true) + { + $this->bubbleCancelled = $cancel; + } - /** - * Returns true if this Event will not bubble any further up the stack. - * - * @return bool - */ - public function bubbleCancelled() - { - return $this->bubbleCancelled; - } + /** + * Returns true if this Event will not bubble any further up the stack. + * + * @return bool + */ + public function bubbleCancelled() + { + return $this->bubbleCancelled; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/ResponseEvent.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/ResponseEvent.php index ddae7aab9a4..ff7c37116ba 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/ResponseEvent.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/ResponseEvent.php @@ -15,50 +15,50 @@ */ class Swift_Events_ResponseEvent extends Swift_Events_EventObject { - /** - * The overall result. - * - * @var bool - */ - private $valid; + /** + * The overall result. + * + * @var bool + */ + private $valid; - /** - * The response received from the server. - * - * @var string - */ - private $response; + /** + * The response received from the server. + * + * @var string + */ + private $response; - /** - * Create a new ResponseEvent for $source and $response. - * - * @param string $response - * @param bool $valid - */ - public function __construct(Swift_Transport $source, $response, $valid = false) - { - parent::__construct($source); - $this->response = $response; - $this->valid = $valid; - } + /** + * Create a new ResponseEvent for $source and $response. + * + * @param string $response + * @param bool $valid + */ + public function __construct(Swift_Transport $source, $response, $valid = false) + { + parent::__construct($source); + $this->response = $response; + $this->valid = $valid; + } - /** - * Get the response which was received from the server. - * - * @return string - */ - public function getResponse() - { - return $this->response; - } + /** + * Get the response which was received from the server. + * + * @return string + */ + public function getResponse() + { + return $this->response; + } - /** - * Get the success status of this Event. - * - * @return bool - */ - public function isValid() - { - return $this->valid; - } + /** + * Get the success status of this Event. + * + * @return bool + */ + public function isValid() + { + return $this->valid; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/ResponseListener.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/ResponseListener.php index ba607510426..85115a33811 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/ResponseListener.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/ResponseListener.php @@ -15,8 +15,8 @@ */ interface Swift_Events_ResponseListener extends Swift_Events_EventListener { - /** - * Invoked immediately following a response coming back. - */ - public function responseReceived(Swift_Events_ResponseEvent $evt); + /** + * Invoked immediately following a response coming back. + */ + public function responseReceived(Swift_Events_ResponseEvent $evt); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/SendEvent.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/SendEvent.php index c485f29010e..a435691e0b0 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/SendEvent.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/SendEvent.php @@ -15,112 +15,112 @@ */ class Swift_Events_SendEvent extends Swift_Events_EventObject { - /** Sending has yet to occur */ - const RESULT_PENDING = 0x0001; + /** Sending has yet to occur */ + const RESULT_PENDING = 0x0001; - /** Email is spooled, ready to be sent */ - const RESULT_SPOOLED = 0x0011; + /** Email is spooled, ready to be sent */ + const RESULT_SPOOLED = 0x0011; - /** Sending was successful */ - const RESULT_SUCCESS = 0x0010; + /** Sending was successful */ + const RESULT_SUCCESS = 0x0010; - /** Sending worked, but there were some failures */ - const RESULT_TENTATIVE = 0x0100; + /** Sending worked, but there were some failures */ + const RESULT_TENTATIVE = 0x0100; - /** Sending failed */ - const RESULT_FAILED = 0x1000; + /** Sending failed */ + const RESULT_FAILED = 0x1000; - /** - * The Message being sent. - * - * @var Swift_Mime_SimpleMessage - */ - private $message; + /** + * The Message being sent. + * + * @var Swift_Mime_SimpleMessage + */ + private $message; - /** - * Any recipients which failed after sending. - * - * @var string[] - */ - private $failedRecipients = []; + /** + * Any recipients which failed after sending. + * + * @var string[] + */ + private $failedRecipients = []; - /** - * The overall result as a bitmask from the class constants. - * - * @var int - */ - private $result; + /** + * The overall result as a bitmask from the class constants. + * + * @var int + */ + private $result; - /** - * Create a new SendEvent for $source and $message. - */ - public function __construct(Swift_Transport $source, Swift_Mime_SimpleMessage $message) - { - parent::__construct($source); - $this->message = $message; - $this->result = self::RESULT_PENDING; - } + /** + * Create a new SendEvent for $source and $message. + */ + public function __construct(Swift_Transport $source, Swift_Mime_SimpleMessage $message) + { + parent::__construct($source); + $this->message = $message; + $this->result = self::RESULT_PENDING; + } - /** - * Get the Transport used to send the Message. - * - * @return Swift_Transport - */ - public function getTransport() - { - return $this->getSource(); - } + /** + * Get the Transport used to send the Message. + * + * @return Swift_Transport + */ + public function getTransport() + { + return $this->getSource(); + } - /** - * Get the Message being sent. - * - * @return Swift_Mime_SimpleMessage - */ - public function getMessage() - { - return $this->message; - } + /** + * Get the Message being sent. + * + * @return Swift_Mime_SimpleMessage + */ + public function getMessage() + { + return $this->message; + } - /** - * Set the array of addresses that failed in sending. - * - * @param array $recipients - */ - public function setFailedRecipients($recipients) - { - $this->failedRecipients = $recipients; - } + /** + * Set the array of addresses that failed in sending. + * + * @param array $recipients + */ + public function setFailedRecipients($recipients) + { + $this->failedRecipients = $recipients; + } - /** - * Get an recipient addresses which were not accepted for delivery. - * - * @return string[] - */ - public function getFailedRecipients() - { - return $this->failedRecipients; - } + /** + * Get an recipient addresses which were not accepted for delivery. + * + * @return string[] + */ + public function getFailedRecipients() + { + return $this->failedRecipients; + } - /** - * Set the result of sending. - * - * @param int $result - */ - public function setResult($result) - { - $this->result = $result; - } + /** + * Set the result of sending. + * + * @param int $result + */ + public function setResult($result) + { + $this->result = $result; + } - /** - * Get the result of this Event. - * - * The return value is a bitmask from - * {@see RESULT_PENDING, RESULT_SUCCESS, RESULT_TENTATIVE, RESULT_FAILED} - * - * @return int - */ - public function getResult() - { - return $this->result; - } + /** + * Get the result of this Event. + * + * The return value is a bitmask from + * {@see RESULT_PENDING, RESULT_SUCCESS, RESULT_TENTATIVE, RESULT_FAILED} + * + * @return int + */ + public function getResult() + { + return $this->result; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/SendListener.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/SendListener.php index 33f7f03f870..f7bf55ef56c 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/SendListener.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/SendListener.php @@ -15,13 +15,13 @@ */ interface Swift_Events_SendListener extends Swift_Events_EventListener { - /** - * Invoked immediately before the Message is sent. - */ - public function beforeSendPerformed(Swift_Events_SendEvent $evt); + /** + * Invoked immediately before the Message is sent. + */ + public function beforeSendPerformed(Swift_Events_SendEvent $evt); - /** - * Invoked immediately after the Message is sent. - */ - public function sendPerformed(Swift_Events_SendEvent $evt); + /** + * Invoked immediately after the Message is sent. + */ + public function sendPerformed(Swift_Events_SendEvent $evt); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/SimpleEventDispatcher.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/SimpleEventDispatcher.php index 7531214d824..6557103c99a 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/SimpleEventDispatcher.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/SimpleEventDispatcher.php @@ -15,128 +15,128 @@ */ class Swift_Events_SimpleEventDispatcher implements Swift_Events_EventDispatcher { - /** A map of event types to their associated listener types */ - private $eventMap = []; + /** A map of event types to their associated listener types */ + private $eventMap = []; - /** Event listeners bound to this dispatcher */ - private $listeners = []; + /** Event listeners bound to this dispatcher */ + private $listeners = []; - /** - * Create a new EventDispatcher. - */ - public function __construct() - { - $this->eventMap = [ - 'Swift_Events_CommandEvent' => 'Swift_Events_CommandListener', - 'Swift_Events_ResponseEvent' => 'Swift_Events_ResponseListener', - 'Swift_Events_SendEvent' => 'Swift_Events_SendListener', - 'Swift_Events_TransportChangeEvent' => 'Swift_Events_TransportChangeListener', - 'Swift_Events_TransportExceptionEvent' => 'Swift_Events_TransportExceptionListener', - ]; - } + /** + * Create a new EventDispatcher. + */ + public function __construct() + { + $this->eventMap = [ + 'Swift_Events_CommandEvent' => 'Swift_Events_CommandListener', + 'Swift_Events_ResponseEvent' => 'Swift_Events_ResponseListener', + 'Swift_Events_SendEvent' => 'Swift_Events_SendListener', + 'Swift_Events_TransportChangeEvent' => 'Swift_Events_TransportChangeListener', + 'Swift_Events_TransportExceptionEvent' => 'Swift_Events_TransportExceptionListener', + ]; + } - /** - * Create a new SendEvent for $source and $message. - * - * @return Swift_Events_SendEvent - */ - public function createSendEvent(Swift_Transport $source, Swift_Mime_SimpleMessage $message) - { - return new Swift_Events_SendEvent($source, $message); - } + /** + * Create a new SendEvent for $source and $message. + * + * @return Swift_Events_SendEvent + */ + public function createSendEvent(Swift_Transport $source, Swift_Mime_SimpleMessage $message) + { + return new Swift_Events_SendEvent($source, $message); + } - /** - * Create a new CommandEvent for $source and $command. - * - * @param string $command That will be executed - * @param array $successCodes That are needed - * - * @return Swift_Events_CommandEvent - */ - public function createCommandEvent(Swift_Transport $source, $command, $successCodes = []) - { - return new Swift_Events_CommandEvent($source, $command, $successCodes); - } + /** + * Create a new CommandEvent for $source and $command. + * + * @param string $command That will be executed + * @param array $successCodes That are needed + * + * @return Swift_Events_CommandEvent + */ + public function createCommandEvent(Swift_Transport $source, $command, $successCodes = []) + { + return new Swift_Events_CommandEvent($source, $command, $successCodes); + } - /** - * Create a new ResponseEvent for $source and $response. - * - * @param string $response - * @param bool $valid If the response is valid - * - * @return Swift_Events_ResponseEvent - */ - public function createResponseEvent(Swift_Transport $source, $response, $valid) - { - return new Swift_Events_ResponseEvent($source, $response, $valid); - } + /** + * Create a new ResponseEvent for $source and $response. + * + * @param string $response + * @param bool $valid If the response is valid + * + * @return Swift_Events_ResponseEvent + */ + public function createResponseEvent(Swift_Transport $source, $response, $valid) + { + return new Swift_Events_ResponseEvent($source, $response, $valid); + } - /** - * Create a new TransportChangeEvent for $source. - * - * @return Swift_Events_TransportChangeEvent - */ - public function createTransportChangeEvent(Swift_Transport $source) - { - return new Swift_Events_TransportChangeEvent($source); - } + /** + * Create a new TransportChangeEvent for $source. + * + * @return Swift_Events_TransportChangeEvent + */ + public function createTransportChangeEvent(Swift_Transport $source) + { + return new Swift_Events_TransportChangeEvent($source); + } - /** - * Create a new TransportExceptionEvent for $source. - * - * @return Swift_Events_TransportExceptionEvent - */ - public function createTransportExceptionEvent(Swift_Transport $source, Swift_TransportException $ex) - { - return new Swift_Events_TransportExceptionEvent($source, $ex); - } + /** + * Create a new TransportExceptionEvent for $source. + * + * @return Swift_Events_TransportExceptionEvent + */ + public function createTransportExceptionEvent(Swift_Transport $source, Swift_TransportException $ex) + { + return new Swift_Events_TransportExceptionEvent($source, $ex); + } - /** - * Bind an event listener to this dispatcher. - */ - public function bindEventListener(Swift_Events_EventListener $listener) - { - foreach ($this->listeners as $l) { - // Already loaded - if ($l === $listener) { - return; - } - } - $this->listeners[] = $listener; - } + /** + * Bind an event listener to this dispatcher. + */ + public function bindEventListener(Swift_Events_EventListener $listener) + { + foreach ($this->listeners as $l) { + // Already loaded + if ($l === $listener) { + return; + } + } + $this->listeners[] = $listener; + } - /** - * Dispatch the given Event to all suitable listeners. - * - * @param string $target method - */ - public function dispatchEvent(Swift_Events_EventObject $evt, $target) - { - $bubbleQueue = $this->prepareBubbleQueue($evt); - $this->bubble($bubbleQueue, $evt, $target); - } + /** + * Dispatch the given Event to all suitable listeners. + * + * @param string $target method + */ + public function dispatchEvent(Swift_Events_EventObject $evt, $target) + { + $bubbleQueue = $this->prepareBubbleQueue($evt); + $this->bubble($bubbleQueue, $evt, $target); + } - /** Queue listeners on a stack ready for $evt to be bubbled up it */ - private function prepareBubbleQueue(Swift_Events_EventObject $evt) - { - $bubbleQueue = []; - $evtClass = \get_class($evt); - foreach ($this->listeners as $listener) { - if (\array_key_exists($evtClass, $this->eventMap) - && ($listener instanceof $this->eventMap[$evtClass])) { - $bubbleQueue[] = $listener; - } - } + /** Queue listeners on a stack ready for $evt to be bubbled up it */ + private function prepareBubbleQueue(Swift_Events_EventObject $evt) + { + $bubbleQueue = []; + $evtClass = \get_class($evt); + foreach ($this->listeners as $listener) { + if (\array_key_exists($evtClass, $this->eventMap) + && ($listener instanceof $this->eventMap[$evtClass])) { + $bubbleQueue[] = $listener; + } + } - return $bubbleQueue; - } + return $bubbleQueue; + } - /** Bubble $evt up the stack calling $target() on each listener */ - private function bubble(array &$bubbleQueue, Swift_Events_EventObject $evt, $target) - { - if (!$evt->bubbleCancelled() && $listener = array_shift($bubbleQueue)) { - $listener->$target($evt); - $this->bubble($bubbleQueue, $evt, $target); - } - } + /** Bubble $evt up the stack calling $target() on each listener */ + private function bubble(array &$bubbleQueue, Swift_Events_EventObject $evt, $target) + { + if (!$evt->bubbleCancelled() && $listener = array_shift($bubbleQueue)) { + $listener->$target($evt); + $this->bubble($bubbleQueue, $evt, $target); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/TransportChangeListener.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/TransportChangeListener.php index 24d6bde50bd..4a7492bc551 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/TransportChangeListener.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/TransportChangeListener.php @@ -15,23 +15,23 @@ */ interface Swift_Events_TransportChangeListener extends Swift_Events_EventListener { - /** - * Invoked just before a Transport is started. - */ - public function beforeTransportStarted(Swift_Events_TransportChangeEvent $evt); + /** + * Invoked just before a Transport is started. + */ + public function beforeTransportStarted(Swift_Events_TransportChangeEvent $evt); - /** - * Invoked immediately after the Transport is started. - */ - public function transportStarted(Swift_Events_TransportChangeEvent $evt); + /** + * Invoked immediately after the Transport is started. + */ + public function transportStarted(Swift_Events_TransportChangeEvent $evt); - /** - * Invoked just before a Transport is stopped. - */ - public function beforeTransportStopped(Swift_Events_TransportChangeEvent $evt); + /** + * Invoked just before a Transport is stopped. + */ + public function beforeTransportStopped(Swift_Events_TransportChangeEvent $evt); - /** - * Invoked immediately after the Transport is stopped. - */ - public function transportStopped(Swift_Events_TransportChangeEvent $evt); + /** + * Invoked immediately after the Transport is stopped. + */ + public function transportStopped(Swift_Events_TransportChangeEvent $evt); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/TransportExceptionEvent.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/TransportExceptionEvent.php index 0301c8dfc11..df442cc70f6 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/TransportExceptionEvent.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/TransportExceptionEvent.php @@ -15,29 +15,29 @@ */ class Swift_Events_TransportExceptionEvent extends Swift_Events_EventObject { - /** - * The Exception thrown. - * - * @var Swift_TransportException - */ - private $exception; + /** + * The Exception thrown. + * + * @var Swift_TransportException + */ + private $exception; - /** - * Create a new TransportExceptionEvent for $transport. - */ - public function __construct(Swift_Transport $transport, Swift_TransportException $ex) - { - parent::__construct($transport); - $this->exception = $ex; - } + /** + * Create a new TransportExceptionEvent for $transport. + */ + public function __construct(Swift_Transport $transport, Swift_TransportException $ex) + { + parent::__construct($transport); + $this->exception = $ex; + } - /** - * Get the TransportException thrown. - * - * @return Swift_TransportException - */ - public function getException() - { - return $this->exception; - } + /** + * Get the TransportException thrown. + * + * @return Swift_TransportException + */ + public function getException() + { + return $this->exception; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/TransportExceptionListener.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/TransportExceptionListener.php index 1de6e6e59a9..ad80eb01d0f 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Events/TransportExceptionListener.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Events/TransportExceptionListener.php @@ -15,8 +15,8 @@ */ interface Swift_Events_TransportExceptionListener extends Swift_Events_EventListener { - /** - * Invoked as a TransportException is thrown in the Transport system. - */ - public function exceptionThrown(Swift_Events_TransportExceptionEvent $evt); + /** + * Invoked as a TransportException is thrown in the Transport system. + */ + public function exceptionThrown(Swift_Events_TransportExceptionEvent $evt); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/FailoverTransport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/FailoverTransport.php index 57d343c9ed3..af0be917903 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/FailoverTransport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/FailoverTransport.php @@ -15,19 +15,19 @@ */ class Swift_FailoverTransport extends Swift_Transport_FailoverTransport { - /** - * Creates a new FailoverTransport with $transports. - * - * @param Swift_Transport[] $transports - */ - public function __construct($transports = []) - { - \call_user_func_array( - [$this, 'Swift_Transport_FailoverTransport::__construct'], - Swift_DependencyContainer::getInstance() - ->createDependenciesFor('transport.failover') - ); + /** + * Creates a new FailoverTransport with $transports. + * + * @param Swift_Transport[] $transports + */ + public function __construct($transports = []) + { + \call_user_func_array( + [$this, 'Swift_Transport_FailoverTransport::__construct'], + Swift_DependencyContainer::getInstance() + ->createDependenciesFor('transport.failover') + ); - $this->setTransports($transports); - } + $this->setTransports($transports); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/FileSpool.php b/htdocs/includes/swiftmailer/lib/classes/Swift/FileSpool.php index 4dd49a65270..7af8471c9d7 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/FileSpool.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/FileSpool.php @@ -16,193 +16,193 @@ */ class Swift_FileSpool extends Swift_ConfigurableSpool { - /** The spool directory */ - private $path; + /** The spool directory */ + private $path; - /** - * File WriteRetry Limit. - * - * @var int - */ - private $retryLimit = 10; + /** + * File WriteRetry Limit. + * + * @var int + */ + private $retryLimit = 10; - /** - * Create a new FileSpool. - * - * @param string $path - * - * @throws Swift_IoException - */ - public function __construct($path) - { - $this->path = $path; + /** + * Create a new FileSpool. + * + * @param string $path + * + * @throws Swift_IoException + */ + public function __construct($path) + { + $this->path = $path; - if (!file_exists($this->path)) { - if (!mkdir($this->path, 0777, true)) { - throw new Swift_IoException(sprintf('Unable to create path "%s".', $this->path)); - } - } - } + if (!file_exists($this->path)) { + if (!mkdir($this->path, 0777, true)) { + throw new Swift_IoException(sprintf('Unable to create path "%s".', $this->path)); + } + } + } - /** - * Tests if this Spool mechanism has started. - * - * @return bool - */ - public function isStarted() - { - return true; - } + /** + * Tests if this Spool mechanism has started. + * + * @return bool + */ + public function isStarted() + { + return true; + } - /** - * Starts this Spool mechanism. - */ - public function start() - { - } + /** + * Starts this Spool mechanism. + */ + public function start() + { + } - /** - * Stops this Spool mechanism. - */ - public function stop() - { - } + /** + * Stops this Spool mechanism. + */ + public function stop() + { + } - /** - * Allow to manage the enqueuing retry limit. - * - * Default, is ten and allows over 64^20 different fileNames - * - * @param int $limit - */ - public function setRetryLimit($limit) - { - $this->retryLimit = $limit; - } + /** + * Allow to manage the enqueuing retry limit. + * + * Default, is ten and allows over 64^20 different fileNames + * + * @param int $limit + */ + public function setRetryLimit($limit) + { + $this->retryLimit = $limit; + } - /** - * Queues a message. - * - * @param Swift_Mime_SimpleMessage $message The message to store - * - * @throws Swift_IoException - * - * @return bool - */ - public function queueMessage(Swift_Mime_SimpleMessage $message) - { - $ser = serialize($message); - $fileName = $this->path.'/'.$this->getRandomString(10); - for ($i = 0; $i < $this->retryLimit; ++$i) { - /* We try an exclusive creation of the file. This is an atomic operation, it avoid locking mechanism */ - $fp = @fopen($fileName.'.message', 'xb'); - if (false !== $fp) { - if (false === fwrite($fp, $ser)) { - return false; - } + /** + * Queues a message. + * + * @param Swift_Mime_SimpleMessage $message The message to store + * + * @throws Swift_IoException + * + * @return bool + */ + public function queueMessage(Swift_Mime_SimpleMessage $message) + { + $ser = serialize($message); + $fileName = $this->path.'/'.$this->getRandomString(10); + for ($i = 0; $i < $this->retryLimit; ++$i) { + /* We try an exclusive creation of the file. This is an atomic operation, it avoid locking mechanism */ + $fp = @fopen($fileName.'.message', 'xb'); + if (false !== $fp) { + if (false === fwrite($fp, $ser)) { + return false; + } - return fclose($fp); - } else { - /* The file already exists, we try a longer fileName */ - $fileName .= $this->getRandomString(1); - } - } + return fclose($fp); + } else { + /* The file already exists, we try a longer fileName */ + $fileName .= $this->getRandomString(1); + } + } - throw new Swift_IoException(sprintf('Unable to create a file for enqueuing Message in "%s".', $this->path)); - } + throw new Swift_IoException(sprintf('Unable to create a file for enqueuing Message in "%s".', $this->path)); + } - /** - * Execute a recovery if for any reason a process is sending for too long. - * - * @param int $timeout in second Defaults is for very slow smtp responses - */ - public function recover($timeout = 900) - { - foreach (new DirectoryIterator($this->path) as $file) { - $file = $file->getRealPath(); + /** + * Execute a recovery if for any reason a process is sending for too long. + * + * @param int $timeout in second Defaults is for very slow smtp responses + */ + public function recover($timeout = 900) + { + foreach (new DirectoryIterator($this->path) as $file) { + $file = $file->getRealPath(); - if ('.message.sending' == substr($file, -16)) { - $lockedtime = filectime($file); - if ((time() - $lockedtime) > $timeout) { - rename($file, substr($file, 0, -8)); - } - } - } - } + if ('.message.sending' == substr($file, -16)) { + $lockedtime = filectime($file); + if ((time() - $lockedtime) > $timeout) { + rename($file, substr($file, 0, -8)); + } + } + } + } - /** - * Sends messages using the given transport instance. - * - * @param Swift_Transport $transport A transport instance - * @param string[] $failedRecipients An array of failures by-reference - * - * @return int The number of sent e-mail's - */ - public function flushQueue(Swift_Transport $transport, &$failedRecipients = null) - { - $directoryIterator = new DirectoryIterator($this->path); + /** + * Sends messages using the given transport instance. + * + * @param Swift_Transport $transport A transport instance + * @param string[] $failedRecipients An array of failures by-reference + * + * @return int The number of sent e-mail's + */ + public function flushQueue(Swift_Transport $transport, &$failedRecipients = null) + { + $directoryIterator = new DirectoryIterator($this->path); - /* Start the transport only if there are queued files to send */ - if (!$transport->isStarted()) { - foreach ($directoryIterator as $file) { - if ('.message' == substr($file->getRealPath(), -8)) { - $transport->start(); - break; - } - } - } + /* Start the transport only if there are queued files to send */ + if (!$transport->isStarted()) { + foreach ($directoryIterator as $file) { + if ('.message' == substr($file->getRealPath(), -8)) { + $transport->start(); + break; + } + } + } - $failedRecipients = (array) $failedRecipients; - $count = 0; - $time = time(); - foreach ($directoryIterator as $file) { - $file = $file->getRealPath(); + $failedRecipients = (array) $failedRecipients; + $count = 0; + $time = time(); + foreach ($directoryIterator as $file) { + $file = $file->getRealPath(); - if ('.message' != substr($file, -8)) { - continue; - } + if ('.message' != substr($file, -8)) { + continue; + } - /* We try a rename, it's an atomic operation, and avoid locking the file */ - if (rename($file, $file.'.sending')) { - $message = unserialize(file_get_contents($file.'.sending')); + /* We try a rename, it's an atomic operation, and avoid locking the file */ + if (rename($file, $file.'.sending')) { + $message = unserialize(file_get_contents($file.'.sending')); - $count += $transport->send($message, $failedRecipients); + $count += $transport->send($message, $failedRecipients); - unlink($file.'.sending'); - } else { - /* This message has just been catched by another process */ - continue; - } + unlink($file.'.sending'); + } else { + /* This message has just been catched by another process */ + continue; + } - if ($this->getMessageLimit() && $count >= $this->getMessageLimit()) { - break; - } + if ($this->getMessageLimit() && $count >= $this->getMessageLimit()) { + break; + } - if ($this->getTimeLimit() && (time() - $time) >= $this->getTimeLimit()) { - break; - } - } + if ($this->getTimeLimit() && (time() - $time) >= $this->getTimeLimit()) { + break; + } + } - return $count; - } + return $count; + } - /** - * Returns a random string needed to generate a fileName for the queue. - * - * @param int $count - * - * @return string - */ - protected function getRandomString($count) - { - // This string MUST stay FS safe, avoid special chars - $base = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-'; - $ret = ''; - $strlen = \strlen($base); - for ($i = 0; $i < $count; ++$i) { - $ret .= $base[random_int(0, $strlen - 1)]; - } + /** + * Returns a random string needed to generate a fileName for the queue. + * + * @param int $count + * + * @return string + */ + protected function getRandomString($count) + { + // This string MUST stay FS safe, avoid special chars + $base = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-'; + $ret = ''; + $strlen = \strlen($base); + for ($i = 0; $i < $count; ++$i) { + $ret .= $base[random_int(0, $strlen - 1)]; + } - return $ret; - } + return $ret; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Filterable.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Filterable.php index 9073bf5b663..efa1b1def5e 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Filterable.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Filterable.php @@ -15,17 +15,17 @@ */ interface Swift_Filterable { - /** - * Add a new StreamFilter, referenced by $key. - * - * @param string $key - */ - public function addFilter(Swift_StreamFilter $filter, $key); + /** + * Add a new StreamFilter, referenced by $key. + * + * @param string $key + */ + public function addFilter(Swift_StreamFilter $filter, $key); - /** - * Remove an existing filter using $key. - * - * @param string $key - */ - public function removeFilter($key); + /** + * Remove an existing filter using $key. + * + * @param string $key + */ + public function removeFilter($key); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/InputByteStream.php b/htdocs/includes/swiftmailer/lib/classes/Swift/InputByteStream.php index 67a12acc6f5..379a5a17870 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/InputByteStream.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/InputByteStream.php @@ -18,58 +18,58 @@ */ interface Swift_InputByteStream { - /** - * Writes $bytes to the end of the stream. - * - * Writing may not happen immediately if the stream chooses to buffer. If - * you want to write these bytes with immediate effect, call {@link commit()} - * after calling write(). - * - * This method returns the sequence ID of the write (i.e. 1 for first, 2 for - * second, etc etc). - * - * @param string $bytes - * - * @throws Swift_IoException - * - * @return int - */ - public function write($bytes); + /** + * Writes $bytes to the end of the stream. + * + * Writing may not happen immediately if the stream chooses to buffer. If + * you want to write these bytes with immediate effect, call {@link commit()} + * after calling write(). + * + * This method returns the sequence ID of the write (i.e. 1 for first, 2 for + * second, etc etc). + * + * @param string $bytes + * + * @throws Swift_IoException + * + * @return int + */ + public function write($bytes); - /** - * For any bytes that are currently buffered inside the stream, force them - * off the buffer. - * - * @throws Swift_IoException - */ - public function commit(); + /** + * For any bytes that are currently buffered inside the stream, force them + * off the buffer. + * + * @throws Swift_IoException + */ + public function commit(); - /** - * Attach $is to this stream. - * - * The stream acts as an observer, receiving all data that is written. - * All {@link write()} and {@link flushBuffers()} operations will be mirrored. - * - * @param Swift_InputByteStream $is - */ - public function bind(self $is); + /** + * Attach $is to this stream. + * + * The stream acts as an observer, receiving all data that is written. + * All {@link write()} and {@link flushBuffers()} operations will be mirrored. + * + * @param Swift_InputByteStream $is + */ + public function bind(self $is); - /** - * Remove an already bound stream. - * - * If $is is not bound, no errors will be raised. - * If the stream currently has any buffered data it will be written to $is - * before unbinding occurs. - * - * @param Swift_InputByteStream $is - */ - public function unbind(self $is); + /** + * Remove an already bound stream. + * + * If $is is not bound, no errors will be raised. + * If the stream currently has any buffered data it will be written to $is + * before unbinding occurs. + * + * @param Swift_InputByteStream $is + */ + public function unbind(self $is); - /** - * Flush the contents of the stream (empty it) and set the internal pointer - * to the beginning. - * - * @throws Swift_IoException - */ - public function flushBuffers(); + /** + * Flush the contents of the stream (empty it) and set the internal pointer + * to the beginning. + * + * @throws Swift_IoException + */ + public function flushBuffers(); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/IoException.php b/htdocs/includes/swiftmailer/lib/classes/Swift/IoException.php index 8a8b9ff9029..5452bd416a6 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/IoException.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/IoException.php @@ -15,14 +15,14 @@ */ class Swift_IoException extends Swift_SwiftException { - /** - * Create a new IoException with $message. - * - * @param string $message - * @param int $code - */ - public function __construct($message, $code = 0, Exception $previous = null) - { - parent::__construct($message, $code, $previous); - } + /** + * Create a new IoException with $message. + * + * @param string $message + * @param int $code + */ + public function __construct($message, $code = 0, Exception $previous = null) + { + parent::__construct($message, $code, $previous); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache.php b/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache.php index 791085d85e7..87f6a074212 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache.php @@ -15,90 +15,90 @@ */ interface Swift_KeyCache { - /** Mode for replacing existing cached data */ - const MODE_WRITE = 1; + /** Mode for replacing existing cached data */ + const MODE_WRITE = 1; - /** Mode for appending data to the end of existing cached data */ - const MODE_APPEND = 2; + /** Mode for appending data to the end of existing cached data */ + const MODE_APPEND = 2; - /** - * Set a string into the cache under $itemKey for the namespace $nsKey. - * - * @see MODE_WRITE, MODE_APPEND - * - * @param string $nsKey - * @param string $itemKey - * @param string $string - * @param int $mode - */ - public function setString($nsKey, $itemKey, $string, $mode); + /** + * Set a string into the cache under $itemKey for the namespace $nsKey. + * + * @see MODE_WRITE, MODE_APPEND + * + * @param string $nsKey + * @param string $itemKey + * @param string $string + * @param int $mode + */ + public function setString($nsKey, $itemKey, $string, $mode); - /** - * Set a ByteStream into the cache under $itemKey for the namespace $nsKey. - * - * @see MODE_WRITE, MODE_APPEND - * - * @param string $nsKey - * @param string $itemKey - * @param int $mode - */ - public function importFromByteStream($nsKey, $itemKey, Swift_OutputByteStream $os, $mode); + /** + * Set a ByteStream into the cache under $itemKey for the namespace $nsKey. + * + * @see MODE_WRITE, MODE_APPEND + * + * @param string $nsKey + * @param string $itemKey + * @param int $mode + */ + public function importFromByteStream($nsKey, $itemKey, Swift_OutputByteStream $os, $mode); - /** - * Provides a ByteStream which when written to, writes data to $itemKey. - * - * NOTE: The stream will always write in append mode. - * If the optional third parameter is passed all writes will go through $is. - * - * @param string $nsKey - * @param string $itemKey - * @param Swift_InputByteStream $is optional input stream - * - * @return Swift_InputByteStream - */ - public function getInputByteStream($nsKey, $itemKey, Swift_InputByteStream $is = null); + /** + * Provides a ByteStream which when written to, writes data to $itemKey. + * + * NOTE: The stream will always write in append mode. + * If the optional third parameter is passed all writes will go through $is. + * + * @param string $nsKey + * @param string $itemKey + * @param Swift_InputByteStream $is optional input stream + * + * @return Swift_InputByteStream + */ + public function getInputByteStream($nsKey, $itemKey, Swift_InputByteStream $is = null); - /** - * Get data back out of the cache as a string. - * - * @param string $nsKey - * @param string $itemKey - * - * @return string - */ - public function getString($nsKey, $itemKey); + /** + * Get data back out of the cache as a string. + * + * @param string $nsKey + * @param string $itemKey + * + * @return string + */ + public function getString($nsKey, $itemKey); - /** - * Get data back out of the cache as a ByteStream. - * - * @param string $nsKey - * @param string $itemKey - * @param Swift_InputByteStream $is stream to write the data to - */ - public function exportToByteStream($nsKey, $itemKey, Swift_InputByteStream $is); + /** + * Get data back out of the cache as a ByteStream. + * + * @param string $nsKey + * @param string $itemKey + * @param Swift_InputByteStream $is stream to write the data to + */ + public function exportToByteStream($nsKey, $itemKey, Swift_InputByteStream $is); - /** - * Check if the given $itemKey exists in the namespace $nsKey. - * - * @param string $nsKey - * @param string $itemKey - * - * @return bool - */ - public function hasKey($nsKey, $itemKey); + /** + * Check if the given $itemKey exists in the namespace $nsKey. + * + * @param string $nsKey + * @param string $itemKey + * + * @return bool + */ + public function hasKey($nsKey, $itemKey); - /** - * Clear data for $itemKey in the namespace $nsKey if it exists. - * - * @param string $nsKey - * @param string $itemKey - */ - public function clearKey($nsKey, $itemKey); + /** + * Clear data for $itemKey in the namespace $nsKey if it exists. + * + * @param string $nsKey + * @param string $itemKey + */ + public function clearKey($nsKey, $itemKey); - /** - * Clear all data in the namespace $nsKey if it exists. - * - * @param string $nsKey - */ - public function clearAll($nsKey); + /** + * Clear all data in the namespace $nsKey if it exists. + * + * @param string $nsKey + */ + public function clearAll($nsKey); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/ArrayKeyCache.php b/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/ArrayKeyCache.php index 92a6c2d107e..e8fef1c95d4 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/ArrayKeyCache.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/ArrayKeyCache.php @@ -15,183 +15,183 @@ */ class Swift_KeyCache_ArrayKeyCache implements Swift_KeyCache { - /** - * Cache contents. - * - * @var array - */ - private $contents = []; + /** + * Cache contents. + * + * @var array + */ + private $contents = []; - /** - * An InputStream for cloning. - * - * @var Swift_KeyCache_KeyCacheInputStream - */ - private $stream; + /** + * An InputStream for cloning. + * + * @var Swift_KeyCache_KeyCacheInputStream + */ + private $stream; - /** - * Create a new ArrayKeyCache with the given $stream for cloning to make - * InputByteStreams. - */ - public function __construct(Swift_KeyCache_KeyCacheInputStream $stream) - { - $this->stream = $stream; - } + /** + * Create a new ArrayKeyCache with the given $stream for cloning to make + * InputByteStreams. + */ + public function __construct(Swift_KeyCache_KeyCacheInputStream $stream) + { + $this->stream = $stream; + } - /** - * Set a string into the cache under $itemKey for the namespace $nsKey. - * - * @see MODE_WRITE, MODE_APPEND - * - * @param string $nsKey - * @param string $itemKey - * @param string $string - * @param int $mode - */ - public function setString($nsKey, $itemKey, $string, $mode) - { - $this->prepareCache($nsKey); - switch ($mode) { - case self::MODE_WRITE: - $this->contents[$nsKey][$itemKey] = $string; - break; - case self::MODE_APPEND: - if (!$this->hasKey($nsKey, $itemKey)) { - $this->contents[$nsKey][$itemKey] = ''; - } - $this->contents[$nsKey][$itemKey] .= $string; - break; - default: - throw new Swift_SwiftException('Invalid mode ['.$mode.'] used to set nsKey='.$nsKey.', itemKey='.$itemKey); - } - } + /** + * Set a string into the cache under $itemKey for the namespace $nsKey. + * + * @see MODE_WRITE, MODE_APPEND + * + * @param string $nsKey + * @param string $itemKey + * @param string $string + * @param int $mode + */ + public function setString($nsKey, $itemKey, $string, $mode) + { + $this->prepareCache($nsKey); + switch ($mode) { + case self::MODE_WRITE: + $this->contents[$nsKey][$itemKey] = $string; + break; + case self::MODE_APPEND: + if (!$this->hasKey($nsKey, $itemKey)) { + $this->contents[$nsKey][$itemKey] = ''; + } + $this->contents[$nsKey][$itemKey] .= $string; + break; + default: + throw new Swift_SwiftException('Invalid mode ['.$mode.'] used to set nsKey='.$nsKey.', itemKey='.$itemKey); + } + } - /** - * Set a ByteStream into the cache under $itemKey for the namespace $nsKey. - * - * @see MODE_WRITE, MODE_APPEND - * - * @param string $nsKey - * @param string $itemKey - * @param int $mode - */ - public function importFromByteStream($nsKey, $itemKey, Swift_OutputByteStream $os, $mode) - { - $this->prepareCache($nsKey); - switch ($mode) { - case self::MODE_WRITE: - $this->clearKey($nsKey, $itemKey); - // no break - case self::MODE_APPEND: - if (!$this->hasKey($nsKey, $itemKey)) { - $this->contents[$nsKey][$itemKey] = ''; - } - while (false !== $bytes = $os->read(8192)) { - $this->contents[$nsKey][$itemKey] .= $bytes; - } - break; - default: - throw new Swift_SwiftException('Invalid mode ['.$mode.'] used to set nsKey='.$nsKey.', itemKey='.$itemKey); - } - } + /** + * Set a ByteStream into the cache under $itemKey for the namespace $nsKey. + * + * @see MODE_WRITE, MODE_APPEND + * + * @param string $nsKey + * @param string $itemKey + * @param int $mode + */ + public function importFromByteStream($nsKey, $itemKey, Swift_OutputByteStream $os, $mode) + { + $this->prepareCache($nsKey); + switch ($mode) { + case self::MODE_WRITE: + $this->clearKey($nsKey, $itemKey); + // no break + case self::MODE_APPEND: + if (!$this->hasKey($nsKey, $itemKey)) { + $this->contents[$nsKey][$itemKey] = ''; + } + while (false !== $bytes = $os->read(8192)) { + $this->contents[$nsKey][$itemKey] .= $bytes; + } + break; + default: + throw new Swift_SwiftException('Invalid mode ['.$mode.'] used to set nsKey='.$nsKey.', itemKey='.$itemKey); + } + } - /** - * Provides a ByteStream which when written to, writes data to $itemKey. - * - * NOTE: The stream will always write in append mode. - * - * @param string $nsKey - * @param string $itemKey - * - * @return Swift_InputByteStream - */ - public function getInputByteStream($nsKey, $itemKey, Swift_InputByteStream $writeThrough = null) - { - $is = clone $this->stream; - $is->setKeyCache($this); - $is->setNsKey($nsKey); - $is->setItemKey($itemKey); - if (isset($writeThrough)) { - $is->setWriteThroughStream($writeThrough); - } + /** + * Provides a ByteStream which when written to, writes data to $itemKey. + * + * NOTE: The stream will always write in append mode. + * + * @param string $nsKey + * @param string $itemKey + * + * @return Swift_InputByteStream + */ + public function getInputByteStream($nsKey, $itemKey, Swift_InputByteStream $writeThrough = null) + { + $is = clone $this->stream; + $is->setKeyCache($this); + $is->setNsKey($nsKey); + $is->setItemKey($itemKey); + if (isset($writeThrough)) { + $is->setWriteThroughStream($writeThrough); + } - return $is; - } + return $is; + } - /** - * Get data back out of the cache as a string. - * - * @param string $nsKey - * @param string $itemKey - * - * @return string - */ - public function getString($nsKey, $itemKey) - { - $this->prepareCache($nsKey); - if ($this->hasKey($nsKey, $itemKey)) { - return $this->contents[$nsKey][$itemKey]; - } - } + /** + * Get data back out of the cache as a string. + * + * @param string $nsKey + * @param string $itemKey + * + * @return string + */ + public function getString($nsKey, $itemKey) + { + $this->prepareCache($nsKey); + if ($this->hasKey($nsKey, $itemKey)) { + return $this->contents[$nsKey][$itemKey]; + } + } - /** - * Get data back out of the cache as a ByteStream. - * - * @param string $nsKey - * @param string $itemKey - * @param Swift_InputByteStream $is to write the data to - */ - public function exportToByteStream($nsKey, $itemKey, Swift_InputByteStream $is) - { - $this->prepareCache($nsKey); - $is->write($this->getString($nsKey, $itemKey)); - } + /** + * Get data back out of the cache as a ByteStream. + * + * @param string $nsKey + * @param string $itemKey + * @param Swift_InputByteStream $is to write the data to + */ + public function exportToByteStream($nsKey, $itemKey, Swift_InputByteStream $is) + { + $this->prepareCache($nsKey); + $is->write($this->getString($nsKey, $itemKey)); + } - /** - * Check if the given $itemKey exists in the namespace $nsKey. - * - * @param string $nsKey - * @param string $itemKey - * - * @return bool - */ - public function hasKey($nsKey, $itemKey) - { - $this->prepareCache($nsKey); + /** + * Check if the given $itemKey exists in the namespace $nsKey. + * + * @param string $nsKey + * @param string $itemKey + * + * @return bool + */ + public function hasKey($nsKey, $itemKey) + { + $this->prepareCache($nsKey); - return \array_key_exists($itemKey, $this->contents[$nsKey]); - } + return \array_key_exists($itemKey, $this->contents[$nsKey]); + } - /** - * Clear data for $itemKey in the namespace $nsKey if it exists. - * - * @param string $nsKey - * @param string $itemKey - */ - public function clearKey($nsKey, $itemKey) - { - unset($this->contents[$nsKey][$itemKey]); - } + /** + * Clear data for $itemKey in the namespace $nsKey if it exists. + * + * @param string $nsKey + * @param string $itemKey + */ + public function clearKey($nsKey, $itemKey) + { + unset($this->contents[$nsKey][$itemKey]); + } - /** - * Clear all data in the namespace $nsKey if it exists. - * - * @param string $nsKey - */ - public function clearAll($nsKey) - { - unset($this->contents[$nsKey]); - } + /** + * Clear all data in the namespace $nsKey if it exists. + * + * @param string $nsKey + */ + public function clearAll($nsKey) + { + unset($this->contents[$nsKey]); + } - /** - * Initialize the namespace of $nsKey if needed. - * - * @param string $nsKey - */ - private function prepareCache($nsKey) - { - if (!\array_key_exists($nsKey, $this->contents)) { - $this->contents[$nsKey] = []; - } - } + /** + * Initialize the namespace of $nsKey if needed. + * + * @param string $nsKey + */ + private function prepareCache($nsKey) + { + if (!\array_key_exists($nsKey, $this->contents)) { + $this->contents[$nsKey] = []; + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/DiskKeyCache.php b/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/DiskKeyCache.php index 4075b928e13..33b6367cb8b 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/DiskKeyCache.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/DiskKeyCache.php @@ -15,280 +15,280 @@ */ class Swift_KeyCache_DiskKeyCache implements Swift_KeyCache { - /** Signal to place pointer at start of file */ - const POSITION_START = 0; + /** Signal to place pointer at start of file */ + const POSITION_START = 0; - /** Signal to place pointer at end of file */ - const POSITION_END = 1; + /** Signal to place pointer at end of file */ + const POSITION_END = 1; - /** Signal to leave pointer in whatever position it currently is */ - const POSITION_CURRENT = 2; + /** Signal to leave pointer in whatever position it currently is */ + const POSITION_CURRENT = 2; - /** - * An InputStream for cloning. - * - * @var Swift_KeyCache_KeyCacheInputStream - */ - private $stream; + /** + * An InputStream for cloning. + * + * @var Swift_KeyCache_KeyCacheInputStream + */ + private $stream; - /** - * A path to write to. - * - * @var string - */ - private $path; + /** + * A path to write to. + * + * @var string + */ + private $path; - /** - * Stored keys. - * - * @var array - */ - private $keys = []; + /** + * Stored keys. + * + * @var array + */ + private $keys = []; - /** - * Create a new DiskKeyCache with the given $stream for cloning to make - * InputByteStreams, and the given $path to save to. - * - * @param string $path to save to - */ - public function __construct(Swift_KeyCache_KeyCacheInputStream $stream, $path) - { - $this->stream = $stream; - $this->path = $path; - } + /** + * Create a new DiskKeyCache with the given $stream for cloning to make + * InputByteStreams, and the given $path to save to. + * + * @param string $path to save to + */ + public function __construct(Swift_KeyCache_KeyCacheInputStream $stream, $path) + { + $this->stream = $stream; + $this->path = $path; + } - /** - * Set a string into the cache under $itemKey for the namespace $nsKey. - * - * @see MODE_WRITE, MODE_APPEND - * - * @param string $nsKey - * @param string $itemKey - * @param string $string - * @param int $mode - * - * @throws Swift_IoException - */ - public function setString($nsKey, $itemKey, $string, $mode) - { - $this->prepareCache($nsKey); - switch ($mode) { - case self::MODE_WRITE: - $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_START); - break; - case self::MODE_APPEND: - $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_END); - break; - default: - throw new Swift_SwiftException('Invalid mode ['.$mode.'] used to set nsKey='.$nsKey.', itemKey='.$itemKey); - break; - } - fwrite($fp, $string); - $this->freeHandle($nsKey, $itemKey); - } + /** + * Set a string into the cache under $itemKey for the namespace $nsKey. + * + * @see MODE_WRITE, MODE_APPEND + * + * @param string $nsKey + * @param string $itemKey + * @param string $string + * @param int $mode + * + * @throws Swift_IoException + */ + public function setString($nsKey, $itemKey, $string, $mode) + { + $this->prepareCache($nsKey); + switch ($mode) { + case self::MODE_WRITE: + $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_START); + break; + case self::MODE_APPEND: + $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_END); + break; + default: + throw new Swift_SwiftException('Invalid mode ['.$mode.'] used to set nsKey='.$nsKey.', itemKey='.$itemKey); + break; + } + fwrite($fp, $string); + $this->freeHandle($nsKey, $itemKey); + } - /** - * Set a ByteStream into the cache under $itemKey for the namespace $nsKey. - * - * @see MODE_WRITE, MODE_APPEND - * - * @param string $nsKey - * @param string $itemKey - * @param int $mode - * - * @throws Swift_IoException - */ - public function importFromByteStream($nsKey, $itemKey, Swift_OutputByteStream $os, $mode) - { - $this->prepareCache($nsKey); - switch ($mode) { - case self::MODE_WRITE: - $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_START); - break; - case self::MODE_APPEND: - $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_END); - break; - default: - throw new Swift_SwiftException('Invalid mode ['.$mode.'] used to set nsKey='.$nsKey.', itemKey='.$itemKey); - break; - } - while (false !== $bytes = $os->read(8192)) { - fwrite($fp, $bytes); - } - $this->freeHandle($nsKey, $itemKey); - } + /** + * Set a ByteStream into the cache under $itemKey for the namespace $nsKey. + * + * @see MODE_WRITE, MODE_APPEND + * + * @param string $nsKey + * @param string $itemKey + * @param int $mode + * + * @throws Swift_IoException + */ + public function importFromByteStream($nsKey, $itemKey, Swift_OutputByteStream $os, $mode) + { + $this->prepareCache($nsKey); + switch ($mode) { + case self::MODE_WRITE: + $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_START); + break; + case self::MODE_APPEND: + $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_END); + break; + default: + throw new Swift_SwiftException('Invalid mode ['.$mode.'] used to set nsKey='.$nsKey.', itemKey='.$itemKey); + break; + } + while (false !== $bytes = $os->read(8192)) { + fwrite($fp, $bytes); + } + $this->freeHandle($nsKey, $itemKey); + } - /** - * Provides a ByteStream which when written to, writes data to $itemKey. - * - * NOTE: The stream will always write in append mode. - * - * @param string $nsKey - * @param string $itemKey - * - * @return Swift_InputByteStream - */ - public function getInputByteStream($nsKey, $itemKey, Swift_InputByteStream $writeThrough = null) - { - $is = clone $this->stream; - $is->setKeyCache($this); - $is->setNsKey($nsKey); - $is->setItemKey($itemKey); - if (isset($writeThrough)) { - $is->setWriteThroughStream($writeThrough); - } + /** + * Provides a ByteStream which when written to, writes data to $itemKey. + * + * NOTE: The stream will always write in append mode. + * + * @param string $nsKey + * @param string $itemKey + * + * @return Swift_InputByteStream + */ + public function getInputByteStream($nsKey, $itemKey, Swift_InputByteStream $writeThrough = null) + { + $is = clone $this->stream; + $is->setKeyCache($this); + $is->setNsKey($nsKey); + $is->setItemKey($itemKey); + if (isset($writeThrough)) { + $is->setWriteThroughStream($writeThrough); + } - return $is; - } + return $is; + } - /** - * Get data back out of the cache as a string. - * - * @param string $nsKey - * @param string $itemKey - * - * @throws Swift_IoException - * - * @return string - */ - public function getString($nsKey, $itemKey) - { - $this->prepareCache($nsKey); - if ($this->hasKey($nsKey, $itemKey)) { - $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_START); - $str = ''; - while (!feof($fp) && false !== $bytes = fread($fp, 8192)) { - $str .= $bytes; - } - $this->freeHandle($nsKey, $itemKey); + /** + * Get data back out of the cache as a string. + * + * @param string $nsKey + * @param string $itemKey + * + * @throws Swift_IoException + * + * @return string + */ + public function getString($nsKey, $itemKey) + { + $this->prepareCache($nsKey); + if ($this->hasKey($nsKey, $itemKey)) { + $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_START); + $str = ''; + while (!feof($fp) && false !== $bytes = fread($fp, 8192)) { + $str .= $bytes; + } + $this->freeHandle($nsKey, $itemKey); - return $str; - } - } + return $str; + } + } - /** - * Get data back out of the cache as a ByteStream. - * - * @param string $nsKey - * @param string $itemKey - * @param Swift_InputByteStream $is to write the data to - */ - public function exportToByteStream($nsKey, $itemKey, Swift_InputByteStream $is) - { - if ($this->hasKey($nsKey, $itemKey)) { - $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_START); - while (!feof($fp) && false !== $bytes = fread($fp, 8192)) { - $is->write($bytes); - } - $this->freeHandle($nsKey, $itemKey); - } - } + /** + * Get data back out of the cache as a ByteStream. + * + * @param string $nsKey + * @param string $itemKey + * @param Swift_InputByteStream $is to write the data to + */ + public function exportToByteStream($nsKey, $itemKey, Swift_InputByteStream $is) + { + if ($this->hasKey($nsKey, $itemKey)) { + $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_START); + while (!feof($fp) && false !== $bytes = fread($fp, 8192)) { + $is->write($bytes); + } + $this->freeHandle($nsKey, $itemKey); + } + } - /** - * Check if the given $itemKey exists in the namespace $nsKey. - * - * @param string $nsKey - * @param string $itemKey - * - * @return bool - */ - public function hasKey($nsKey, $itemKey) - { - return is_file($this->path.'/'.$nsKey.'/'.$itemKey); - } + /** + * Check if the given $itemKey exists in the namespace $nsKey. + * + * @param string $nsKey + * @param string $itemKey + * + * @return bool + */ + public function hasKey($nsKey, $itemKey) + { + return is_file($this->path.'/'.$nsKey.'/'.$itemKey); + } - /** - * Clear data for $itemKey in the namespace $nsKey if it exists. - * - * @param string $nsKey - * @param string $itemKey - */ - public function clearKey($nsKey, $itemKey) - { - if ($this->hasKey($nsKey, $itemKey)) { - $this->freeHandle($nsKey, $itemKey); - unlink($this->path.'/'.$nsKey.'/'.$itemKey); - } - } + /** + * Clear data for $itemKey in the namespace $nsKey if it exists. + * + * @param string $nsKey + * @param string $itemKey + */ + public function clearKey($nsKey, $itemKey) + { + if ($this->hasKey($nsKey, $itemKey)) { + $this->freeHandle($nsKey, $itemKey); + unlink($this->path.'/'.$nsKey.'/'.$itemKey); + } + } - /** - * Clear all data in the namespace $nsKey if it exists. - * - * @param string $nsKey - */ - public function clearAll($nsKey) - { - if (\array_key_exists($nsKey, $this->keys)) { - foreach ($this->keys[$nsKey] as $itemKey => $null) { - $this->clearKey($nsKey, $itemKey); - } - if (is_dir($this->path.'/'.$nsKey)) { - rmdir($this->path.'/'.$nsKey); - } - unset($this->keys[$nsKey]); - } - } + /** + * Clear all data in the namespace $nsKey if it exists. + * + * @param string $nsKey + */ + public function clearAll($nsKey) + { + if (\array_key_exists($nsKey, $this->keys)) { + foreach ($this->keys[$nsKey] as $itemKey => $null) { + $this->clearKey($nsKey, $itemKey); + } + if (is_dir($this->path.'/'.$nsKey)) { + rmdir($this->path.'/'.$nsKey); + } + unset($this->keys[$nsKey]); + } + } - /** - * Initialize the namespace of $nsKey if needed. - * - * @param string $nsKey - */ - private function prepareCache($nsKey) - { - $cacheDir = $this->path.'/'.$nsKey; - if (!is_dir($cacheDir)) { - if (!mkdir($cacheDir)) { - throw new Swift_IoException('Failed to create cache directory '.$cacheDir); - } - $this->keys[$nsKey] = []; - } - } + /** + * Initialize the namespace of $nsKey if needed. + * + * @param string $nsKey + */ + private function prepareCache($nsKey) + { + $cacheDir = $this->path.'/'.$nsKey; + if (!is_dir($cacheDir)) { + if (!mkdir($cacheDir)) { + throw new Swift_IoException('Failed to create cache directory '.$cacheDir); + } + $this->keys[$nsKey] = []; + } + } - /** - * Get a file handle on the cache item. - * - * @param string $nsKey - * @param string $itemKey - * @param int $position - * - * @return resource - */ - private function getHandle($nsKey, $itemKey, $position) - { - if (!isset($this->keys[$nsKey][$itemKey])) { - $openMode = $this->hasKey($nsKey, $itemKey) ? 'r+b' : 'w+b'; - $fp = fopen($this->path.'/'.$nsKey.'/'.$itemKey, $openMode); - $this->keys[$nsKey][$itemKey] = $fp; - } - if (self::POSITION_START == $position) { - fseek($this->keys[$nsKey][$itemKey], 0, SEEK_SET); - } elseif (self::POSITION_END == $position) { - fseek($this->keys[$nsKey][$itemKey], 0, SEEK_END); - } + /** + * Get a file handle on the cache item. + * + * @param string $nsKey + * @param string $itemKey + * @param int $position + * + * @return resource + */ + private function getHandle($nsKey, $itemKey, $position) + { + if (!isset($this->keys[$nsKey][$itemKey])) { + $openMode = $this->hasKey($nsKey, $itemKey) ? 'r+b' : 'w+b'; + $fp = fopen($this->path.'/'.$nsKey.'/'.$itemKey, $openMode); + $this->keys[$nsKey][$itemKey] = $fp; + } + if (self::POSITION_START == $position) { + fseek($this->keys[$nsKey][$itemKey], 0, SEEK_SET); + } elseif (self::POSITION_END == $position) { + fseek($this->keys[$nsKey][$itemKey], 0, SEEK_END); + } - return $this->keys[$nsKey][$itemKey]; - } + return $this->keys[$nsKey][$itemKey]; + } - private function freeHandle($nsKey, $itemKey) - { - $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_CURRENT); - fclose($fp); - $this->keys[$nsKey][$itemKey] = null; - } + private function freeHandle($nsKey, $itemKey) + { + $fp = $this->getHandle($nsKey, $itemKey, self::POSITION_CURRENT); + fclose($fp); + $this->keys[$nsKey][$itemKey] = null; + } - /** - * Destructor. - */ - public function __destruct() - { - foreach ($this->keys as $nsKey => $null) { - $this->clearAll($nsKey); - } - } + /** + * Destructor. + */ + public function __destruct() + { + foreach ($this->keys as $nsKey => $null) { + $this->clearAll($nsKey); + } + } - public function __wakeup() - { - $this->keys = []; - } + public function __wakeup() + { + $this->keys = []; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/KeyCacheInputStream.php b/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/KeyCacheInputStream.php index 159f97643cd..be2dbba0c58 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/KeyCacheInputStream.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/KeyCacheInputStream.php @@ -15,33 +15,33 @@ */ interface Swift_KeyCache_KeyCacheInputStream extends Swift_InputByteStream { - /** - * Set the KeyCache to wrap. - */ - public function setKeyCache(Swift_KeyCache $keyCache); + /** + * Set the KeyCache to wrap. + */ + public function setKeyCache(Swift_KeyCache $keyCache); - /** - * Set the nsKey which will be written to. - * - * @param string $nsKey - */ - public function setNsKey($nsKey); + /** + * Set the nsKey which will be written to. + * + * @param string $nsKey + */ + public function setNsKey($nsKey); - /** - * Set the itemKey which will be written to. - * - * @param string $itemKey - */ - public function setItemKey($itemKey); + /** + * Set the itemKey which will be written to. + * + * @param string $itemKey + */ + public function setItemKey($itemKey); - /** - * Specify a stream to write through for each write(). - */ - public function setWriteThroughStream(Swift_InputByteStream $is); + /** + * Specify a stream to write through for each write(). + */ + public function setWriteThroughStream(Swift_InputByteStream $is); - /** - * Any implementation should be cloneable, allowing the clone to access a - * separate $nsKey and $itemKey. - */ - public function __clone(); + /** + * Any implementation should be cloneable, allowing the clone to access a + * separate $nsKey and $itemKey. + */ + public function __clone(); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/NullKeyCache.php b/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/NullKeyCache.php index 2b04d77fe4f..957b1b2a000 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/NullKeyCache.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/NullKeyCache.php @@ -15,99 +15,99 @@ */ class Swift_KeyCache_NullKeyCache implements Swift_KeyCache { - /** - * Set a string into the cache under $itemKey for the namespace $nsKey. - * - * @see MODE_WRITE, MODE_APPEND - * - * @param string $nsKey - * @param string $itemKey - * @param string $string - * @param int $mode - */ - public function setString($nsKey, $itemKey, $string, $mode) - { - } + /** + * Set a string into the cache under $itemKey for the namespace $nsKey. + * + * @see MODE_WRITE, MODE_APPEND + * + * @param string $nsKey + * @param string $itemKey + * @param string $string + * @param int $mode + */ + public function setString($nsKey, $itemKey, $string, $mode) + { + } - /** - * Set a ByteStream into the cache under $itemKey for the namespace $nsKey. - * - * @see MODE_WRITE, MODE_APPEND - * - * @param string $nsKey - * @param string $itemKey - * @param int $mode - */ - public function importFromByteStream($nsKey, $itemKey, Swift_OutputByteStream $os, $mode) - { - } + /** + * Set a ByteStream into the cache under $itemKey for the namespace $nsKey. + * + * @see MODE_WRITE, MODE_APPEND + * + * @param string $nsKey + * @param string $itemKey + * @param int $mode + */ + public function importFromByteStream($nsKey, $itemKey, Swift_OutputByteStream $os, $mode) + { + } - /** - * Provides a ByteStream which when written to, writes data to $itemKey. - * - * NOTE: The stream will always write in append mode. - * - * @param string $nsKey - * @param string $itemKey - * - * @return Swift_InputByteStream - */ - public function getInputByteStream($nsKey, $itemKey, Swift_InputByteStream $writeThrough = null) - { - } + /** + * Provides a ByteStream which when written to, writes data to $itemKey. + * + * NOTE: The stream will always write in append mode. + * + * @param string $nsKey + * @param string $itemKey + * + * @return Swift_InputByteStream + */ + public function getInputByteStream($nsKey, $itemKey, Swift_InputByteStream $writeThrough = null) + { + } - /** - * Get data back out of the cache as a string. - * - * @param string $nsKey - * @param string $itemKey - * - * @return string - */ - public function getString($nsKey, $itemKey) - { - } + /** + * Get data back out of the cache as a string. + * + * @param string $nsKey + * @param string $itemKey + * + * @return string + */ + public function getString($nsKey, $itemKey) + { + } - /** - * Get data back out of the cache as a ByteStream. - * - * @param string $nsKey - * @param string $itemKey - * @param Swift_InputByteStream $is to write the data to - */ - public function exportToByteStream($nsKey, $itemKey, Swift_InputByteStream $is) - { - } + /** + * Get data back out of the cache as a ByteStream. + * + * @param string $nsKey + * @param string $itemKey + * @param Swift_InputByteStream $is to write the data to + */ + public function exportToByteStream($nsKey, $itemKey, Swift_InputByteStream $is) + { + } - /** - * Check if the given $itemKey exists in the namespace $nsKey. - * - * @param string $nsKey - * @param string $itemKey - * - * @return bool - */ - public function hasKey($nsKey, $itemKey) - { - return false; - } + /** + * Check if the given $itemKey exists in the namespace $nsKey. + * + * @param string $nsKey + * @param string $itemKey + * + * @return bool + */ + public function hasKey($nsKey, $itemKey) + { + return false; + } - /** - * Clear data for $itemKey in the namespace $nsKey if it exists. - * - * @param string $nsKey - * @param string $itemKey - */ - public function clearKey($nsKey, $itemKey) - { - } + /** + * Clear data for $itemKey in the namespace $nsKey if it exists. + * + * @param string $nsKey + * @param string $itemKey + */ + public function clearKey($nsKey, $itemKey) + { + } - /** - * Clear all data in the namespace $nsKey if it exists. - * - * @param string $nsKey - */ - public function clearAll($nsKey) - { - } + /** + * Clear all data in the namespace $nsKey if it exists. + * + * @param string $nsKey + */ + public function clearAll($nsKey) + { + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/SimpleKeyCacheInputStream.php b/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/SimpleKeyCacheInputStream.php index d9d75e078c7..03bab481ea3 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/SimpleKeyCacheInputStream.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/KeyCache/SimpleKeyCacheInputStream.php @@ -15,109 +15,109 @@ */ class Swift_KeyCache_SimpleKeyCacheInputStream implements Swift_KeyCache_KeyCacheInputStream { - /** The KeyCache being written to */ - private $keyCache; + /** The KeyCache being written to */ + private $keyCache; - /** The nsKey of the KeyCache being written to */ - private $nsKey; + /** The nsKey of the KeyCache being written to */ + private $nsKey; - /** The itemKey of the KeyCache being written to */ - private $itemKey; + /** The itemKey of the KeyCache being written to */ + private $itemKey; - /** A stream to write through on each write() */ - private $writeThrough = null; + /** A stream to write through on each write() */ + private $writeThrough = null; - /** - * Set the KeyCache to wrap. - */ - public function setKeyCache(Swift_KeyCache $keyCache) - { - $this->keyCache = $keyCache; - } + /** + * Set the KeyCache to wrap. + */ + public function setKeyCache(Swift_KeyCache $keyCache) + { + $this->keyCache = $keyCache; + } - /** - * Specify a stream to write through for each write(). - */ - public function setWriteThroughStream(Swift_InputByteStream $is) - { - $this->writeThrough = $is; - } + /** + * Specify a stream to write through for each write(). + */ + public function setWriteThroughStream(Swift_InputByteStream $is) + { + $this->writeThrough = $is; + } - /** - * Writes $bytes to the end of the stream. - * - * @param string $bytes - * @param Swift_InputByteStream $is optional - */ - public function write($bytes, Swift_InputByteStream $is = null) - { - $this->keyCache->setString( - $this->nsKey, $this->itemKey, $bytes, Swift_KeyCache::MODE_APPEND - ); - if (isset($is)) { - $is->write($bytes); - } - if (isset($this->writeThrough)) { - $this->writeThrough->write($bytes); - } - } + /** + * Writes $bytes to the end of the stream. + * + * @param string $bytes + * @param Swift_InputByteStream $is optional + */ + public function write($bytes, Swift_InputByteStream $is = null) + { + $this->keyCache->setString( + $this->nsKey, $this->itemKey, $bytes, Swift_KeyCache::MODE_APPEND + ); + if (isset($is)) { + $is->write($bytes); + } + if (isset($this->writeThrough)) { + $this->writeThrough->write($bytes); + } + } - /** - * Not used. - */ - public function commit() - { - } + /** + * Not used. + */ + public function commit() + { + } - /** - * Not used. - */ - public function bind(Swift_InputByteStream $is) - { - } + /** + * Not used. + */ + public function bind(Swift_InputByteStream $is) + { + } - /** - * Not used. - */ - public function unbind(Swift_InputByteStream $is) - { - } + /** + * Not used. + */ + public function unbind(Swift_InputByteStream $is) + { + } - /** - * Flush the contents of the stream (empty it) and set the internal pointer - * to the beginning. - */ - public function flushBuffers() - { - $this->keyCache->clearKey($this->nsKey, $this->itemKey); - } + /** + * Flush the contents of the stream (empty it) and set the internal pointer + * to the beginning. + */ + public function flushBuffers() + { + $this->keyCache->clearKey($this->nsKey, $this->itemKey); + } - /** - * Set the nsKey which will be written to. - * - * @param string $nsKey - */ - public function setNsKey($nsKey) - { - $this->nsKey = $nsKey; - } + /** + * Set the nsKey which will be written to. + * + * @param string $nsKey + */ + public function setNsKey($nsKey) + { + $this->nsKey = $nsKey; + } - /** - * Set the itemKey which will be written to. - * - * @param string $itemKey - */ - public function setItemKey($itemKey) - { - $this->itemKey = $itemKey; - } + /** + * Set the itemKey which will be written to. + * + * @param string $itemKey + */ + public function setItemKey($itemKey) + { + $this->itemKey = $itemKey; + } - /** - * Any implementation should be cloneable, allowing the clone to access a - * separate $nsKey and $itemKey. - */ - public function __clone() - { - $this->writeThrough = null; - } + /** + * Any implementation should be cloneable, allowing the clone to access a + * separate $nsKey and $itemKey. + */ + public function __clone() + { + $this->writeThrough = null; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/LoadBalancedTransport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/LoadBalancedTransport.php index 3373f67964e..244b5f60245 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/LoadBalancedTransport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/LoadBalancedTransport.php @@ -15,19 +15,19 @@ */ class Swift_LoadBalancedTransport extends Swift_Transport_LoadBalancedTransport { - /** - * Creates a new LoadBalancedTransport with $transports. - * - * @param array $transports - */ - public function __construct($transports = []) - { - \call_user_func_array( - [$this, 'Swift_Transport_LoadBalancedTransport::__construct'], - Swift_DependencyContainer::getInstance() - ->createDependenciesFor('transport.loadbalanced') - ); + /** + * Creates a new LoadBalancedTransport with $transports. + * + * @param array $transports + */ + public function __construct($transports = []) + { + \call_user_func_array( + [$this, 'Swift_Transport_LoadBalancedTransport::__construct'], + Swift_DependencyContainer::getInstance() + ->createDependenciesFor('transport.loadbalanced') + ); - $this->setTransports($transports); - } + $this->setTransports($transports); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mailer.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mailer.php index ef9d66365bb..57630074cd9 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mailer.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mailer.php @@ -15,84 +15,84 @@ */ class Swift_Mailer { - /** The Transport used to send messages */ - private $transport; + /** The Transport used to send messages */ + private $transport; - /** - * Create a new Mailer using $transport for delivery. - */ - public function __construct(Swift_Transport $transport) - { - $this->transport = $transport; - } + /** + * Create a new Mailer using $transport for delivery. + */ + public function __construct(Swift_Transport $transport) + { + $this->transport = $transport; + } - /** - * Create a new class instance of one of the message services. - * - * For example 'mimepart' would create a 'message.mimepart' instance - * - * @param string $service - * - * @return object - */ - public function createMessage($service = 'message') - { - return Swift_DependencyContainer::getInstance() - ->lookup('message.'.$service); - } + /** + * Create a new class instance of one of the message services. + * + * For example 'mimepart' would create a 'message.mimepart' instance + * + * @param string $service + * + * @return object + */ + public function createMessage($service = 'message') + { + return Swift_DependencyContainer::getInstance() + ->lookup('message.'.$service); + } - /** - * Send the given Message like it would be sent in a mail client. - * - * All recipients (with the exception of Bcc) will be able to see the other - * recipients this message was sent to. - * - * Recipient/sender data will be retrieved from the Message object. - * - * The return value is the number of recipients who were accepted for - * delivery. - * - * @param array $failedRecipients An array of failures by-reference - * - * @return int The number of successful recipients. Can be 0 which indicates failure - */ - public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) - { - $failedRecipients = (array) $failedRecipients; + /** + * Send the given Message like it would be sent in a mail client. + * + * All recipients (with the exception of Bcc) will be able to see the other + * recipients this message was sent to. + * + * Recipient/sender data will be retrieved from the Message object. + * + * The return value is the number of recipients who were accepted for + * delivery. + * + * @param array $failedRecipients An array of failures by-reference + * + * @return int The number of successful recipients. Can be 0 which indicates failure + */ + public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) + { + $failedRecipients = (array) $failedRecipients; - // FIXME: to be removed in 7.0 (as transport must now start itself on send) - if (!$this->transport->isStarted()) { - $this->transport->start(); - } + // FIXME: to be removed in 7.0 (as transport must now start itself on send) + if (!$this->transport->isStarted()) { + $this->transport->start(); + } - $sent = 0; + $sent = 0; - try { - $sent = $this->transport->send($message, $failedRecipients); - } catch (Swift_RfcComplianceException $e) { - foreach ($message->getTo() as $address => $name) { - $failedRecipients[] = $address; - } - } + try { + $sent = $this->transport->send($message, $failedRecipients); + } catch (Swift_RfcComplianceException $e) { + foreach ($message->getTo() as $address => $name) { + $failedRecipients[] = $address; + } + } - return $sent; - } + return $sent; + } - /** - * Register a plugin using a known unique key (e.g. myPlugin). - */ - public function registerPlugin(Swift_Events_EventListener $plugin) - { - $this->transport->registerPlugin($plugin); - } + /** + * Register a plugin using a known unique key (e.g. myPlugin). + */ + public function registerPlugin(Swift_Events_EventListener $plugin) + { + $this->transport->registerPlugin($plugin); + } - /** - * The Transport used to send messages. - * - * @return Swift_Transport - */ - public function getTransport() - { - return $this->transport; - } + /** + * The Transport used to send messages. + * + * @return Swift_Transport + */ + public function getTransport() + { + return $this->transport; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mailer/ArrayRecipientIterator.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mailer/ArrayRecipientIterator.php index 6ee0b1571a4..19aa82a9c40 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mailer/ArrayRecipientIterator.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mailer/ArrayRecipientIterator.php @@ -15,39 +15,39 @@ */ class Swift_Mailer_ArrayRecipientIterator implements Swift_Mailer_RecipientIterator { - /** - * The list of recipients. - * - * @var array - */ - private $recipients = []; + /** + * The list of recipients. + * + * @var array + */ + private $recipients = []; - /** - * Create a new ArrayRecipientIterator from $recipients. - */ - public function __construct(array $recipients) - { - $this->recipients = $recipients; - } + /** + * Create a new ArrayRecipientIterator from $recipients. + */ + public function __construct(array $recipients) + { + $this->recipients = $recipients; + } - /** - * Returns true only if there are more recipients to send to. - * - * @return bool - */ - public function hasNext() - { - return !empty($this->recipients); - } + /** + * Returns true only if there are more recipients to send to. + * + * @return bool + */ + public function hasNext() + { + return !empty($this->recipients); + } - /** - * Returns an array where the keys are the addresses of recipients and the - * values are the names. e.g. ('foo@bar' => 'Foo') or ('foo@bar' => NULL). - * - * @return array - */ - public function nextRecipient() - { - return array_splice($this->recipients, 0, 1); - } + /** + * Returns an array where the keys are the addresses of recipients and the + * values are the names. e.g. ('foo@bar' => 'Foo') or ('foo@bar' => NULL). + * + * @return array + */ + public function nextRecipient() + { + return array_splice($this->recipients, 0, 1); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/MemorySpool.php b/htdocs/includes/swiftmailer/lib/classes/Swift/MemorySpool.php index af430351eba..e3b0894d87a 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/MemorySpool.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/MemorySpool.php @@ -15,96 +15,96 @@ */ class Swift_MemorySpool implements Swift_Spool { - protected $messages = []; - private $flushRetries = 3; + protected $messages = []; + private $flushRetries = 3; - /** - * Tests if this Transport mechanism has started. - * - * @return bool - */ - public function isStarted() - { - return true; - } + /** + * Tests if this Transport mechanism has started. + * + * @return bool + */ + public function isStarted() + { + return true; + } - /** - * Starts this Transport mechanism. - */ - public function start() - { - } + /** + * Starts this Transport mechanism. + */ + public function start() + { + } - /** - * Stops this Transport mechanism. - */ - public function stop() - { - } + /** + * Stops this Transport mechanism. + */ + public function stop() + { + } - /** - * @param int $retries - */ - public function setFlushRetries($retries) - { - $this->flushRetries = $retries; - } + /** + * @param int $retries + */ + public function setFlushRetries($retries) + { + $this->flushRetries = $retries; + } - /** - * Stores a message in the queue. - * - * @param Swift_Mime_SimpleMessage $message The message to store - * - * @return bool Whether the operation has succeeded - */ - public function queueMessage(Swift_Mime_SimpleMessage $message) - { - //clone the message to make sure it is not changed while in the queue - $this->messages[] = clone $message; + /** + * Stores a message in the queue. + * + * @param Swift_Mime_SimpleMessage $message The message to store + * + * @return bool Whether the operation has succeeded + */ + public function queueMessage(Swift_Mime_SimpleMessage $message) + { + //clone the message to make sure it is not changed while in the queue + $this->messages[] = clone $message; - return true; - } + return true; + } - /** - * Sends messages using the given transport instance. - * - * @param Swift_Transport $transport A transport instance - * @param string[] $failedRecipients An array of failures by-reference - * - * @return int The number of sent emails - */ - public function flushQueue(Swift_Transport $transport, &$failedRecipients = null) - { - if (!$this->messages) { - return 0; - } + /** + * Sends messages using the given transport instance. + * + * @param Swift_Transport $transport A transport instance + * @param string[] $failedRecipients An array of failures by-reference + * + * @return int The number of sent emails + */ + public function flushQueue(Swift_Transport $transport, &$failedRecipients = null) + { + if (!$this->messages) { + return 0; + } - if (!$transport->isStarted()) { - $transport->start(); - } + if (!$transport->isStarted()) { + $transport->start(); + } - $count = 0; - $retries = $this->flushRetries; - while ($retries--) { - try { - while ($message = array_pop($this->messages)) { - $count += $transport->send($message, $failedRecipients); - } - } catch (Swift_TransportException $exception) { - if ($retries) { - // re-queue the message at the end of the queue to give a chance - // to the other messages to be sent, in case the failure was due to - // this message and not just the transport failing - array_unshift($this->messages, $message); + $count = 0; + $retries = $this->flushRetries; + while ($retries--) { + try { + while ($message = array_pop($this->messages)) { + $count += $transport->send($message, $failedRecipients); + } + } catch (Swift_TransportException $exception) { + if ($retries) { + // re-queue the message at the end of the queue to give a chance + // to the other messages to be sent, in case the failure was due to + // this message and not just the transport failing + array_unshift($this->messages, $message); - // wait half a second before we try again - usleep(500000); - } else { - throw $exception; - } - } - } + // wait half a second before we try again + usleep(500000); + } else { + throw $exception; + } + } + } - return $count; - } + return $count; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Message.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Message.php index 103563c620c..5c5834e23d8 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Message.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Message.php @@ -15,265 +15,265 @@ */ class Swift_Message extends Swift_Mime_SimpleMessage { - /** - * @var Swift_Signers_HeaderSigner[] - */ - private $headerSigners = []; + /** + * @var Swift_Signers_HeaderSigner[] + */ + private $headerSigners = []; - /** - * @var Swift_Signers_BodySigner[] - */ - private $bodySigners = []; + /** + * @var Swift_Signers_BodySigner[] + */ + private $bodySigners = []; - /** - * @var array - */ - private $savedMessage = []; + /** + * @var array + */ + private $savedMessage = []; - /** - * Create a new Message. - * - * Details may be optionally passed into the constructor. - * - * @param string $subject - * @param string $body - * @param string $contentType - * @param string $charset - */ - public function __construct($subject = null, $body = null, $contentType = null, $charset = null) - { - \call_user_func_array( - [$this, 'Swift_Mime_SimpleMessage::__construct'], - Swift_DependencyContainer::getInstance() - ->createDependenciesFor('mime.message') - ); + /** + * Create a new Message. + * + * Details may be optionally passed into the constructor. + * + * @param string $subject + * @param string $body + * @param string $contentType + * @param string $charset + */ + public function __construct($subject = null, $body = null, $contentType = null, $charset = null) + { + \call_user_func_array( + [$this, 'Swift_Mime_SimpleMessage::__construct'], + Swift_DependencyContainer::getInstance() + ->createDependenciesFor('mime.message') + ); - if (!isset($charset)) { - $charset = Swift_DependencyContainer::getInstance() - ->lookup('properties.charset'); - } - $this->setSubject($subject); - $this->setBody($body); - $this->setCharset($charset); - if ($contentType) { - $this->setContentType($contentType); - } - } + if (!isset($charset)) { + $charset = Swift_DependencyContainer::getInstance() + ->lookup('properties.charset'); + } + $this->setSubject($subject); + $this->setBody($body); + $this->setCharset($charset); + if ($contentType) { + $this->setContentType($contentType); + } + } - /** - * Add a MimePart to this Message. - * - * @param string|Swift_OutputByteStream $body - * @param string $contentType - * @param string $charset - * - * @return $this - */ - public function addPart($body, $contentType = null, $charset = null) - { - return $this->attach((new Swift_MimePart($body, $contentType, $charset))->setEncoder($this->getEncoder())); - } + /** + * Add a MimePart to this Message. + * + * @param string|Swift_OutputByteStream $body + * @param string $contentType + * @param string $charset + * + * @return $this + */ + public function addPart($body, $contentType = null, $charset = null) + { + return $this->attach((new Swift_MimePart($body, $contentType, $charset))->setEncoder($this->getEncoder())); + } - /** - * Attach a new signature handler to the message. - * - * @return $this - */ - public function attachSigner(Swift_Signer $signer) - { - if ($signer instanceof Swift_Signers_HeaderSigner) { - $this->headerSigners[] = $signer; - } elseif ($signer instanceof Swift_Signers_BodySigner) { - $this->bodySigners[] = $signer; - } + /** + * Attach a new signature handler to the message. + * + * @return $this + */ + public function attachSigner(Swift_Signer $signer) + { + if ($signer instanceof Swift_Signers_HeaderSigner) { + $this->headerSigners[] = $signer; + } elseif ($signer instanceof Swift_Signers_BodySigner) { + $this->bodySigners[] = $signer; + } - return $this; - } + return $this; + } - /** - * Detach a signature handler from a message. - * - * @return $this - */ - public function detachSigner(Swift_Signer $signer) - { - if ($signer instanceof Swift_Signers_HeaderSigner) { - foreach ($this->headerSigners as $k => $headerSigner) { - if ($headerSigner === $signer) { - unset($this->headerSigners[$k]); + /** + * Detach a signature handler from a message. + * + * @return $this + */ + public function detachSigner(Swift_Signer $signer) + { + if ($signer instanceof Swift_Signers_HeaderSigner) { + foreach ($this->headerSigners as $k => $headerSigner) { + if ($headerSigner === $signer) { + unset($this->headerSigners[$k]); - return $this; - } - } - } elseif ($signer instanceof Swift_Signers_BodySigner) { - foreach ($this->bodySigners as $k => $bodySigner) { - if ($bodySigner === $signer) { - unset($this->bodySigners[$k]); + return $this; + } + } + } elseif ($signer instanceof Swift_Signers_BodySigner) { + foreach ($this->bodySigners as $k => $bodySigner) { + if ($bodySigner === $signer) { + unset($this->bodySigners[$k]); - return $this; - } - } - } + return $this; + } + } + } - return $this; - } + return $this; + } - /** - * Clear all signature handlers attached to the message. - * - * @return $this - */ - public function clearSigners() - { - $this->headerSigners = []; - $this->bodySigners = []; + /** + * Clear all signature handlers attached to the message. + * + * @return $this + */ + public function clearSigners() + { + $this->headerSigners = []; + $this->bodySigners = []; - return $this; - } + return $this; + } - /** - * Get this message as a complete string. - * - * @return string - */ - public function toString() - { - if (empty($this->headerSigners) && empty($this->bodySigners)) { - return parent::toString(); - } + /** + * Get this message as a complete string. + * + * @return string + */ + public function toString() + { + if (empty($this->headerSigners) && empty($this->bodySigners)) { + return parent::toString(); + } - $this->saveMessage(); + $this->saveMessage(); - $this->doSign(); + $this->doSign(); - $string = parent::toString(); + $string = parent::toString(); - $this->restoreMessage(); + $this->restoreMessage(); - return $string; - } + return $string; + } - /** - * Write this message to a {@link Swift_InputByteStream}. - */ - public function toByteStream(Swift_InputByteStream $is) - { - if (empty($this->headerSigners) && empty($this->bodySigners)) { - parent::toByteStream($is); + /** + * Write this message to a {@link Swift_InputByteStream}. + */ + public function toByteStream(Swift_InputByteStream $is) + { + if (empty($this->headerSigners) && empty($this->bodySigners)) { + parent::toByteStream($is); - return; - } + return; + } - $this->saveMessage(); + $this->saveMessage(); - $this->doSign(); + $this->doSign(); - parent::toByteStream($is); + parent::toByteStream($is); - $this->restoreMessage(); - } + $this->restoreMessage(); + } - public function __wakeup() - { - Swift_DependencyContainer::getInstance()->createDependenciesFor('mime.message'); - } + public function __wakeup() + { + Swift_DependencyContainer::getInstance()->createDependenciesFor('mime.message'); + } - /** - * loops through signers and apply the signatures. - */ - protected function doSign() - { - foreach ($this->bodySigners as $signer) { - $altered = $signer->getAlteredHeaders(); - $this->saveHeaders($altered); - $signer->signMessage($this); - } + /** + * loops through signers and apply the signatures. + */ + protected function doSign() + { + foreach ($this->bodySigners as $signer) { + $altered = $signer->getAlteredHeaders(); + $this->saveHeaders($altered); + $signer->signMessage($this); + } - foreach ($this->headerSigners as $signer) { - $altered = $signer->getAlteredHeaders(); - $this->saveHeaders($altered); - $signer->reset(); + foreach ($this->headerSigners as $signer) { + $altered = $signer->getAlteredHeaders(); + $this->saveHeaders($altered); + $signer->reset(); - $signer->setHeaders($this->getHeaders()); + $signer->setHeaders($this->getHeaders()); - $signer->startBody(); - $this->bodyToByteStream($signer); - $signer->endBody(); + $signer->startBody(); + $this->bodyToByteStream($signer); + $signer->endBody(); - $signer->addSignature($this->getHeaders()); - } - } + $signer->addSignature($this->getHeaders()); + } + } - /** - * save the message before any signature is applied. - */ - protected function saveMessage() - { - $this->savedMessage = ['headers' => []]; - $this->savedMessage['body'] = $this->getBody(); - $this->savedMessage['children'] = $this->getChildren(); - if (\count($this->savedMessage['children']) > 0 && '' != $this->getBody()) { - $this->setChildren(array_merge([$this->becomeMimePart()], $this->savedMessage['children'])); - $this->setBody(''); - } - } + /** + * save the message before any signature is applied. + */ + protected function saveMessage() + { + $this->savedMessage = ['headers' => []]; + $this->savedMessage['body'] = $this->getBody(); + $this->savedMessage['children'] = $this->getChildren(); + if (\count($this->savedMessage['children']) > 0 && '' != $this->getBody()) { + $this->setChildren(array_merge([$this->becomeMimePart()], $this->savedMessage['children'])); + $this->setBody(''); + } + } - /** - * save the original headers. - */ - protected function saveHeaders(array $altered) - { - foreach ($altered as $head) { - $lc = strtolower($head ?? ''); + /** + * save the original headers. + */ + protected function saveHeaders(array $altered) + { + foreach ($altered as $head) { + $lc = strtolower($head ?? ''); - if (!isset($this->savedMessage['headers'][$lc])) { - $this->savedMessage['headers'][$lc] = $this->getHeaders()->getAll($head); - } - } - } + if (!isset($this->savedMessage['headers'][$lc])) { + $this->savedMessage['headers'][$lc] = $this->getHeaders()->getAll($head); + } + } + } - /** - * Remove or restore altered headers. - */ - protected function restoreHeaders() - { - foreach ($this->savedMessage['headers'] as $name => $savedValue) { - $headers = $this->getHeaders()->getAll($name); + /** + * Remove or restore altered headers. + */ + protected function restoreHeaders() + { + foreach ($this->savedMessage['headers'] as $name => $savedValue) { + $headers = $this->getHeaders()->getAll($name); - foreach ($headers as $key => $value) { - if (!isset($savedValue[$key])) { - $this->getHeaders()->remove($name, $key); - } - } - } - } + foreach ($headers as $key => $value) { + if (!isset($savedValue[$key])) { + $this->getHeaders()->remove($name, $key); + } + } + } + } - /** - * Restore message body. - */ - protected function restoreMessage() - { - $this->setBody($this->savedMessage['body']); - $this->setChildren($this->savedMessage['children']); + /** + * Restore message body. + */ + protected function restoreMessage() + { + $this->setBody($this->savedMessage['body']); + $this->setChildren($this->savedMessage['children']); - $this->restoreHeaders(); - $this->savedMessage = []; - } + $this->restoreHeaders(); + $this->savedMessage = []; + } - /** - * Clone Message Signers. - * - * @see Swift_Mime_SimpleMimeEntity::__clone() - */ - public function __clone() - { - parent::__clone(); - foreach ($this->bodySigners as $key => $bodySigner) { - $this->bodySigners[$key] = clone $bodySigner; - } + /** + * Clone Message Signers. + * + * @see Swift_Mime_SimpleMimeEntity::__clone() + */ + public function __clone() + { + parent::__clone(); + foreach ($this->bodySigners as $key => $bodySigner) { + $this->bodySigners[$key] = clone $bodySigner; + } - foreach ($this->headerSigners as $key => $headerSigner) { - $this->headerSigners[$key] = clone $headerSigner; - } - } + foreach ($this->headerSigners as $key => $headerSigner) { + $this->headerSigners[$key] = clone $headerSigner; + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Attachment.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Attachment.php index ed9b7cbe50c..d994373bd78 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Attachment.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Attachment.php @@ -15,130 +15,130 @@ */ class Swift_Mime_Attachment extends Swift_Mime_SimpleMimeEntity { - /** Recognized MIME types */ - private $mimeTypes = []; + /** Recognized MIME types */ + private $mimeTypes = []; - /** - * Create a new Attachment with $headers, $encoder and $cache. - * - * @param array $mimeTypes - */ - public function __construct(Swift_Mime_SimpleHeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_IdGenerator $idGenerator, $mimeTypes = []) - { - parent::__construct($headers, $encoder, $cache, $idGenerator); - $this->setDisposition('attachment'); - $this->setContentType('application/octet-stream'); - $this->mimeTypes = $mimeTypes; - } + /** + * Create a new Attachment with $headers, $encoder and $cache. + * + * @param array $mimeTypes + */ + public function __construct(Swift_Mime_SimpleHeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_IdGenerator $idGenerator, $mimeTypes = []) + { + parent::__construct($headers, $encoder, $cache, $idGenerator); + $this->setDisposition('attachment'); + $this->setContentType('application/octet-stream'); + $this->mimeTypes = $mimeTypes; + } - /** - * Get the nesting level used for this attachment. - * - * Always returns {@link LEVEL_MIXED}. - * - * @return int - */ - public function getNestingLevel() - { - return self::LEVEL_MIXED; - } + /** + * Get the nesting level used for this attachment. + * + * Always returns {@link LEVEL_MIXED}. + * + * @return int + */ + public function getNestingLevel() + { + return self::LEVEL_MIXED; + } - /** - * Get the Content-Disposition of this attachment. - * - * By default attachments have a disposition of "attachment". - * - * @return string - */ - public function getDisposition() - { - return $this->getHeaderFieldModel('Content-Disposition'); - } + /** + * Get the Content-Disposition of this attachment. + * + * By default attachments have a disposition of "attachment". + * + * @return string + */ + public function getDisposition() + { + return $this->getHeaderFieldModel('Content-Disposition'); + } - /** - * Set the Content-Disposition of this attachment. - * - * @param string $disposition - * - * @return $this - */ - public function setDisposition($disposition) - { - if (!$this->setHeaderFieldModel('Content-Disposition', $disposition)) { - $this->getHeaders()->addParameterizedHeader('Content-Disposition', $disposition); - } + /** + * Set the Content-Disposition of this attachment. + * + * @param string $disposition + * + * @return $this + */ + public function setDisposition($disposition) + { + if (!$this->setHeaderFieldModel('Content-Disposition', $disposition)) { + $this->getHeaders()->addParameterizedHeader('Content-Disposition', $disposition); + } - return $this; - } + return $this; + } - /** - * Get the filename of this attachment when downloaded. - * - * @return string - */ - public function getFilename() - { - return $this->getHeaderParameter('Content-Disposition', 'filename'); - } + /** + * Get the filename of this attachment when downloaded. + * + * @return string + */ + public function getFilename() + { + return $this->getHeaderParameter('Content-Disposition', 'filename'); + } - /** - * Set the filename of this attachment. - * - * @param string $filename - * - * @return $this - */ - public function setFilename($filename) - { - $this->setHeaderParameter('Content-Disposition', 'filename', $filename); - $this->setHeaderParameter('Content-Type', 'name', $filename); + /** + * Set the filename of this attachment. + * + * @param string $filename + * + * @return $this + */ + public function setFilename($filename) + { + $this->setHeaderParameter('Content-Disposition', 'filename', $filename); + $this->setHeaderParameter('Content-Type', 'name', $filename); - return $this; - } + return $this; + } - /** - * Get the file size of this attachment. - * - * @return int - */ - public function getSize() - { - return $this->getHeaderParameter('Content-Disposition', 'size'); - } + /** + * Get the file size of this attachment. + * + * @return int + */ + public function getSize() + { + return $this->getHeaderParameter('Content-Disposition', 'size'); + } - /** - * Set the file size of this attachment. - * - * @param int $size - * - * @return $this - */ - public function setSize($size) - { - $this->setHeaderParameter('Content-Disposition', 'size', $size); + /** + * Set the file size of this attachment. + * + * @param int $size + * + * @return $this + */ + public function setSize($size) + { + $this->setHeaderParameter('Content-Disposition', 'size', $size); - return $this; - } + return $this; + } - /** - * Set the file that this attachment is for. - * - * @param string $contentType optional - * - * @return $this - */ - public function setFile(Swift_FileStream $file, $contentType = null) - { - $this->setFilename(basename($file->getPath())); - $this->setBody($file, $contentType); - if (!isset($contentType)) { - $extension = strtolower(substr($file->getPath(), strrpos($file->getPath(), '.') + 1)); + /** + * Set the file that this attachment is for. + * + * @param string $contentType optional + * + * @return $this + */ + public function setFile(Swift_FileStream $file, $contentType = null) + { + $this->setFilename(basename($file->getPath())); + $this->setBody($file, $contentType); + if (!isset($contentType)) { + $extension = strtolower(substr($file->getPath(), strrpos($file->getPath(), '.') + 1)); - if (\array_key_exists($extension, $this->mimeTypes)) { - $this->setContentType($this->mimeTypes[$extension]); - } - } + if (\array_key_exists($extension, $this->mimeTypes)) { + $this->setContentType($this->mimeTypes[$extension]); + } + } - return $this; - } + return $this; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/Base64ContentEncoder.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/Base64ContentEncoder.php index d7ae850d61a..b7e1e028307 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/Base64ContentEncoder.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/Base64ContentEncoder.php @@ -15,87 +15,87 @@ */ class Swift_Mime_ContentEncoder_Base64ContentEncoder extends Swift_Encoder_Base64Encoder implements Swift_Mime_ContentEncoder { - /** - * Encode stream $in to stream $out. - * - * @param int $firstLineOffset - */ - public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) - { - if (0 >= $maxLineLength || 76 < $maxLineLength) { - $maxLineLength = 76; - } + /** + * Encode stream $in to stream $out. + * + * @param int $firstLineOffset + */ + public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) + { + if (0 >= $maxLineLength || 76 < $maxLineLength) { + $maxLineLength = 76; + } - $remainder = 0; - $base64ReadBufferRemainderBytes = ''; + $remainder = 0; + $base64ReadBufferRemainderBytes = ''; - // To reduce memory usage, the output buffer is streamed to the input buffer like so: - // Output Stream => base64encode => wrap line length => Input Stream - // HOWEVER it's important to note that base64_encode() should only be passed whole triplets of data (except for the final chunk of data) - // otherwise it will assume the input data has *ended* and it will incorrectly pad/terminate the base64 data mid-stream. - // We use $base64ReadBufferRemainderBytes to carry over 1-2 "remainder" bytes from the each chunk from OutputStream and pre-pend those onto the - // chunk of bytes read in the next iteration. - // When the OutputStream is empty, we must flush any remainder bytes. - while (true) { - $readBytes = $os->read(8192); - $atEOF = (false === $readBytes); + // To reduce memory usage, the output buffer is streamed to the input buffer like so: + // Output Stream => base64encode => wrap line length => Input Stream + // HOWEVER it's important to note that base64_encode() should only be passed whole triplets of data (except for the final chunk of data) + // otherwise it will assume the input data has *ended* and it will incorrectly pad/terminate the base64 data mid-stream. + // We use $base64ReadBufferRemainderBytes to carry over 1-2 "remainder" bytes from the each chunk from OutputStream and pre-pend those onto the + // chunk of bytes read in the next iteration. + // When the OutputStream is empty, we must flush any remainder bytes. + while (true) { + $readBytes = $os->read(8192); + $atEOF = (false === $readBytes); - if ($atEOF) { - $streamTheseBytes = $base64ReadBufferRemainderBytes; - } else { - $streamTheseBytes = $base64ReadBufferRemainderBytes.$readBytes; - } - $base64ReadBufferRemainderBytes = ''; - $bytesLength = \strlen($streamTheseBytes); + if ($atEOF) { + $streamTheseBytes = $base64ReadBufferRemainderBytes; + } else { + $streamTheseBytes = $base64ReadBufferRemainderBytes.$readBytes; + } + $base64ReadBufferRemainderBytes = ''; + $bytesLength = \strlen($streamTheseBytes); - if (0 === $bytesLength) { // no data left to encode - break; - } + if (0 === $bytesLength) { // no data left to encode + break; + } - // if we're not on the last block of the ouput stream, make sure $streamTheseBytes ends with a complete triplet of data - // and carry over remainder 1-2 bytes to the next loop iteration - if (!$atEOF) { - $excessBytes = $bytesLength % 3; - if (0 !== $excessBytes) { - $base64ReadBufferRemainderBytes = substr($streamTheseBytes, -$excessBytes); - $streamTheseBytes = substr($streamTheseBytes, 0, $bytesLength - $excessBytes); - } - } + // if we're not on the last block of the ouput stream, make sure $streamTheseBytes ends with a complete triplet of data + // and carry over remainder 1-2 bytes to the next loop iteration + if (!$atEOF) { + $excessBytes = $bytesLength % 3; + if (0 !== $excessBytes) { + $base64ReadBufferRemainderBytes = substr($streamTheseBytes, -$excessBytes); + $streamTheseBytes = substr($streamTheseBytes, 0, $bytesLength - $excessBytes); + } + } - $encoded = base64_encode($streamTheseBytes); - $encodedTransformed = ''; - $thisMaxLineLength = $maxLineLength - $remainder - $firstLineOffset; + $encoded = base64_encode($streamTheseBytes); + $encodedTransformed = ''; + $thisMaxLineLength = $maxLineLength - $remainder - $firstLineOffset; - while ($thisMaxLineLength < \strlen($encoded)) { - $encodedTransformed .= substr($encoded, 0, $thisMaxLineLength)."\r\n"; - $firstLineOffset = 0; - $encoded = substr($encoded, $thisMaxLineLength); - $thisMaxLineLength = $maxLineLength; - $remainder = 0; - } + while ($thisMaxLineLength < \strlen($encoded)) { + $encodedTransformed .= substr($encoded, 0, $thisMaxLineLength)."\r\n"; + $firstLineOffset = 0; + $encoded = substr($encoded, $thisMaxLineLength); + $thisMaxLineLength = $maxLineLength; + $remainder = 0; + } - if (0 < $remainingLength = \strlen($encoded)) { - $remainder += $remainingLength; - $encodedTransformed .= $encoded; - $encoded = null; - } + if (0 < $remainingLength = \strlen($encoded)) { + $remainder += $remainingLength; + $encodedTransformed .= $encoded; + $encoded = null; + } - $is->write($encodedTransformed); + $is->write($encodedTransformed); - if ($atEOF) { - break; - } - } - } + if ($atEOF) { + break; + } + } + } - /** - * Get the name of this encoding scheme. - * Returns the string 'base64'. - * - * @return string - */ - public function getName() - { - return 'base64'; - } + /** + * Get the name of this encoding scheme. + * Returns the string 'base64'. + * + * @return string + */ + public function getName() + { + return 'base64'; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/NativeQpContentEncoder.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/NativeQpContentEncoder.php index a678d67edaf..8dfea605fde 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/NativeQpContentEncoder.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/NativeQpContentEncoder.php @@ -15,107 +15,107 @@ */ class Swift_Mime_ContentEncoder_NativeQpContentEncoder implements Swift_Mime_ContentEncoder { - /** - * @var string|null - */ - private $charset; + /** + * @var string|null + */ + private $charset; - /** - * @param string|null $charset - */ - public function __construct($charset = null) - { - $this->charset = $charset ?: 'utf-8'; - } + /** + * @param string|null $charset + */ + public function __construct($charset = null) + { + $this->charset = $charset ?: 'utf-8'; + } - /** - * Notify this observer that the entity's charset has changed. - * - * @param string $charset - */ - public function charsetChanged($charset) - { - $this->charset = $charset; - } + /** + * Notify this observer that the entity's charset has changed. + * + * @param string $charset + */ + public function charsetChanged($charset) + { + $this->charset = $charset; + } - /** - * Encode $in to $out. - * - * @param Swift_OutputByteStream $os to read from - * @param Swift_InputByteStream $is to write to - * @param int $firstLineOffset - * @param int $maxLineLength 0 indicates the default length for this encoding - * - * @throws RuntimeException - */ - public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) - { - if ('utf-8' !== $this->charset) { - throw new RuntimeException(sprintf('Charset "%s" not supported. NativeQpContentEncoder only supports "utf-8"', $this->charset)); - } + /** + * Encode $in to $out. + * + * @param Swift_OutputByteStream $os to read from + * @param Swift_InputByteStream $is to write to + * @param int $firstLineOffset + * @param int $maxLineLength 0 indicates the default length for this encoding + * + * @throws RuntimeException + */ + public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) + { + if ('utf-8' !== $this->charset) { + throw new RuntimeException(sprintf('Charset "%s" not supported. NativeQpContentEncoder only supports "utf-8"', $this->charset)); + } - $string = ''; + $string = ''; - while (false !== $bytes = $os->read(8192)) { - $string .= $bytes; - } + while (false !== $bytes = $os->read(8192)) { + $string .= $bytes; + } - $is->write($this->encodeString($string)); - } + $is->write($this->encodeString($string)); + } - /** - * Get the MIME name of this content encoding scheme. - * - * @return string - */ - public function getName() - { - return 'quoted-printable'; - } + /** + * Get the MIME name of this content encoding scheme. + * + * @return string + */ + public function getName() + { + return 'quoted-printable'; + } - /** - * Encode a given string to produce an encoded string. - * - * @param string $string - * @param int $firstLineOffset if first line needs to be shorter - * @param int $maxLineLength 0 indicates the default length for this encoding - * - * @throws RuntimeException - * - * @return string - */ - public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) - { - if ('utf-8' !== $this->charset) { - throw new RuntimeException(sprintf('Charset "%s" not supported. NativeQpContentEncoder only supports "utf-8"', $this->charset)); - } + /** + * Encode a given string to produce an encoded string. + * + * @param string $string + * @param int $firstLineOffset if first line needs to be shorter + * @param int $maxLineLength 0 indicates the default length for this encoding + * + * @throws RuntimeException + * + * @return string + */ + public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) + { + if ('utf-8' !== $this->charset) { + throw new RuntimeException(sprintf('Charset "%s" not supported. NativeQpContentEncoder only supports "utf-8"', $this->charset)); + } - return $this->standardize(quoted_printable_encode($string)); - } + return $this->standardize(quoted_printable_encode($string)); + } - /** - * Make sure CRLF is correct and HT/SPACE are in valid places. - * - * @param string $string - * - * @return string - */ - protected function standardize($string) - { - // transform CR or LF to CRLF - $string = preg_replace('~=0D(?!=0A)|(?name = $name; - } + /** + * Creates a new NullContentEncoder with $name (probably 7bit or 8bit). + * + * @param string $name + */ + public function __construct($name) + { + $this->name = $name; + } - /** - * Encode a given string to produce an encoded string. - * - * @param string $string - * @param int $firstLineOffset ignored - * @param int $maxLineLength ignored - * - * @return string - */ - public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) - { - return $string; - } + /** + * Encode a given string to produce an encoded string. + * + * @param string $string + * @param int $firstLineOffset ignored + * @param int $maxLineLength ignored + * + * @return string + */ + public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) + { + return $string; + } - /** - * Encode stream $in to stream $out. - * - * @param int $firstLineOffset ignored - * @param int $maxLineLength ignored - */ - public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) - { - while (false !== ($bytes = $os->read(8192))) { - $is->write($bytes); - } - } + /** + * Encode stream $in to stream $out. + * + * @param int $firstLineOffset ignored + * @param int $maxLineLength ignored + */ + public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) + { + while (false !== ($bytes = $os->read(8192))) { + $is->write($bytes); + } + } - /** - * Get the name of this encoding scheme. - * - * @return string - */ - public function getName() - { - return $this->name; - } + /** + * Get the name of this encoding scheme. + * + * @return string + */ + public function getName() + { + return $this->name; + } - /** - * Not used. - */ - public function charsetChanged($charset) - { - } + /** + * Not used. + */ + public function charsetChanged($charset) + { + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/PlainContentEncoder.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/PlainContentEncoder.php index 02546e03d95..72592fc5894 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/PlainContentEncoder.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/PlainContentEncoder.php @@ -19,146 +19,146 @@ */ class Swift_Mime_ContentEncoder_PlainContentEncoder implements Swift_Mime_ContentEncoder { - /** - * The name of this encoding scheme (probably 7bit or 8bit). - * - * @var string - */ - private $name; + /** + * The name of this encoding scheme (probably 7bit or 8bit). + * + * @var string + */ + private $name; - /** - * True if canonical transformations should be done. - * - * @var bool - */ - private $canonical; + /** + * True if canonical transformations should be done. + * + * @var bool + */ + private $canonical; - /** - * Creates a new PlainContentEncoder with $name (probably 7bit or 8bit). - * - * @param string $name - * @param bool $canonical if canonicalization transformation should be done - */ - public function __construct($name, $canonical = false) - { - $this->name = $name; - $this->canonical = $canonical; - } + /** + * Creates a new PlainContentEncoder with $name (probably 7bit or 8bit). + * + * @param string $name + * @param bool $canonical if canonicalization transformation should be done + */ + public function __construct($name, $canonical = false) + { + $this->name = $name; + $this->canonical = $canonical; + } - /** - * Encode a given string to produce an encoded string. - * - * @param string $string - * @param int $firstLineOffset ignored - * @param int $maxLineLength - 0 means no wrapping will occur - * - * @return string - */ - public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) - { - if ($this->canonical) { - $string = $this->canonicalize($string); - } + /** + * Encode a given string to produce an encoded string. + * + * @param string $string + * @param int $firstLineOffset ignored + * @param int $maxLineLength - 0 means no wrapping will occur + * + * @return string + */ + public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) + { + if ($this->canonical) { + $string = $this->canonicalize($string); + } - return $this->safeWordwrap($string, $maxLineLength, "\r\n"); - } + return $this->safeWordwrap($string, $maxLineLength, "\r\n"); + } - /** - * Encode stream $in to stream $out. - * - * @param int $firstLineOffset ignored - * @param int $maxLineLength optional, 0 means no wrapping will occur - */ - public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) - { - $leftOver = ''; - while (false !== $bytes = $os->read(8192)) { - $toencode = $leftOver.$bytes; - if ($this->canonical) { - $toencode = $this->canonicalize($toencode); - } - $wrapped = $this->safeWordwrap($toencode, $maxLineLength, "\r\n"); - $lastLinePos = strrpos($wrapped, "\r\n"); - $leftOver = substr($wrapped, $lastLinePos); - $wrapped = substr($wrapped, 0, $lastLinePos); + /** + * Encode stream $in to stream $out. + * + * @param int $firstLineOffset ignored + * @param int $maxLineLength optional, 0 means no wrapping will occur + */ + public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) + { + $leftOver = ''; + while (false !== $bytes = $os->read(8192)) { + $toencode = $leftOver.$bytes; + if ($this->canonical) { + $toencode = $this->canonicalize($toencode); + } + $wrapped = $this->safeWordwrap($toencode, $maxLineLength, "\r\n"); + $lastLinePos = strrpos($wrapped, "\r\n"); + $leftOver = substr($wrapped, $lastLinePos); + $wrapped = substr($wrapped, 0, $lastLinePos); - $is->write($wrapped); - } - if (\strlen($leftOver)) { - $is->write($leftOver); - } - } + $is->write($wrapped); + } + if (\strlen($leftOver)) { + $is->write($leftOver); + } + } - /** - * Get the name of this encoding scheme. - * - * @return string - */ - public function getName() - { - return $this->name; - } + /** + * Get the name of this encoding scheme. + * + * @return string + */ + public function getName() + { + return $this->name; + } - /** - * Not used. - */ - public function charsetChanged($charset) - { - } + /** + * Not used. + */ + public function charsetChanged($charset) + { + } - /** - * A safer (but weaker) wordwrap for unicode. - * - * @param string $string - * @param int $length - * @param string $le - * - * @return string - */ - private function safeWordwrap($string, $length = 75, $le = "\r\n") - { - if (0 >= $length) { - return $string; - } + /** + * A safer (but weaker) wordwrap for unicode. + * + * @param string $string + * @param int $length + * @param string $le + * + * @return string + */ + private function safeWordwrap($string, $length = 75, $le = "\r\n") + { + if (0 >= $length) { + return $string; + } - $originalLines = explode($le, $string); + $originalLines = explode($le, $string); - $lines = []; - $lineCount = 0; + $lines = []; + $lineCount = 0; - foreach ($originalLines as $originalLine) { - $lines[] = ''; - $currentLine = &$lines[$lineCount++]; + foreach ($originalLines as $originalLine) { + $lines[] = ''; + $currentLine = &$lines[$lineCount++]; - //$chunks = preg_split('/(?<=[\ \t,\.!\?\-&\+\/])/', $originalLine); - $chunks = preg_split('/(?<=\s)/', $originalLine); + //$chunks = preg_split('/(?<=[\ \t,\.!\?\-&\+\/])/', $originalLine); + $chunks = preg_split('/(?<=\s)/', $originalLine); - foreach ($chunks as $chunk) { - if (0 != \strlen($currentLine) - && \strlen($currentLine.$chunk) > $length) { - $lines[] = ''; - $currentLine = &$lines[$lineCount++]; - } - $currentLine .= $chunk; - } - } + foreach ($chunks as $chunk) { + if (0 != \strlen($currentLine) + && \strlen($currentLine.$chunk) > $length) { + $lines[] = ''; + $currentLine = &$lines[$lineCount++]; + } + $currentLine .= $chunk; + } + } - return implode("\r\n", $lines); - } + return implode("\r\n", $lines); + } - /** - * Canonicalize string input (fix CRLF). - * - * @param string $string - * - * @return string - */ - private function canonicalize($string) - { - return str_replace( - ["\r\n", "\r", "\n"], - ["\n", "\n", "\r\n"], - $string - ); - } + /** + * Canonicalize string input (fix CRLF). + * + * @param string $string + * + * @return string + */ + private function canonicalize($string) + { + return str_replace( + ["\r\n", "\r", "\n"], + ["\n", "\n", "\r\n"], + $string + ); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoder.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoder.php index 51785234043..465ffd87850 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoder.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoder.php @@ -15,120 +15,120 @@ */ class Swift_Mime_ContentEncoder_QpContentEncoder extends Swift_Encoder_QpEncoder implements Swift_Mime_ContentEncoder { - protected $dotEscape; + protected $dotEscape; - /** - * Creates a new QpContentEncoder for the given CharacterStream. - * - * @param Swift_CharacterStream $charStream to use for reading characters - * @param Swift_StreamFilter $filter if canonicalization should occur - * @param bool $dotEscape if dot stuffing workaround must be enabled - */ - public function __construct(Swift_CharacterStream $charStream, Swift_StreamFilter $filter = null, $dotEscape = false) - { - $this->dotEscape = $dotEscape; - parent::__construct($charStream, $filter); - } + /** + * Creates a new QpContentEncoder for the given CharacterStream. + * + * @param Swift_CharacterStream $charStream to use for reading characters + * @param Swift_StreamFilter $filter if canonicalization should occur + * @param bool $dotEscape if dot stuffing workaround must be enabled + */ + public function __construct(Swift_CharacterStream $charStream, Swift_StreamFilter $filter = null, $dotEscape = false) + { + $this->dotEscape = $dotEscape; + parent::__construct($charStream, $filter); + } - public function __sleep() - { - return ['charStream', 'filter', 'dotEscape']; - } + public function __sleep() + { + return ['charStream', 'filter', 'dotEscape']; + } - protected function getSafeMapShareId() - { - return static::class.($this->dotEscape ? '.dotEscape' : ''); - } + protected function getSafeMapShareId() + { + return static::class.($this->dotEscape ? '.dotEscape' : ''); + } - protected function initSafeMap() - { - parent::initSafeMap(); - if ($this->dotEscape) { - /* Encode . as =2e for buggy remote servers */ - unset($this->safeMap[0x2e]); - } - } + protected function initSafeMap() + { + parent::initSafeMap(); + if ($this->dotEscape) { + /* Encode . as =2e for buggy remote servers */ + unset($this->safeMap[0x2e]); + } + } - /** - * Encode stream $in to stream $out. - * - * QP encoded strings have a maximum line length of 76 characters. - * If the first line needs to be shorter, indicate the difference with - * $firstLineOffset. - * - * @param Swift_OutputByteStream $os output stream - * @param Swift_InputByteStream $is input stream - * @param int $firstLineOffset - * @param int $maxLineLength - */ - public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) - { - if ($maxLineLength > 76 || $maxLineLength <= 0) { - $maxLineLength = 76; - } + /** + * Encode stream $in to stream $out. + * + * QP encoded strings have a maximum line length of 76 characters. + * If the first line needs to be shorter, indicate the difference with + * $firstLineOffset. + * + * @param Swift_OutputByteStream $os output stream + * @param Swift_InputByteStream $is input stream + * @param int $firstLineOffset + * @param int $maxLineLength + */ + public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) + { + if ($maxLineLength > 76 || $maxLineLength <= 0) { + $maxLineLength = 76; + } - $thisLineLength = $maxLineLength - $firstLineOffset; + $thisLineLength = $maxLineLength - $firstLineOffset; - $this->charStream->flushContents(); - $this->charStream->importByteStream($os); + $this->charStream->flushContents(); + $this->charStream->importByteStream($os); - $currentLine = ''; - $prepend = ''; - $size = $lineLen = 0; + $currentLine = ''; + $prepend = ''; + $size = $lineLen = 0; - while (false !== $bytes = $this->nextSequence()) { - // If we're filtering the input - if (isset($this->filter)) { - // If we can't filter because we need more bytes - while ($this->filter->shouldBuffer($bytes)) { - // Then collect bytes into the buffer - if (false === $moreBytes = $this->nextSequence(1)) { - break; - } + while (false !== $bytes = $this->nextSequence()) { + // If we're filtering the input + if (isset($this->filter)) { + // If we can't filter because we need more bytes + while ($this->filter->shouldBuffer($bytes)) { + // Then collect bytes into the buffer + if (false === $moreBytes = $this->nextSequence(1)) { + break; + } - foreach ($moreBytes as $b) { - $bytes[] = $b; - } - } - // And filter them - $bytes = $this->filter->filter($bytes); - } + foreach ($moreBytes as $b) { + $bytes[] = $b; + } + } + // And filter them + $bytes = $this->filter->filter($bytes); + } - $enc = $this->encodeByteSequence($bytes, $size); + $enc = $this->encodeByteSequence($bytes, $size); - $i = strpos($enc, '=0D=0A'); - $newLineLength = $lineLen + (false === $i ? $size : $i); + $i = strpos($enc, '=0D=0A'); + $newLineLength = $lineLen + (false === $i ? $size : $i); - if ($currentLine && $newLineLength >= $thisLineLength) { - $is->write($prepend.$this->standardize($currentLine)); - $currentLine = ''; - $prepend = "=\r\n"; - $thisLineLength = $maxLineLength; - $lineLen = 0; - } + if ($currentLine && $newLineLength >= $thisLineLength) { + $is->write($prepend.$this->standardize($currentLine)); + $currentLine = ''; + $prepend = "=\r\n"; + $thisLineLength = $maxLineLength; + $lineLen = 0; + } - $currentLine .= $enc; + $currentLine .= $enc; - if (false === $i) { - $lineLen += $size; - } else { - // 6 is the length of '=0D=0A'. - $lineLen = $size - strrpos($enc, '=0D=0A') - 6; - } - } - if (\strlen($currentLine)) { - $is->write($prepend.$this->standardize($currentLine)); - } - } + if (false === $i) { + $lineLen += $size; + } else { + // 6 is the length of '=0D=0A'. + $lineLen = $size - strrpos($enc, '=0D=0A') - 6; + } + } + if (\strlen($currentLine)) { + $is->write($prepend.$this->standardize($currentLine)); + } + } - /** - * Get the name of this encoding scheme. - * Returns the string 'quoted-printable'. - * - * @return string - */ - public function getName() - { - return 'quoted-printable'; - } + /** + * Get the name of this encoding scheme. + * Returns the string 'quoted-printable'. + * + * @return string + */ + public function getName() + { + return 'quoted-printable'; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoderProxy.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoderProxy.php index 7b9fb138c3a..f3ece43aecd 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoderProxy.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoderProxy.php @@ -17,80 +17,80 @@ */ class Swift_Mime_ContentEncoder_QpContentEncoderProxy implements Swift_Mime_ContentEncoder { - /** - * @var Swift_Mime_ContentEncoder_QpContentEncoder - */ - private $safeEncoder; + /** + * @var Swift_Mime_ContentEncoder_QpContentEncoder + */ + private $safeEncoder; - /** - * @var Swift_Mime_ContentEncoder_NativeQpContentEncoder - */ - private $nativeEncoder; + /** + * @var Swift_Mime_ContentEncoder_NativeQpContentEncoder + */ + private $nativeEncoder; - /** - * @var string|null - */ - private $charset; + /** + * @var string|null + */ + private $charset; - /** - * Constructor. - * - * @param string|null $charset - */ - public function __construct(Swift_Mime_ContentEncoder_QpContentEncoder $safeEncoder, Swift_Mime_ContentEncoder_NativeQpContentEncoder $nativeEncoder, $charset) - { - $this->safeEncoder = $safeEncoder; - $this->nativeEncoder = $nativeEncoder; - $this->charset = $charset; - } + /** + * Constructor. + * + * @param string|null $charset + */ + public function __construct(Swift_Mime_ContentEncoder_QpContentEncoder $safeEncoder, Swift_Mime_ContentEncoder_NativeQpContentEncoder $nativeEncoder, $charset) + { + $this->safeEncoder = $safeEncoder; + $this->nativeEncoder = $nativeEncoder; + $this->charset = $charset; + } - /** - * Make a deep copy of object. - */ - public function __clone() - { - $this->safeEncoder = clone $this->safeEncoder; - $this->nativeEncoder = clone $this->nativeEncoder; - } + /** + * Make a deep copy of object. + */ + public function __clone() + { + $this->safeEncoder = clone $this->safeEncoder; + $this->nativeEncoder = clone $this->nativeEncoder; + } - /** - * {@inheritdoc} - */ - public function charsetChanged($charset) - { - $this->charset = $charset; - $this->safeEncoder->charsetChanged($charset); - } + /** + * {@inheritdoc} + */ + public function charsetChanged($charset) + { + $this->charset = $charset; + $this->safeEncoder->charsetChanged($charset); + } - /** - * {@inheritdoc} - */ - public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) - { - $this->getEncoder()->encodeByteStream($os, $is, $firstLineOffset, $maxLineLength); - } + /** + * {@inheritdoc} + */ + public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) + { + $this->getEncoder()->encodeByteStream($os, $is, $firstLineOffset, $maxLineLength); + } - /** - * {@inheritdoc} - */ - public function getName() - { - return 'quoted-printable'; - } + /** + * {@inheritdoc} + */ + public function getName() + { + return 'quoted-printable'; + } - /** - * {@inheritdoc} - */ - public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) - { - return $this->getEncoder()->encodeString($string, $firstLineOffset, $maxLineLength); - } + /** + * {@inheritdoc} + */ + public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) + { + return $this->getEncoder()->encodeString($string, $firstLineOffset, $maxLineLength); + } - /** - * @return Swift_Mime_ContentEncoder - */ - private function getEncoder() - { - return 'utf-8' === $this->charset ? $this->nativeEncoder : $this->safeEncoder; - } + /** + * @return Swift_Mime_ContentEncoder + */ + private function getEncoder() + { + return 'utf-8' === $this->charset ? $this->nativeEncoder : $this->safeEncoder; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/RawContentEncoder.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/RawContentEncoder.php index 99d09c56478..870e7f41a93 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/RawContentEncoder.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/RawContentEncoder.php @@ -19,47 +19,47 @@ */ class Swift_Mime_ContentEncoder_RawContentEncoder implements Swift_Mime_ContentEncoder { - /** - * Encode a given string to produce an encoded string. - * - * @param string $string - * @param int $firstLineOffset ignored - * @param int $maxLineLength ignored - * - * @return string - */ - public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) - { - return $string; - } + /** + * Encode a given string to produce an encoded string. + * + * @param string $string + * @param int $firstLineOffset ignored + * @param int $maxLineLength ignored + * + * @return string + */ + public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) + { + return $string; + } - /** - * Encode stream $in to stream $out. - * - * @param int $firstLineOffset ignored - * @param int $maxLineLength ignored - */ - public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) - { - while (false !== ($bytes = $os->read(8192))) { - $is->write($bytes); - } - } + /** + * Encode stream $in to stream $out. + * + * @param int $firstLineOffset ignored + * @param int $maxLineLength ignored + */ + public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) + { + while (false !== ($bytes = $os->read(8192))) { + $is->write($bytes); + } + } - /** - * Get the name of this encoding scheme. - * - * @return string - */ - public function getName() - { - return 'raw'; - } + /** + * Get the name of this encoding scheme. + * + * @return string + */ + public function getName() + { + return 'raw'; + } - /** - * Not used. - */ - public function charsetChanged($charset) - { - } + /** + * Not used. + */ + public function charsetChanged($charset) + { + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/EmbeddedFile.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/EmbeddedFile.php index 7b65f781465..42a51770c76 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/EmbeddedFile.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/EmbeddedFile.php @@ -15,27 +15,27 @@ */ class Swift_Mime_EmbeddedFile extends Swift_Mime_Attachment { - /** - * Creates a new Attachment with $headers and $encoder. - * - * @param array $mimeTypes optional - */ - public function __construct(Swift_Mime_SimpleHeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_IdGenerator $idGenerator, $mimeTypes = []) - { - parent::__construct($headers, $encoder, $cache, $idGenerator, $mimeTypes); - $this->setDisposition('inline'); - $this->setId($this->getId()); - } + /** + * Creates a new Attachment with $headers and $encoder. + * + * @param array $mimeTypes optional + */ + public function __construct(Swift_Mime_SimpleHeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_IdGenerator $idGenerator, $mimeTypes = []) + { + parent::__construct($headers, $encoder, $cache, $idGenerator, $mimeTypes); + $this->setDisposition('inline'); + $this->setId($this->getId()); + } - /** - * Get the nesting level of this EmbeddedFile. - * - * Returns {@see LEVEL_RELATED}. - * - * @return int - */ - public function getNestingLevel() - { - return self::LEVEL_RELATED; - } + /** + * Get the nesting level of this EmbeddedFile. + * + * Returns {@see LEVEL_RELATED}. + * + * @return int + */ + public function getNestingLevel() + { + return self::LEVEL_RELATED; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/EncodingObserver.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/EncodingObserver.php index 51915764259..1a952ece12c 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/EncodingObserver.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/EncodingObserver.php @@ -15,8 +15,8 @@ */ interface Swift_Mime_EncodingObserver { - /** - * Notify this observer that the observed entity's ContentEncoder has changed. - */ - public function encoderChanged(Swift_Mime_ContentEncoder $encoder); + /** + * Notify this observer that the observed entity's ContentEncoder has changed. + */ + public function encoderChanged(Swift_Mime_ContentEncoder $encoder); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Header.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Header.php index e2559ffba52..ca712f35aa0 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Header.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Header.php @@ -15,79 +15,79 @@ */ interface Swift_Mime_Header { - /** Text headers */ - const TYPE_TEXT = 2; + /** Text headers */ + const TYPE_TEXT = 2; - /** headers (text + params) */ - const TYPE_PARAMETERIZED = 6; + /** headers (text + params) */ + const TYPE_PARAMETERIZED = 6; - /** Mailbox and address headers */ - const TYPE_MAILBOX = 8; + /** Mailbox and address headers */ + const TYPE_MAILBOX = 8; - /** Date and time headers */ - const TYPE_DATE = 16; + /** Date and time headers */ + const TYPE_DATE = 16; - /** Identification headers */ - const TYPE_ID = 32; + /** Identification headers */ + const TYPE_ID = 32; - /** Address path headers */ - const TYPE_PATH = 64; + /** Address path headers */ + const TYPE_PATH = 64; - /** - * Get the type of Header that this instance represents. - * - * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX - * @see TYPE_DATE, TYPE_ID, TYPE_PATH - * - * @return int - */ - public function getFieldType(); + /** + * Get the type of Header that this instance represents. + * + * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX + * @see TYPE_DATE, TYPE_ID, TYPE_PATH + * + * @return int + */ + public function getFieldType(); - /** - * Set the model for the field body. - * - * The actual types needed will vary depending upon the type of Header. - * - * @param mixed $model - */ - public function setFieldBodyModel($model); + /** + * Set the model for the field body. + * + * The actual types needed will vary depending upon the type of Header. + * + * @param mixed $model + */ + public function setFieldBodyModel($model); - /** - * Set the charset used when rendering the Header. - * - * @param string $charset - */ - public function setCharset($charset); + /** + * Set the charset used when rendering the Header. + * + * @param string $charset + */ + public function setCharset($charset); - /** - * Get the model for the field body. - * - * The return type depends on the specifics of the Header. - * - * @return mixed - */ - public function getFieldBodyModel(); + /** + * Get the model for the field body. + * + * The return type depends on the specifics of the Header. + * + * @return mixed + */ + public function getFieldBodyModel(); - /** - * Get the name of this header (e.g. Subject). - * - * The name is an identifier and as such will be immutable. - * - * @return string - */ - public function getFieldName(); + /** + * Get the name of this header (e.g. Subject). + * + * The name is an identifier and as such will be immutable. + * + * @return string + */ + public function getFieldName(); - /** - * Get the field body, prepared for folding into a final header value. - * - * @return string - */ - public function getFieldBody(); + /** + * Get the field body, prepared for folding into a final header value. + * + * @return string + */ + public function getFieldBody(); - /** - * Get this Header rendered as a compliant string, including trailing CRLF. - * - * @return string - */ - public function toString(); + /** + * Get this Header rendered as a compliant string, including trailing CRLF. + * + * @return string + */ + public function toString(); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder/Base64HeaderEncoder.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder/Base64HeaderEncoder.php index 6bcb1e4e8f8..21c8aaabfea 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder/Base64HeaderEncoder.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder/Base64HeaderEncoder.php @@ -15,41 +15,41 @@ */ class Swift_Mime_HeaderEncoder_Base64HeaderEncoder extends Swift_Encoder_Base64Encoder implements Swift_Mime_HeaderEncoder { - /** - * Get the name of this encoding scheme. - * Returns the string 'B'. - * - * @return string - */ - public function getName() - { - return 'B'; - } + /** + * Get the name of this encoding scheme. + * Returns the string 'B'. + * + * @return string + */ + public function getName() + { + return 'B'; + } - /** - * Takes an unencoded string and produces a Base64 encoded string from it. - * - * If the charset is iso-2022-jp, it uses mb_encode_mimeheader instead of - * default encodeString, otherwise pass to the parent method. - * - * @param string $string string to encode - * @param int $firstLineOffset - * @param int $maxLineLength optional, 0 indicates the default of 76 bytes - * @param string $charset - * - * @return string - */ - public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0, $charset = 'utf-8') - { - if ('iso-2022-jp' === strtolower($charset ?? '')) { - $old = mb_internal_encoding(); - mb_internal_encoding('utf-8'); - $newstring = mb_encode_mimeheader($string, $charset, $this->getName(), "\r\n"); - mb_internal_encoding($old); + /** + * Takes an unencoded string and produces a Base64 encoded string from it. + * + * If the charset is iso-2022-jp, it uses mb_encode_mimeheader instead of + * default encodeString, otherwise pass to the parent method. + * + * @param string $string string to encode + * @param int $firstLineOffset + * @param int $maxLineLength optional, 0 indicates the default of 76 bytes + * @param string $charset + * + * @return string + */ + public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0, $charset = 'utf-8') + { + if ('iso-2022-jp' === strtolower($charset ?? '')) { + $old = mb_internal_encoding(); + mb_internal_encoding('utf-8'); + $newstring = mb_encode_mimeheader($string, $charset, $this->getName(), "\r\n"); + mb_internal_encoding($old); - return $newstring; - } + return $newstring; + } - return parent::encodeString($string, $firstLineOffset, $maxLineLength); - } + return parent::encodeString($string, $firstLineOffset, $maxLineLength); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder/QpHeaderEncoder.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder/QpHeaderEncoder.php index 6cfeb3b9285..378c4805057 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder/QpHeaderEncoder.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder/QpHeaderEncoder.php @@ -15,51 +15,51 @@ */ class Swift_Mime_HeaderEncoder_QpHeaderEncoder extends Swift_Encoder_QpEncoder implements Swift_Mime_HeaderEncoder { - /** - * Creates a new QpHeaderEncoder for the given CharacterStream. - * - * @param Swift_CharacterStream $charStream to use for reading characters - */ - public function __construct(Swift_CharacterStream $charStream) - { - parent::__construct($charStream); - } + /** + * Creates a new QpHeaderEncoder for the given CharacterStream. + * + * @param Swift_CharacterStream $charStream to use for reading characters + */ + public function __construct(Swift_CharacterStream $charStream) + { + parent::__construct($charStream); + } - protected function initSafeMap() - { - foreach (array_merge( - range(0x61, 0x7A), range(0x41, 0x5A), - range(0x30, 0x39), [0x20, 0x21, 0x2A, 0x2B, 0x2D, 0x2F] - ) as $byte) { - $this->safeMap[$byte] = \chr($byte); - } - } + protected function initSafeMap() + { + foreach (array_merge( + range(0x61, 0x7A), range(0x41, 0x5A), + range(0x30, 0x39), [0x20, 0x21, 0x2A, 0x2B, 0x2D, 0x2F] + ) as $byte) { + $this->safeMap[$byte] = \chr($byte); + } + } - /** - * Get the name of this encoding scheme. - * - * Returns the string 'Q'. - * - * @return string - */ - public function getName() - { - return 'Q'; - } + /** + * Get the name of this encoding scheme. + * + * Returns the string 'Q'. + * + * @return string + */ + public function getName() + { + return 'Q'; + } - /** - * Takes an unencoded string and produces a QP encoded string from it. - * - * @param string $string string to encode - * @param int $firstLineOffset optional - * @param int $maxLineLength optional, 0 indicates the default of 76 chars - * - * @return string - */ - public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) - { - return str_replace([' ', '=20', "=\r\n"], ['_', '_', "\r\n"], - parent::encodeString($string, $firstLineOffset, $maxLineLength) - ); - } + /** + * Takes an unencoded string and produces a QP encoded string from it. + * + * @param string $string string to encode + * @param int $firstLineOffset optional + * @param int $maxLineLength optional, 0 indicates the default of 76 chars + * + * @return string + */ + public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) + { + return str_replace([' ', '=20', "=\r\n"], ['_', '_', "\r\n"], + parent::encodeString($string, $firstLineOffset, $maxLineLength) + ); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/AbstractHeader.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/AbstractHeader.php index 344a2b4a7a7..25740d1155c 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/AbstractHeader.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/AbstractHeader.php @@ -15,472 +15,472 @@ */ abstract class Swift_Mime_Headers_AbstractHeader implements Swift_Mime_Header { - const PHRASE_PATTERN = '(?:(?:(?:(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?[a-zA-Z0-9!#\$%&\'\*\+\-\/=\?\^_`\{\}\|~]+(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?)|(?:(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?"((?:(?:[ \t]*(?:\r\n))?[ \t])?(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21\x23-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])))*(?:(?:[ \t]*(?:\r\n))?[ \t])?"(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?))+?)'; + const PHRASE_PATTERN = '(?:(?:(?:(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?[a-zA-Z0-9!#\$%&\'\*\+\-\/=\?\^_`\{\}\|~]+(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?)|(?:(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?"((?:(?:[ \t]*(?:\r\n))?[ \t])?(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21\x23-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])))*(?:(?:[ \t]*(?:\r\n))?[ \t])?"(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?))+?)'; - /** - * The name of this Header. - * - * @var string - */ - private $name; + /** + * The name of this Header. + * + * @var string + */ + private $name; - /** - * The Encoder used to encode this Header. - * - * @var Swift_Encoder - */ - private $encoder; + /** + * The Encoder used to encode this Header. + * + * @var Swift_Encoder + */ + private $encoder; - /** - * The maximum length of a line in the header. - * - * @var int - */ - private $lineLength = 78; + /** + * The maximum length of a line in the header. + * + * @var int + */ + private $lineLength = 78; - /** - * The language used in this Header. - * - * @var string - */ - private $lang; + /** + * The language used in this Header. + * + * @var string + */ + private $lang; - /** - * The character set of the text in this Header. - * - * @var string - */ - private $charset = 'utf-8'; + /** + * The character set of the text in this Header. + * + * @var string + */ + private $charset = 'utf-8'; - /** - * The value of this Header, cached. - * - * @var string - */ - private $cachedValue = null; + /** + * The value of this Header, cached. + * + * @var string + */ + private $cachedValue = null; - /** - * Set the character set used in this Header. - * - * @param string $charset - */ - public function setCharset($charset) - { - $this->clearCachedValueIf($charset != $this->charset); - $this->charset = $charset; - if (isset($this->encoder)) { - $this->encoder->charsetChanged($charset); - } - } + /** + * Set the character set used in this Header. + * + * @param string $charset + */ + public function setCharset($charset) + { + $this->clearCachedValueIf($charset != $this->charset); + $this->charset = $charset; + if (isset($this->encoder)) { + $this->encoder->charsetChanged($charset); + } + } - /** - * Get the character set used in this Header. - * - * @return string - */ - public function getCharset() - { - return $this->charset; - } + /** + * Get the character set used in this Header. + * + * @return string + */ + public function getCharset() + { + return $this->charset; + } - /** - * Set the language used in this Header. - * - * For example, for US English, 'en-us'. - * This can be unspecified. - * - * @param string $lang - */ - public function setLanguage($lang) - { - $this->clearCachedValueIf($this->lang != $lang); - $this->lang = $lang; - } + /** + * Set the language used in this Header. + * + * For example, for US English, 'en-us'. + * This can be unspecified. + * + * @param string $lang + */ + public function setLanguage($lang) + { + $this->clearCachedValueIf($this->lang != $lang); + $this->lang = $lang; + } - /** - * Get the language used in this Header. - * - * @return string - */ - public function getLanguage() - { - return $this->lang; - } + /** + * Get the language used in this Header. + * + * @return string + */ + public function getLanguage() + { + return $this->lang; + } - /** - * Set the encoder used for encoding the header. - */ - public function setEncoder(Swift_Mime_HeaderEncoder $encoder) - { - $this->encoder = $encoder; - $this->setCachedValue(null); - } + /** + * Set the encoder used for encoding the header. + */ + public function setEncoder(Swift_Mime_HeaderEncoder $encoder) + { + $this->encoder = $encoder; + $this->setCachedValue(null); + } - /** - * Get the encoder used for encoding this Header. - * - * @return Swift_Mime_HeaderEncoder - */ - public function getEncoder() - { - return $this->encoder; - } + /** + * Get the encoder used for encoding this Header. + * + * @return Swift_Mime_HeaderEncoder + */ + public function getEncoder() + { + return $this->encoder; + } - /** - * Get the name of this header (e.g. charset). - * - * @return string - */ - public function getFieldName() - { - return $this->name; - } + /** + * Get the name of this header (e.g. charset). + * + * @return string + */ + public function getFieldName() + { + return $this->name; + } - /** - * Set the maximum length of lines in the header (excluding EOL). - * - * @param int $lineLength - */ - public function setMaxLineLength($lineLength) - { - $this->clearCachedValueIf($this->lineLength != $lineLength); - $this->lineLength = $lineLength; - } + /** + * Set the maximum length of lines in the header (excluding EOL). + * + * @param int $lineLength + */ + public function setMaxLineLength($lineLength) + { + $this->clearCachedValueIf($this->lineLength != $lineLength); + $this->lineLength = $lineLength; + } - /** - * Get the maximum permitted length of lines in this Header. - * - * @return int - */ - public function getMaxLineLength() - { - return $this->lineLength; - } + /** + * Get the maximum permitted length of lines in this Header. + * + * @return int + */ + public function getMaxLineLength() + { + return $this->lineLength; + } - /** - * Get this Header rendered as a RFC 2822 compliant string. - * - * @return string - * - * @throws Swift_RfcComplianceException - */ - public function toString() - { - return $this->tokensToString($this->toTokens()); - } + /** + * Get this Header rendered as a RFC 2822 compliant string. + * + * @return string + * + * @throws Swift_RfcComplianceException + */ + public function toString() + { + return $this->tokensToString($this->toTokens()); + } - /** - * Returns a string representation of this object. - * - * @return string - * - * @see toString() - */ - public function __toString() - { - return $this->toString(); - } + /** + * Returns a string representation of this object. + * + * @return string + * + * @see toString() + */ + public function __toString() + { + return $this->toString(); + } - /** - * Set the name of this Header field. - * - * @param string $name - */ - protected function setFieldName($name) - { - $this->name = $name; - } + /** + * Set the name of this Header field. + * + * @param string $name + */ + protected function setFieldName($name) + { + $this->name = $name; + } - /** - * Produces a compliant, formatted RFC 2822 'phrase' based on the string given. - * - * @param string $string as displayed - * @param string $charset of the text - * @param bool $shorten the first line to make remove for header name - * - * @return string - */ - protected function createPhrase(Swift_Mime_Header $header, $string, $charset, Swift_Mime_HeaderEncoder $encoder = null, $shorten = false) - { - // Treat token as exactly what was given - $phraseStr = $string; - // If it's not valid + /** + * Produces a compliant, formatted RFC 2822 'phrase' based on the string given. + * + * @param string $string as displayed + * @param string $charset of the text + * @param bool $shorten the first line to make remove for header name + * + * @return string + */ + protected function createPhrase(Swift_Mime_Header $header, $string, $charset, Swift_Mime_HeaderEncoder $encoder = null, $shorten = false) + { + // Treat token as exactly what was given + $phraseStr = $string; + // If it's not valid - if (!preg_match('/^'.self::PHRASE_PATTERN.'$/D', $phraseStr)) { - // .. but it is just ascii text, try escaping some characters - // and make it a quoted-string - if (preg_match('/^[\x00-\x08\x0B\x0C\x0E-\x7F]*$/D', $phraseStr)) { - $phraseStr = $this->escapeSpecials($phraseStr, ['"']); - $phraseStr = '"'.$phraseStr.'"'; - } else { - // ... otherwise it needs encoding - // Determine space remaining on line if first line - if ($shorten) { - $usedLength = \strlen($header->getFieldName().': '); - } else { - $usedLength = 0; - } - $phraseStr = $this->encodeWords($header, $string, $usedLength); - } - } + if (!preg_match('/^'.self::PHRASE_PATTERN.'$/D', $phraseStr)) { + // .. but it is just ascii text, try escaping some characters + // and make it a quoted-string + if (preg_match('/^[\x00-\x08\x0B\x0C\x0E-\x7F]*$/D', $phraseStr)) { + $phraseStr = $this->escapeSpecials($phraseStr, ['"']); + $phraseStr = '"'.$phraseStr.'"'; + } else { + // ... otherwise it needs encoding + // Determine space remaining on line if first line + if ($shorten) { + $usedLength = \strlen($header->getFieldName().': '); + } else { + $usedLength = 0; + } + $phraseStr = $this->encodeWords($header, $string, $usedLength); + } + } - return $phraseStr; - } + return $phraseStr; + } - /** - * Escape special characters in a string (convert to quoted-pairs). - * - * @param string $token - * @param string[] $include additional chars to escape - * - * @return string - */ - private function escapeSpecials($token, $include = []) - { - foreach (array_merge(['\\'], $include) as $char) { - $token = str_replace($char, '\\'.$char, $token); - } + /** + * Escape special characters in a string (convert to quoted-pairs). + * + * @param string $token + * @param string[] $include additional chars to escape + * + * @return string + */ + private function escapeSpecials($token, $include = []) + { + foreach (array_merge(['\\'], $include) as $char) { + $token = str_replace($char, '\\'.$char, $token); + } - return $token; - } + return $token; + } - /** - * Encode needed word tokens within a string of input. - * - * @param string $input - * @param string $usedLength optional - * - * @return string - */ - protected function encodeWords(Swift_Mime_Header $header, $input, $usedLength = -1) - { - $value = ''; + /** + * Encode needed word tokens within a string of input. + * + * @param string $input + * @param string $usedLength optional + * + * @return string + */ + protected function encodeWords(Swift_Mime_Header $header, $input, $usedLength = -1) + { + $value = ''; - $tokens = $this->getEncodableWordTokens($input); + $tokens = $this->getEncodableWordTokens($input); - foreach ($tokens as $token) { - // See RFC 2822, Sect 2.2 (really 2.2 ??) - if ($this->tokenNeedsEncoding($token)) { - // Don't encode starting WSP - $firstChar = substr($token, 0, 1); - switch ($firstChar) { - case ' ': - case "\t": - $value .= $firstChar; - $token = substr($token, 1); - } + foreach ($tokens as $token) { + // See RFC 2822, Sect 2.2 (really 2.2 ??) + if ($this->tokenNeedsEncoding($token)) { + // Don't encode starting WSP + $firstChar = substr($token, 0, 1); + switch ($firstChar) { + case ' ': + case "\t": + $value .= $firstChar; + $token = substr($token, 1); + } - if (-1 == $usedLength) { - $usedLength = \strlen($header->getFieldName().': ') + \strlen($value); - } - $value .= $this->getTokenAsEncodedWord($token, $usedLength); + if (-1 == $usedLength) { + $usedLength = \strlen($header->getFieldName().': ') + \strlen($value); + } + $value .= $this->getTokenAsEncodedWord($token, $usedLength); - $header->setMaxLineLength(76); // Forcefully override - } else { - $value .= $token; - } - } + $header->setMaxLineLength(76); // Forcefully override + } else { + $value .= $token; + } + } - return $value; - } + return $value; + } - /** - * Test if a token needs to be encoded or not. - * - * @param string $token - * - * @return bool - */ - protected function tokenNeedsEncoding($token) - { - return preg_match('~[\x00-\x08\x10-\x19\x7F-\xFF\r\n]~', $token); - } + /** + * Test if a token needs to be encoded or not. + * + * @param string $token + * + * @return bool + */ + protected function tokenNeedsEncoding($token) + { + return preg_match('~[\x00-\x08\x10-\x19\x7F-\xFF\r\n]~', $token); + } - /** - * Splits a string into tokens in blocks of words which can be encoded quickly. - * - * @param string $string - * - * @return string[] - */ - protected function getEncodableWordTokens($string) - { - $tokens = []; + /** + * Splits a string into tokens in blocks of words which can be encoded quickly. + * + * @param string $string + * + * @return string[] + */ + protected function getEncodableWordTokens($string) + { + $tokens = []; - $encodedToken = ''; - // Split at all whitespace boundaries - foreach (preg_split('~(?=[\t ])~', $string ?? '') as $token) { - if ($this->tokenNeedsEncoding($token)) { - $encodedToken .= $token; - } else { - if (\strlen($encodedToken) > 0) { - $tokens[] = $encodedToken; - $encodedToken = ''; - } - $tokens[] = $token; - } - } - if (\strlen($encodedToken)) { - $tokens[] = $encodedToken; - } + $encodedToken = ''; + // Split at all whitespace boundaries + foreach (preg_split('~(?=[\t ])~', $string ?? '') as $token) { + if ($this->tokenNeedsEncoding($token)) { + $encodedToken .= $token; + } else { + if (\strlen($encodedToken) > 0) { + $tokens[] = $encodedToken; + $encodedToken = ''; + } + $tokens[] = $token; + } + } + if (\strlen($encodedToken)) { + $tokens[] = $encodedToken; + } - return $tokens; - } + return $tokens; + } - /** - * Get a token as an encoded word for safe insertion into headers. - * - * @param string $token token to encode - * @param int $firstLineOffset optional - * - * @return string - */ - protected function getTokenAsEncodedWord($token, $firstLineOffset = 0) - { - // Adjust $firstLineOffset to account for space needed for syntax - $charsetDecl = $this->charset; - if (isset($this->lang)) { - $charsetDecl .= '*'.$this->lang; - } - $encodingWrapperLength = \strlen( - '=?'.$charsetDecl.'?'.$this->encoder->getName().'??=' - ); + /** + * Get a token as an encoded word for safe insertion into headers. + * + * @param string $token token to encode + * @param int $firstLineOffset optional + * + * @return string + */ + protected function getTokenAsEncodedWord($token, $firstLineOffset = 0) + { + // Adjust $firstLineOffset to account for space needed for syntax + $charsetDecl = $this->charset; + if (isset($this->lang)) { + $charsetDecl .= '*'.$this->lang; + } + $encodingWrapperLength = \strlen( + '=?'.$charsetDecl.'?'.$this->encoder->getName().'??=' + ); - if ($firstLineOffset >= 75) { - //Does this logic need to be here? - $firstLineOffset = 0; - } + if ($firstLineOffset >= 75) { + //Does this logic need to be here? + $firstLineOffset = 0; + } - $encodedTextLines = explode("\r\n", - $this->encoder->encodeString( - $token, $firstLineOffset, 75 - $encodingWrapperLength, $this->charset - ) ?? '' - ); + $encodedTextLines = explode("\r\n", + $this->encoder->encodeString( + $token, $firstLineOffset, 75 - $encodingWrapperLength, $this->charset + ) ?? '' + ); - if ('iso-2022-jp' !== strtolower($this->charset ?? '')) { - // special encoding for iso-2022-jp using mb_encode_mimeheader - foreach ($encodedTextLines as $lineNum => $line) { - $encodedTextLines[$lineNum] = '=?'.$charsetDecl. - '?'.$this->encoder->getName(). - '?'.$line.'?='; - } - } + if ('iso-2022-jp' !== strtolower($this->charset ?? '')) { + // special encoding for iso-2022-jp using mb_encode_mimeheader + foreach ($encodedTextLines as $lineNum => $line) { + $encodedTextLines[$lineNum] = '=?'.$charsetDecl. + '?'.$this->encoder->getName(). + '?'.$line.'?='; + } + } - return implode("\r\n ", $encodedTextLines); - } + return implode("\r\n ", $encodedTextLines); + } - /** - * Generates tokens from the given string which include CRLF as individual tokens. - * - * @param string $token - * - * @return string[] - */ - protected function generateTokenLines($token) - { - return preg_split('~(\r\n)~', $token ?? '', -1, PREG_SPLIT_DELIM_CAPTURE); - } + /** + * Generates tokens from the given string which include CRLF as individual tokens. + * + * @param string $token + * + * @return string[] + */ + protected function generateTokenLines($token) + { + return preg_split('~(\r\n)~', $token ?? '', -1, PREG_SPLIT_DELIM_CAPTURE); + } - /** - * Set a value into the cache. - * - * @param string $value - */ - protected function setCachedValue($value) - { - $this->cachedValue = $value; - } + /** + * Set a value into the cache. + * + * @param string $value + */ + protected function setCachedValue($value) + { + $this->cachedValue = $value; + } - /** - * Get the value in the cache. - * - * @return string - */ - protected function getCachedValue() - { - return $this->cachedValue; - } + /** + * Get the value in the cache. + * + * @return string + */ + protected function getCachedValue() + { + return $this->cachedValue; + } - /** - * Clear the cached value if $condition is met. - * - * @param bool $condition - */ - protected function clearCachedValueIf($condition) - { - if ($condition) { - $this->setCachedValue(null); - } - } + /** + * Clear the cached value if $condition is met. + * + * @param bool $condition + */ + protected function clearCachedValueIf($condition) + { + if ($condition) { + $this->setCachedValue(null); + } + } - /** - * Generate a list of all tokens in the final header. - * - * @param string $string The string to tokenize - * - * @return array An array of tokens as strings - */ - protected function toTokens($string = null) - { - if (null === $string) { - $string = $this->getFieldBody(); - } + /** + * Generate a list of all tokens in the final header. + * + * @param string $string The string to tokenize + * + * @return array An array of tokens as strings + */ + protected function toTokens($string = null) + { + if (null === $string) { + $string = $this->getFieldBody(); + } - $tokens = []; + $tokens = []; - // Generate atoms; split at all invisible boundaries followed by WSP - foreach (preg_split('~(?=[ \t])~', $string ?? '') as $token) { - $newTokens = $this->generateTokenLines($token); - foreach ($newTokens as $newToken) { - $tokens[] = $newToken; - } - } + // Generate atoms; split at all invisible boundaries followed by WSP + foreach (preg_split('~(?=[ \t])~', $string ?? '') as $token) { + $newTokens = $this->generateTokenLines($token); + foreach ($newTokens as $newToken) { + $tokens[] = $newToken; + } + } - return $tokens; - } + return $tokens; + } - /** - * Takes an array of tokens which appear in the header and turns them into - * an RFC 2822 compliant string, adding FWSP where needed. - * - * @param string[] $tokens - * - * @return string - */ - private function tokensToString(array $tokens) - { - $lineCount = 0; - $headerLines = []; - $headerLines[] = $this->name.': '; - $currentLine = &$headerLines[$lineCount++]; + /** + * Takes an array of tokens which appear in the header and turns them into + * an RFC 2822 compliant string, adding FWSP where needed. + * + * @param string[] $tokens + * + * @return string + */ + private function tokensToString(array $tokens) + { + $lineCount = 0; + $headerLines = []; + $headerLines[] = $this->name.': '; + $currentLine = &$headerLines[$lineCount++]; - // Build all tokens back into compliant header - foreach ($tokens as $i => $token) { - // Line longer than specified maximum or token was just a new line - if (("\r\n" == $token) || - ($i > 0 && \strlen($currentLine.$token) > $this->lineLength) - && 0 < \strlen($currentLine)) { - $headerLines[] = ''; - $currentLine = &$headerLines[$lineCount++]; - } + // Build all tokens back into compliant header + foreach ($tokens as $i => $token) { + // Line longer than specified maximum or token was just a new line + if (("\r\n" == $token) || + ($i > 0 && \strlen($currentLine.$token) > $this->lineLength) + && 0 < \strlen($currentLine)) { + $headerLines[] = ''; + $currentLine = &$headerLines[$lineCount++]; + } - // Append token to the line - if ("\r\n" != $token) { - $currentLine .= $token; - } - } + // Append token to the line + if ("\r\n" != $token) { + $currentLine .= $token; + } + } - // Implode with FWS (RFC 2822, 2.2.3) - return implode("\r\n", $headerLines)."\r\n"; - } + // Implode with FWS (RFC 2822, 2.2.3) + return implode("\r\n", $headerLines)."\r\n"; + } - /** - * Make a deep copy of object. - */ - public function __clone() - { - if ($this->encoder) { - $this->encoder = clone $this->encoder; - } - } + /** + * Make a deep copy of object. + */ + public function __clone() + { + if ($this->encoder) { + $this->encoder = clone $this->encoder; + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/DateHeader.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/DateHeader.php index fb83178a8b3..efe1dad6619 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/DateHeader.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/DateHeader.php @@ -15,99 +15,99 @@ */ class Swift_Mime_Headers_DateHeader extends Swift_Mime_Headers_AbstractHeader { - /** - * Date-time value of this Header. - * - * @var DateTimeImmutable - */ - private $dateTime; + /** + * Date-time value of this Header. + * + * @var DateTimeImmutable + */ + private $dateTime; - /** - * Creates a new DateHeader with $name. - * - * @param string $name of Header - */ - public function __construct($name) - { - $this->setFieldName($name); - } + /** + * Creates a new DateHeader with $name. + * + * @param string $name of Header + */ + public function __construct($name) + { + $this->setFieldName($name); + } - /** - * Get the type of Header that this instance represents. - * - * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX - * @see TYPE_DATE, TYPE_ID, TYPE_PATH - * - * @return int - */ - public function getFieldType() - { - return self::TYPE_DATE; - } + /** + * Get the type of Header that this instance represents. + * + * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX + * @see TYPE_DATE, TYPE_ID, TYPE_PATH + * + * @return int + */ + public function getFieldType() + { + return self::TYPE_DATE; + } - /** - * Set the model for the field body. - * - * @param DateTimeInterface $model - */ - public function setFieldBodyModel($model) - { - $this->setDateTime($model); - } + /** + * Set the model for the field body. + * + * @param DateTimeInterface $model + */ + public function setFieldBodyModel($model) + { + $this->setDateTime($model); + } - /** - * Get the model for the field body. - * - * @return DateTimeImmutable - */ - public function getFieldBodyModel() - { - return $this->getDateTime(); - } + /** + * Get the model for the field body. + * + * @return DateTimeImmutable + */ + public function getFieldBodyModel() + { + return $this->getDateTime(); + } - /** - * Get the date-time representing the Date in this Header. - * - * @return DateTimeImmutable - */ - public function getDateTime() - { - return $this->dateTime; - } + /** + * Get the date-time representing the Date in this Header. + * + * @return DateTimeImmutable + */ + public function getDateTime() + { + return $this->dateTime; + } - /** - * Set the date-time of the Date in this Header. - * - * If a DateTime instance is provided, it is converted to DateTimeImmutable. - */ - public function setDateTime(DateTimeInterface $dateTime) - { - $this->clearCachedValueIf($this->getCachedValue() != $dateTime->format(DateTime::RFC2822)); - if ($dateTime instanceof DateTime) { - $immutable = new DateTimeImmutable('@'.$dateTime->getTimestamp()); - $dateTime = $immutable->setTimezone($dateTime->getTimezone()); - } - $this->dateTime = $dateTime; - } + /** + * Set the date-time of the Date in this Header. + * + * If a DateTime instance is provided, it is converted to DateTimeImmutable. + */ + public function setDateTime(DateTimeInterface $dateTime) + { + $this->clearCachedValueIf($this->getCachedValue() != $dateTime->format(DateTime::RFC2822)); + if ($dateTime instanceof DateTime) { + $immutable = new DateTimeImmutable('@'.$dateTime->getTimestamp()); + $dateTime = $immutable->setTimezone($dateTime->getTimezone()); + } + $this->dateTime = $dateTime; + } - /** - * Get the string value of the body in this Header. - * - * This is not necessarily RFC 2822 compliant since folding white space will - * not be added at this stage (see {@link toString()} for that). - * - * @see toString() - * - * @return string - */ - public function getFieldBody() - { - if (!$this->getCachedValue()) { - if (isset($this->dateTime)) { - $this->setCachedValue($this->dateTime->format(DateTime::RFC2822)); - } - } + /** + * Get the string value of the body in this Header. + * + * This is not necessarily RFC 2822 compliant since folding white space will + * not be added at this stage (see {@link toString()} for that). + * + * @see toString() + * + * @return string + */ + public function getFieldBody() + { + if (!$this->getCachedValue()) { + if (isset($this->dateTime)) { + $this->setCachedValue($this->dateTime->format(DateTime::RFC2822)); + } + } - return $this->getCachedValue(); - } + return $this->getCachedValue(); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/IdentificationHeader.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/IdentificationHeader.php index cec31c83961..4fcdff418a7 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/IdentificationHeader.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/IdentificationHeader.php @@ -19,171 +19,171 @@ use Egulias\EmailValidator\Validation\RFCValidation; */ class Swift_Mime_Headers_IdentificationHeader extends Swift_Mime_Headers_AbstractHeader { - /** - * The IDs used in the value of this Header. - * - * This may hold multiple IDs or just a single ID. - * - * @var string[] - */ - private $ids = []; + /** + * The IDs used in the value of this Header. + * + * This may hold multiple IDs or just a single ID. + * + * @var string[] + */ + private $ids = []; - /** - * The strict EmailValidator. - * - * @var EmailValidator - */ - private $emailValidator; + /** + * The strict EmailValidator. + * + * @var EmailValidator + */ + private $emailValidator; - private $addressEncoder; + private $addressEncoder; - /** - * Creates a new IdentificationHeader with the given $name and $id. - * - * @param string $name - */ - public function __construct($name, EmailValidator $emailValidator, Swift_AddressEncoder $addressEncoder = null) - { - $this->setFieldName($name); - $this->emailValidator = $emailValidator; - $this->addressEncoder = $addressEncoder ?? new Swift_AddressEncoder_IdnAddressEncoder(); - } + /** + * Creates a new IdentificationHeader with the given $name and $id. + * + * @param string $name + */ + public function __construct($name, EmailValidator $emailValidator, Swift_AddressEncoder $addressEncoder = null) + { + $this->setFieldName($name); + $this->emailValidator = $emailValidator; + $this->addressEncoder = $addressEncoder ?? new Swift_AddressEncoder_IdnAddressEncoder(); + } - /** - * Get the type of Header that this instance represents. - * - * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX - * @see TYPE_DATE, TYPE_ID, TYPE_PATH - * - * @return int - */ - public function getFieldType() - { - return self::TYPE_ID; - } + /** + * Get the type of Header that this instance represents. + * + * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX + * @see TYPE_DATE, TYPE_ID, TYPE_PATH + * + * @return int + */ + public function getFieldType() + { + return self::TYPE_ID; + } - /** - * Set the model for the field body. - * - * This method takes a string ID, or an array of IDs. - * - * @param mixed $model - * - * @throws Swift_RfcComplianceException - */ - public function setFieldBodyModel($model) - { - $this->setId($model); - } + /** + * Set the model for the field body. + * + * This method takes a string ID, or an array of IDs. + * + * @param mixed $model + * + * @throws Swift_RfcComplianceException + */ + public function setFieldBodyModel($model) + { + $this->setId($model); + } - /** - * Get the model for the field body. - * - * This method returns an array of IDs - * - * @return array - */ - public function getFieldBodyModel() - { - return $this->getIds(); - } + /** + * Get the model for the field body. + * + * This method returns an array of IDs + * + * @return array + */ + public function getFieldBodyModel() + { + return $this->getIds(); + } - /** - * Set the ID used in the value of this header. - * - * @param string|array $id - * - * @throws Swift_RfcComplianceException - */ - public function setId($id) - { - $this->setIds(\is_array($id) ? $id : [$id]); - } + /** + * Set the ID used in the value of this header. + * + * @param string|array $id + * + * @throws Swift_RfcComplianceException + */ + public function setId($id) + { + $this->setIds(\is_array($id) ? $id : [$id]); + } - /** - * Get the ID used in the value of this Header. - * - * If multiple IDs are set only the first is returned. - * - * @return string - */ - public function getId() - { - if (\count($this->ids) > 0) { - return $this->ids[0]; - } - } + /** + * Get the ID used in the value of this Header. + * + * If multiple IDs are set only the first is returned. + * + * @return string + */ + public function getId() + { + if (\count($this->ids) > 0) { + return $this->ids[0]; + } + } - /** - * Set a collection of IDs to use in the value of this Header. - * - * @param string[] $ids - * - * @throws Swift_RfcComplianceException - */ - public function setIds(array $ids) - { - $actualIds = []; + /** + * Set a collection of IDs to use in the value of this Header. + * + * @param string[] $ids + * + * @throws Swift_RfcComplianceException + */ + public function setIds(array $ids) + { + $actualIds = []; - foreach ($ids as $id) { - $this->assertValidId($id); - $actualIds[] = $id; - } + foreach ($ids as $id) { + $this->assertValidId($id); + $actualIds[] = $id; + } - $this->clearCachedValueIf($this->ids != $actualIds); - $this->ids = $actualIds; - } + $this->clearCachedValueIf($this->ids != $actualIds); + $this->ids = $actualIds; + } - /** - * Get the list of IDs used in this Header. - * - * @return string[] - */ - public function getIds() - { - return $this->ids; - } + /** + * Get the list of IDs used in this Header. + * + * @return string[] + */ + public function getIds() + { + return $this->ids; + } - /** - * Get the string value of the body in this Header. - * - * This is not necessarily RFC 2822 compliant since folding white space will - * not be added at this stage (see {@see toString()} for that). - * - * @see toString() - * - * @throws Swift_RfcComplianceException - * - * @return string - */ - public function getFieldBody() - { - if (!$this->getCachedValue()) { - $angleAddrs = []; + /** + * Get the string value of the body in this Header. + * + * This is not necessarily RFC 2822 compliant since folding white space will + * not be added at this stage (see {@see toString()} for that). + * + * @see toString() + * + * @throws Swift_RfcComplianceException + * + * @return string + */ + public function getFieldBody() + { + if (!$this->getCachedValue()) { + $angleAddrs = []; - foreach ($this->ids as $id) { - $angleAddrs[] = '<'.$this->addressEncoder->encodeString($id).'>'; - } + foreach ($this->ids as $id) { + $angleAddrs[] = '<'.$this->addressEncoder->encodeString($id).'>'; + } - $this->setCachedValue(implode(' ', $angleAddrs)); - } + $this->setCachedValue(implode(' ', $angleAddrs)); + } - return $this->getCachedValue(); - } + return $this->getCachedValue(); + } - /** - * Throws an Exception if the id passed does not comply with RFC 2822. - * - * @param string $id - * - * @throws Swift_RfcComplianceException - */ - private function assertValidId($id) - { - $emailValidation = class_exists(MessageIDValidation::class) ? new MessageIDValidation() : new RFCValidation(); + /** + * Throws an Exception if the id passed does not comply with RFC 2822. + * + * @param string $id + * + * @throws Swift_RfcComplianceException + */ + private function assertValidId($id) + { + $emailValidation = class_exists(MessageIDValidation::class) ? new MessageIDValidation() : new RFCValidation(); - if (!$this->emailValidator->isValid($id, $emailValidation)) { - throw new Swift_RfcComplianceException('Invalid ID given <'.$id.'>'); - } - } + if (!$this->emailValidator->isValid($id, $emailValidation)) { + throw new Swift_RfcComplianceException('Invalid ID given <'.$id.'>'); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/MailboxHeader.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/MailboxHeader.php index febc31332dd..ddd5e8cffb1 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/MailboxHeader.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/MailboxHeader.php @@ -18,341 +18,341 @@ use Egulias\EmailValidator\Validation\RFCValidation; */ class Swift_Mime_Headers_MailboxHeader extends Swift_Mime_Headers_AbstractHeader { - /** - * The mailboxes used in this Header. - * - * @var string[] - */ - private $mailboxes = []; + /** + * The mailboxes used in this Header. + * + * @var string[] + */ + private $mailboxes = []; - /** - * The strict EmailValidator. - * - * @var EmailValidator - */ - private $emailValidator; + /** + * The strict EmailValidator. + * + * @var EmailValidator + */ + private $emailValidator; - private $addressEncoder; + private $addressEncoder; - /** - * Creates a new MailboxHeader with $name. - * - * @param string $name of Header - */ - public function __construct($name, Swift_Mime_HeaderEncoder $encoder, EmailValidator $emailValidator, Swift_AddressEncoder $addressEncoder = null) - { - $this->setFieldName($name); - $this->setEncoder($encoder); - $this->emailValidator = $emailValidator; - $this->addressEncoder = $addressEncoder ?? new Swift_AddressEncoder_IdnAddressEncoder(); - } + /** + * Creates a new MailboxHeader with $name. + * + * @param string $name of Header + */ + public function __construct($name, Swift_Mime_HeaderEncoder $encoder, EmailValidator $emailValidator, Swift_AddressEncoder $addressEncoder = null) + { + $this->setFieldName($name); + $this->setEncoder($encoder); + $this->emailValidator = $emailValidator; + $this->addressEncoder = $addressEncoder ?? new Swift_AddressEncoder_IdnAddressEncoder(); + } - /** - * Get the type of Header that this instance represents. - * - * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX - * @see TYPE_DATE, TYPE_ID, TYPE_PATH - * - * @return int - */ - public function getFieldType() - { - return self::TYPE_MAILBOX; - } + /** + * Get the type of Header that this instance represents. + * + * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX + * @see TYPE_DATE, TYPE_ID, TYPE_PATH + * + * @return int + */ + public function getFieldType() + { + return self::TYPE_MAILBOX; + } - /** - * Set the model for the field body. - * - * This method takes a string, or an array of addresses. - * - * @param mixed $model - * - * @throws Swift_RfcComplianceException - */ - public function setFieldBodyModel($model) - { - $this->setNameAddresses($model); - } + /** + * Set the model for the field body. + * + * This method takes a string, or an array of addresses. + * + * @param mixed $model + * + * @throws Swift_RfcComplianceException + */ + public function setFieldBodyModel($model) + { + $this->setNameAddresses($model); + } - /** - * Get the model for the field body. - * - * This method returns an associative array like {@link getNameAddresses()} - * - * @throws Swift_RfcComplianceException - * - * @return array - */ - public function getFieldBodyModel() - { - return $this->getNameAddresses(); - } + /** + * Get the model for the field body. + * + * This method returns an associative array like {@link getNameAddresses()} + * + * @throws Swift_RfcComplianceException + * + * @return array + */ + public function getFieldBodyModel() + { + return $this->getNameAddresses(); + } - /** - * Set a list of mailboxes to be shown in this Header. - * - * The mailboxes can be a simple array of addresses, or an array of - * key=>value pairs where (email => personalName). - * Example: - * - * setNameAddresses(array( - * 'chris@swiftmailer.org' => 'Chris Corbyn', - * 'mark@swiftmailer.org' //No associated personal name - * )); - * ?> - * - * - * @see __construct() - * @see setAddresses() - * @see setValue() - * - * @param string|string[] $mailboxes - * - * @throws Swift_RfcComplianceException - */ - public function setNameAddresses($mailboxes) - { - $this->mailboxes = $this->normalizeMailboxes((array) $mailboxes); - $this->setCachedValue(null); //Clear any cached value - } + /** + * Set a list of mailboxes to be shown in this Header. + * + * The mailboxes can be a simple array of addresses, or an array of + * key=>value pairs where (email => personalName). + * Example: + * + * setNameAddresses(array( + * 'chris@swiftmailer.org' => 'Chris Corbyn', + * 'mark@swiftmailer.org' //No associated personal name + * )); + * ?> + * + * + * @see __construct() + * @see setAddresses() + * @see setValue() + * + * @param string|string[] $mailboxes + * + * @throws Swift_RfcComplianceException + */ + public function setNameAddresses($mailboxes) + { + $this->mailboxes = $this->normalizeMailboxes((array) $mailboxes); + $this->setCachedValue(null); //Clear any cached value + } - /** - * Get the full mailbox list of this Header as an array of valid RFC 2822 strings. - * - * Example: - * - * 'Chris Corbyn', - * 'mark@swiftmailer.org' => 'Mark Corbyn') - * ); - * print_r($header->getNameAddressStrings()); - * // array ( - * // 0 => Chris Corbyn , - * // 1 => Mark Corbyn - * // ) - * ?> - * - * - * @see getNameAddresses() - * @see toString() - * - * @throws Swift_RfcComplianceException - * - * @return string[] - */ - public function getNameAddressStrings() - { - return $this->createNameAddressStrings($this->getNameAddresses()); - } + /** + * Get the full mailbox list of this Header as an array of valid RFC 2822 strings. + * + * Example: + * + * 'Chris Corbyn', + * 'mark@swiftmailer.org' => 'Mark Corbyn') + * ); + * print_r($header->getNameAddressStrings()); + * // array ( + * // 0 => Chris Corbyn , + * // 1 => Mark Corbyn + * // ) + * ?> + * + * + * @see getNameAddresses() + * @see toString() + * + * @throws Swift_RfcComplianceException + * + * @return string[] + */ + public function getNameAddressStrings() + { + return $this->createNameAddressStrings($this->getNameAddresses()); + } - /** - * Get all mailboxes in this Header as key=>value pairs. - * - * The key is the address and the value is the name (or null if none set). - * Example: - * - * 'Chris Corbyn', - * 'mark@swiftmailer.org' => 'Mark Corbyn') - * ); - * print_r($header->getNameAddresses()); - * // array ( - * // chris@swiftmailer.org => Chris Corbyn, - * // mark@swiftmailer.org => Mark Corbyn - * // ) - * ?> - * - * - * @see getAddresses() - * @see getNameAddressStrings() - * - * @return string[] - */ - public function getNameAddresses() - { - return $this->mailboxes; - } + /** + * Get all mailboxes in this Header as key=>value pairs. + * + * The key is the address and the value is the name (or null if none set). + * Example: + * + * 'Chris Corbyn', + * 'mark@swiftmailer.org' => 'Mark Corbyn') + * ); + * print_r($header->getNameAddresses()); + * // array ( + * // chris@swiftmailer.org => Chris Corbyn, + * // mark@swiftmailer.org => Mark Corbyn + * // ) + * ?> + * + * + * @see getAddresses() + * @see getNameAddressStrings() + * + * @return string[] + */ + public function getNameAddresses() + { + return $this->mailboxes; + } - /** - * Makes this Header represent a list of plain email addresses with no names. - * - * Example: - * - * setAddresses( - * array('one@domain.tld', 'two@domain.tld', 'three@domain.tld') - * ); - * ?> - * - * - * @see setNameAddresses() - * @see setValue() - * - * @param string[] $addresses - * - * @throws Swift_RfcComplianceException - */ - public function setAddresses($addresses) - { - $this->setNameAddresses(array_values((array) $addresses)); - } + /** + * Makes this Header represent a list of plain email addresses with no names. + * + * Example: + * + * setAddresses( + * array('one@domain.tld', 'two@domain.tld', 'three@domain.tld') + * ); + * ?> + * + * + * @see setNameAddresses() + * @see setValue() + * + * @param string[] $addresses + * + * @throws Swift_RfcComplianceException + */ + public function setAddresses($addresses) + { + $this->setNameAddresses(array_values((array) $addresses)); + } - /** - * Get all email addresses in this Header. - * - * @see getNameAddresses() - * - * @return string[] - */ - public function getAddresses() - { - return array_keys($this->mailboxes); - } + /** + * Get all email addresses in this Header. + * + * @see getNameAddresses() + * + * @return string[] + */ + public function getAddresses() + { + return array_keys($this->mailboxes); + } - /** - * Remove one or more addresses from this Header. - * - * @param string|string[] $addresses - */ - public function removeAddresses($addresses) - { - $this->setCachedValue(null); - foreach ((array) $addresses as $address) { - unset($this->mailboxes[$address]); - } - } + /** + * Remove one or more addresses from this Header. + * + * @param string|string[] $addresses + */ + public function removeAddresses($addresses) + { + $this->setCachedValue(null); + foreach ((array) $addresses as $address) { + unset($this->mailboxes[$address]); + } + } - /** - * Get the string value of the body in this Header. - * - * This is not necessarily RFC 2822 compliant since folding white space will - * not be added at this stage (see {@link toString()} for that). - * - * @see toString() - * - * @throws Swift_RfcComplianceException - * - * @return string - */ - public function getFieldBody() - { - // Compute the string value of the header only if needed - if (null === $this->getCachedValue()) { - $this->setCachedValue($this->createMailboxListString($this->mailboxes)); - } + /** + * Get the string value of the body in this Header. + * + * This is not necessarily RFC 2822 compliant since folding white space will + * not be added at this stage (see {@link toString()} for that). + * + * @see toString() + * + * @throws Swift_RfcComplianceException + * + * @return string + */ + public function getFieldBody() + { + // Compute the string value of the header only if needed + if (null === $this->getCachedValue()) { + $this->setCachedValue($this->createMailboxListString($this->mailboxes)); + } - return $this->getCachedValue(); - } + return $this->getCachedValue(); + } - /** - * Normalizes a user-input list of mailboxes into consistent key=>value pairs. - * - * @param string[] $mailboxes - * - * @return string[] - */ - protected function normalizeMailboxes(array $mailboxes) - { - $actualMailboxes = []; + /** + * Normalizes a user-input list of mailboxes into consistent key=>value pairs. + * + * @param string[] $mailboxes + * + * @return string[] + */ + protected function normalizeMailboxes(array $mailboxes) + { + $actualMailboxes = []; - foreach ($mailboxes as $key => $value) { - if (\is_string($key)) { - //key is email addr - $address = $key; - $name = $value; - } else { - $address = $value; - $name = null; - } - $this->assertValidAddress($address); - $actualMailboxes[$address] = $name; - } + foreach ($mailboxes as $key => $value) { + if (\is_string($key)) { + //key is email addr + $address = $key; + $name = $value; + } else { + $address = $value; + $name = null; + } + $this->assertValidAddress($address); + $actualMailboxes[$address] = $name; + } - return $actualMailboxes; - } + return $actualMailboxes; + } - /** - * Produces a compliant, formatted display-name based on the string given. - * - * @param string $displayName as displayed - * @param bool $shorten the first line to make remove for header name - * - * @return string - */ - protected function createDisplayNameString($displayName, $shorten = false) - { - return $this->createPhrase($this, $displayName, $this->getCharset(), $this->getEncoder(), $shorten); - } + /** + * Produces a compliant, formatted display-name based on the string given. + * + * @param string $displayName as displayed + * @param bool $shorten the first line to make remove for header name + * + * @return string + */ + protected function createDisplayNameString($displayName, $shorten = false) + { + return $this->createPhrase($this, $displayName, $this->getCharset(), $this->getEncoder(), $shorten); + } - /** - * Creates a string form of all the mailboxes in the passed array. - * - * @param string[] $mailboxes - * - * @throws Swift_RfcComplianceException - * - * @return string - */ - protected function createMailboxListString(array $mailboxes) - { - return implode(', ', $this->createNameAddressStrings($mailboxes)); - } + /** + * Creates a string form of all the mailboxes in the passed array. + * + * @param string[] $mailboxes + * + * @throws Swift_RfcComplianceException + * + * @return string + */ + protected function createMailboxListString(array $mailboxes) + { + return implode(', ', $this->createNameAddressStrings($mailboxes)); + } - /** - * Redefine the encoding requirements for mailboxes. - * - * All "specials" must be encoded as the full header value will not be quoted - * - * @see RFC 2822 3.2.1 - * - * @param string $token - * - * @return bool - */ - protected function tokenNeedsEncoding($token) - { - return preg_match('/[()<>\[\]:;@\,."]/', $token) || parent::tokenNeedsEncoding($token); - } + /** + * Redefine the encoding requirements for mailboxes. + * + * All "specials" must be encoded as the full header value will not be quoted + * + * @see RFC 2822 3.2.1 + * + * @param string $token + * + * @return bool + */ + protected function tokenNeedsEncoding($token) + { + return preg_match('/[()<>\[\]:;@\,."]/', $token) || parent::tokenNeedsEncoding($token); + } - /** - * Return an array of strings conforming the the name-addr spec of RFC 2822. - * - * @param string[] $mailboxes - * - * @return string[] - */ - private function createNameAddressStrings(array $mailboxes) - { - $strings = []; + /** + * Return an array of strings conforming the the name-addr spec of RFC 2822. + * + * @param string[] $mailboxes + * + * @return string[] + */ + private function createNameAddressStrings(array $mailboxes) + { + $strings = []; - foreach ($mailboxes as $email => $name) { - $mailboxStr = $this->addressEncoder->encodeString($email); - if (null !== $name) { - $nameStr = $this->createDisplayNameString($name, empty($strings)); - $mailboxStr = $nameStr.' <'.$mailboxStr.'>'; - } - $strings[] = $mailboxStr; - } + foreach ($mailboxes as $email => $name) { + $mailboxStr = $this->addressEncoder->encodeString($email); + if (null !== $name) { + $nameStr = $this->createDisplayNameString($name, empty($strings)); + $mailboxStr = $nameStr.' <'.$mailboxStr.'>'; + } + $strings[] = $mailboxStr; + } - return $strings; - } + return $strings; + } - /** - * Throws an Exception if the address passed does not comply with RFC 2822. - * - * @param string $address - * - * @throws Swift_RfcComplianceException if invalid - */ - private function assertValidAddress($address) - { - if (!$this->emailValidator->isValid($address, new RFCValidation())) { - throw new Swift_RfcComplianceException('Address in mailbox given ['.$address.'] does not comply with RFC 2822, 3.6.2.'); - } - } + /** + * Throws an Exception if the address passed does not comply with RFC 2822. + * + * @param string $address + * + * @throws Swift_RfcComplianceException if invalid + */ + private function assertValidAddress($address) + { + if (!$this->emailValidator->isValid($address, new RFCValidation())) { + throw new Swift_RfcComplianceException('Address in mailbox given ['.$address.'] does not comply with RFC 2822, 3.6.2.'); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/OpenDKIMHeader.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/OpenDKIMHeader.php index d0cb3504a97..fafb5bae21f 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/OpenDKIMHeader.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/OpenDKIMHeader.php @@ -17,119 +17,119 @@ */ class Swift_Mime_Headers_OpenDKIMHeader implements Swift_Mime_Header { - /** - * The value of this Header. - * - * @var string - */ - private $value; + /** + * The value of this Header. + * + * @var string + */ + private $value; - /** - * The name of this Header. - * - * @var string - */ - private $fieldName; + /** + * The name of this Header. + * + * @var string + */ + private $fieldName; - /** - * @param string $name - */ - public function __construct($name) - { - $this->fieldName = $name; - } + /** + * @param string $name + */ + public function __construct($name) + { + $this->fieldName = $name; + } - /** - * Get the type of Header that this instance represents. - * - * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX - * @see TYPE_DATE, TYPE_ID, TYPE_PATH - * - * @return int - */ - public function getFieldType() - { - return self::TYPE_TEXT; - } + /** + * Get the type of Header that this instance represents. + * + * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX + * @see TYPE_DATE, TYPE_ID, TYPE_PATH + * + * @return int + */ + public function getFieldType() + { + return self::TYPE_TEXT; + } - /** - * Set the model for the field body. - * - * This method takes a string for the field value. - * - * @param string $model - */ - public function setFieldBodyModel($model) - { - $this->setValue($model); - } + /** + * Set the model for the field body. + * + * This method takes a string for the field value. + * + * @param string $model + */ + public function setFieldBodyModel($model) + { + $this->setValue($model); + } - /** - * Get the model for the field body. - * - * This method returns a string. - * - * @return string - */ - public function getFieldBodyModel() - { - return $this->getValue(); - } + /** + * Get the model for the field body. + * + * This method returns a string. + * + * @return string + */ + public function getFieldBodyModel() + { + return $this->getValue(); + } - /** - * Get the (unencoded) value of this header. - * - * @return string - */ - public function getValue() - { - return $this->value; - } + /** + * Get the (unencoded) value of this header. + * + * @return string + */ + public function getValue() + { + return $this->value; + } - /** - * Set the (unencoded) value of this header. - * - * @param string $value - */ - public function setValue($value) - { - $this->value = $value; - } + /** + * Set the (unencoded) value of this header. + * + * @param string $value + */ + public function setValue($value) + { + $this->value = $value; + } - /** - * Get the value of this header prepared for rendering. - * - * @return string - */ - public function getFieldBody() - { - return $this->value; - } + /** + * Get the value of this header prepared for rendering. + * + * @return string + */ + public function getFieldBody() + { + return $this->value; + } - /** - * Get this Header rendered as a RFC 2822 compliant string. - * - * @return string - */ - public function toString() - { - return $this->fieldName.': '.$this->value."\r\n"; - } + /** + * Get this Header rendered as a RFC 2822 compliant string. + * + * @return string + */ + public function toString() + { + return $this->fieldName.': '.$this->value."\r\n"; + } - /** - * Set the Header FieldName. - * - * @see Swift_Mime_Header::getFieldName() - */ - public function getFieldName() - { - return $this->fieldName; - } + /** + * Set the Header FieldName. + * + * @see Swift_Mime_Header::getFieldName() + */ + public function getFieldName() + { + return $this->fieldName; + } - /** - * Ignored. - */ - public function setCharset($charset) - { - } + /** + * Ignored. + */ + public function setCharset($charset) + { + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/ParameterizedHeader.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/ParameterizedHeader.php index 6cd26a26465..47c15e6c05f 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/ParameterizedHeader.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/ParameterizedHeader.php @@ -15,241 +15,241 @@ */ class Swift_Mime_Headers_ParameterizedHeader extends Swift_Mime_Headers_UnstructuredHeader { - /** - * RFC 2231's definition of a token. - * - * @var string - */ - const TOKEN_REGEX = '(?:[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E]+)'; + /** + * RFC 2231's definition of a token. + * + * @var string + */ + const TOKEN_REGEX = '(?:[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E]+)'; - /** - * The Encoder used to encode the parameters. - * - * @var Swift_Encoder - */ - private $paramEncoder; + /** + * The Encoder used to encode the parameters. + * + * @var Swift_Encoder + */ + private $paramEncoder; - /** - * The parameters as an associative array. - * - * @var string[] - */ - private $params = []; + /** + * The parameters as an associative array. + * + * @var string[] + */ + private $params = []; - /** - * Creates a new ParameterizedHeader with $name. - * - * @param string $name - */ - public function __construct($name, Swift_Mime_HeaderEncoder $encoder, Swift_Encoder $paramEncoder = null) - { - parent::__construct($name, $encoder); - $this->paramEncoder = $paramEncoder; - } + /** + * Creates a new ParameterizedHeader with $name. + * + * @param string $name + */ + public function __construct($name, Swift_Mime_HeaderEncoder $encoder, Swift_Encoder $paramEncoder = null) + { + parent::__construct($name, $encoder); + $this->paramEncoder = $paramEncoder; + } - /** - * Get the type of Header that this instance represents. - * - * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX - * @see TYPE_DATE, TYPE_ID, TYPE_PATH - * - * @return int - */ - public function getFieldType() - { - return self::TYPE_PARAMETERIZED; - } + /** + * Get the type of Header that this instance represents. + * + * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX + * @see TYPE_DATE, TYPE_ID, TYPE_PATH + * + * @return int + */ + public function getFieldType() + { + return self::TYPE_PARAMETERIZED; + } - /** - * Set the character set used in this Header. - * - * @param string $charset - */ - public function setCharset($charset) - { - parent::setCharset($charset); - if (isset($this->paramEncoder)) { - $this->paramEncoder->charsetChanged($charset); - } - } + /** + * Set the character set used in this Header. + * + * @param string $charset + */ + public function setCharset($charset) + { + parent::setCharset($charset); + if (isset($this->paramEncoder)) { + $this->paramEncoder->charsetChanged($charset); + } + } - /** - * Set the value of $parameter. - * - * @param string $parameter - * @param string $value - */ - public function setParameter($parameter, $value) - { - $this->setParameters(array_merge($this->getParameters(), [$parameter => $value])); - } + /** + * Set the value of $parameter. + * + * @param string $parameter + * @param string $value + */ + public function setParameter($parameter, $value) + { + $this->setParameters(array_merge($this->getParameters(), [$parameter => $value])); + } - /** - * Get the value of $parameter. - * - * @param string $parameter - * - * @return string - */ - public function getParameter($parameter) - { - $params = $this->getParameters(); + /** + * Get the value of $parameter. + * + * @param string $parameter + * + * @return string + */ + public function getParameter($parameter) + { + $params = $this->getParameters(); - return $params[$parameter] ?? null; - } + return $params[$parameter] ?? null; + } - /** - * Set an associative array of parameter names mapped to values. - * - * @param string[] $parameters - */ - public function setParameters(array $parameters) - { - $this->clearCachedValueIf($this->params != $parameters); - $this->params = $parameters; - } + /** + * Set an associative array of parameter names mapped to values. + * + * @param string[] $parameters + */ + public function setParameters(array $parameters) + { + $this->clearCachedValueIf($this->params != $parameters); + $this->params = $parameters; + } - /** - * Returns an associative array of parameter names mapped to values. - * - * @return string[] - */ - public function getParameters() - { - return $this->params; - } + /** + * Returns an associative array of parameter names mapped to values. + * + * @return string[] + */ + public function getParameters() + { + return $this->params; + } - /** - * Get the value of this header prepared for rendering. - * - * @return string - */ - public function getFieldBody() //TODO: Check caching here - { - $body = parent::getFieldBody(); - foreach ($this->params as $name => $value) { - if (null !== $value) { - // Add the parameter - $body .= '; '.$this->createParameter($name, $value); - } - } + /** + * Get the value of this header prepared for rendering. + * + * @return string + */ + public function getFieldBody() //TODO: Check caching here + { + $body = parent::getFieldBody(); + foreach ($this->params as $name => $value) { + if (null !== $value) { + // Add the parameter + $body .= '; '.$this->createParameter($name, $value); + } + } - return $body; - } + return $body; + } - /** - * Generate a list of all tokens in the final header. - * - * This doesn't need to be overridden in theory, but it is for implementation - * reasons to prevent potential breakage of attributes. - * - * @param string $string The string to tokenize - * - * @return array An array of tokens as strings - */ - protected function toTokens($string = null) - { - $tokens = parent::toTokens(parent::getFieldBody()); + /** + * Generate a list of all tokens in the final header. + * + * This doesn't need to be overridden in theory, but it is for implementation + * reasons to prevent potential breakage of attributes. + * + * @param string $string The string to tokenize + * + * @return array An array of tokens as strings + */ + protected function toTokens($string = null) + { + $tokens = parent::toTokens(parent::getFieldBody()); - // Try creating any parameters - foreach ($this->params as $name => $value) { - if (null !== $value) { - // Add the semi-colon separator - $tokens[\count($tokens) - 1] .= ';'; - $tokens = array_merge($tokens, $this->generateTokenLines( - ' '.$this->createParameter($name, $value) - )); - } - } + // Try creating any parameters + foreach ($this->params as $name => $value) { + if (null !== $value) { + // Add the semi-colon separator + $tokens[\count($tokens) - 1] .= ';'; + $tokens = array_merge($tokens, $this->generateTokenLines( + ' '.$this->createParameter($name, $value) + )); + } + } - return $tokens; - } + return $tokens; + } - /** - * Render a RFC 2047 compliant header parameter from the $name and $value. - * - * @param string $name - * @param string $value - * - * @return string - */ - private function createParameter($name, $value) - { - $origValue = $value; + /** + * Render a RFC 2047 compliant header parameter from the $name and $value. + * + * @param string $name + * @param string $value + * + * @return string + */ + private function createParameter($name, $value) + { + $origValue = $value; - $encoded = false; - // Allow room for parameter name, indices, "=" and DQUOTEs - $maxValueLength = $this->getMaxLineLength() - \strlen($name.'=*N"";') - 1; - $firstLineOffset = 0; + $encoded = false; + // Allow room for parameter name, indices, "=" and DQUOTEs + $maxValueLength = $this->getMaxLineLength() - \strlen($name.'=*N"";') - 1; + $firstLineOffset = 0; - // If it's not already a valid parameter value... - if (!preg_match('/^'.self::TOKEN_REGEX.'$/D', $value)) { - // TODO: text, or something else?? - // ... and it's not ascii - if (!preg_match('/^[\x00-\x08\x0B\x0C\x0E-\x7F]*$/D', $value)) { - $encoded = true; - // Allow space for the indices, charset and language - $maxValueLength = $this->getMaxLineLength() - \strlen($name.'*N*="";') - 1; - $firstLineOffset = \strlen( - $this->getCharset()."'".$this->getLanguage()."'" - ); - } - } + // If it's not already a valid parameter value... + if (!preg_match('/^'.self::TOKEN_REGEX.'$/D', $value)) { + // TODO: text, or something else?? + // ... and it's not ascii + if (!preg_match('/^[\x00-\x08\x0B\x0C\x0E-\x7F]*$/D', $value)) { + $encoded = true; + // Allow space for the indices, charset and language + $maxValueLength = $this->getMaxLineLength() - \strlen($name.'*N*="";') - 1; + $firstLineOffset = \strlen( + $this->getCharset()."'".$this->getLanguage()."'" + ); + } + } - // Encode if we need to - if ($encoded || \strlen($value) > $maxValueLength) { - if (isset($this->paramEncoder)) { - $value = $this->paramEncoder->encodeString( - $origValue, $firstLineOffset, $maxValueLength, $this->getCharset() - ); - } else { - // We have to go against RFC 2183/2231 in some areas for interoperability - $value = $this->getTokenAsEncodedWord($origValue); - $encoded = false; - } - } + // Encode if we need to + if ($encoded || \strlen($value) > $maxValueLength) { + if (isset($this->paramEncoder)) { + $value = $this->paramEncoder->encodeString( + $origValue, $firstLineOffset, $maxValueLength, $this->getCharset() + ); + } else { + // We have to go against RFC 2183/2231 in some areas for interoperability + $value = $this->getTokenAsEncodedWord($origValue); + $encoded = false; + } + } - $valueLines = isset($this->paramEncoder) ? explode("\r\n", $value) : [$value]; + $valueLines = isset($this->paramEncoder) ? explode("\r\n", $value) : [$value]; - // Need to add indices - if (\count($valueLines) > 1) { - $paramLines = []; - foreach ($valueLines as $i => $line) { - $paramLines[] = $name.'*'.$i. - $this->getEndOfParameterValue($line, true, 0 == $i); - } + // Need to add indices + if (\count($valueLines) > 1) { + $paramLines = []; + foreach ($valueLines as $i => $line) { + $paramLines[] = $name.'*'.$i. + $this->getEndOfParameterValue($line, true, 0 == $i); + } - return implode(";\r\n ", $paramLines); - } else { - return $name.$this->getEndOfParameterValue( - $valueLines[0], $encoded, true - ); - } - } + return implode(";\r\n ", $paramLines); + } else { + return $name.$this->getEndOfParameterValue( + $valueLines[0], $encoded, true + ); + } + } - /** - * Returns the parameter value from the "=" and beyond. - * - * @param string $value to append - * @param bool $encoded - * @param bool $firstLine - * - * @return string - */ - private function getEndOfParameterValue($value, $encoded = false, $firstLine = false) - { - if (!preg_match('/^'.self::TOKEN_REGEX.'$/D', $value)) { - $value = '"'.$value.'"'; - } - $prepend = '='; - if ($encoded) { - $prepend = '*='; - if ($firstLine) { - $prepend = '*='.$this->getCharset()."'".$this->getLanguage(). - "'"; - } - } + /** + * Returns the parameter value from the "=" and beyond. + * + * @param string $value to append + * @param bool $encoded + * @param bool $firstLine + * + * @return string + */ + private function getEndOfParameterValue($value, $encoded = false, $firstLine = false) + { + if (!preg_match('/^'.self::TOKEN_REGEX.'$/D', $value)) { + $value = '"'.$value.'"'; + } + $prepend = '='; + if ($encoded) { + $prepend = '*='; + if ($firstLine) { + $prepend = '*='.$this->getCharset()."'".$this->getLanguage(). + "'"; + } + } - return $prepend.$value; - } + return $prepend.$value; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/PathHeader.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/PathHeader.php index 86ab1deaf50..81b421ee7a8 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/PathHeader.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/PathHeader.php @@ -18,136 +18,136 @@ use Egulias\EmailValidator\Validation\RFCValidation; */ class Swift_Mime_Headers_PathHeader extends Swift_Mime_Headers_AbstractHeader { - /** - * The address in this Header (if specified). - * - * @var string - */ - private $address; + /** + * The address in this Header (if specified). + * + * @var string + */ + private $address; - /** - * The strict EmailValidator. - * - * @var EmailValidator - */ - private $emailValidator; + /** + * The strict EmailValidator. + * + * @var EmailValidator + */ + private $emailValidator; - private $addressEncoder; + private $addressEncoder; - /** - * Creates a new PathHeader with the given $name. - * - * @param string $name - */ - public function __construct($name, EmailValidator $emailValidator, Swift_AddressEncoder $addressEncoder = null) - { - $this->setFieldName($name); - $this->emailValidator = $emailValidator; - $this->addressEncoder = $addressEncoder ?? new Swift_AddressEncoder_IdnAddressEncoder(); - } + /** + * Creates a new PathHeader with the given $name. + * + * @param string $name + */ + public function __construct($name, EmailValidator $emailValidator, Swift_AddressEncoder $addressEncoder = null) + { + $this->setFieldName($name); + $this->emailValidator = $emailValidator; + $this->addressEncoder = $addressEncoder ?? new Swift_AddressEncoder_IdnAddressEncoder(); + } - /** - * Get the type of Header that this instance represents. - * - * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX - * @see TYPE_DATE, TYPE_ID, TYPE_PATH - * - * @return int - */ - public function getFieldType() - { - return self::TYPE_PATH; - } + /** + * Get the type of Header that this instance represents. + * + * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX + * @see TYPE_DATE, TYPE_ID, TYPE_PATH + * + * @return int + */ + public function getFieldType() + { + return self::TYPE_PATH; + } - /** - * Set the model for the field body. - * This method takes a string for an address. - * - * @param string $model - * - * @throws Swift_RfcComplianceException - */ - public function setFieldBodyModel($model) - { - $this->setAddress($model); - } + /** + * Set the model for the field body. + * This method takes a string for an address. + * + * @param string $model + * + * @throws Swift_RfcComplianceException + */ + public function setFieldBodyModel($model) + { + $this->setAddress($model); + } - /** - * Get the model for the field body. - * This method returns a string email address. - * - * @return mixed - */ - public function getFieldBodyModel() - { - return $this->getAddress(); - } + /** + * Get the model for the field body. + * This method returns a string email address. + * + * @return mixed + */ + public function getFieldBodyModel() + { + return $this->getAddress(); + } - /** - * Set the Address which should appear in this Header. - * - * @param string $address - * - * @throws Swift_RfcComplianceException - */ - public function setAddress($address) - { - if (null === $address) { - $this->address = null; - } elseif ('' == $address) { - $this->address = ''; - } else { - $this->assertValidAddress($address); - $this->address = $address; - } - $this->setCachedValue(null); - } + /** + * Set the Address which should appear in this Header. + * + * @param string $address + * + * @throws Swift_RfcComplianceException + */ + public function setAddress($address) + { + if (null === $address) { + $this->address = null; + } elseif ('' == $address) { + $this->address = ''; + } else { + $this->assertValidAddress($address); + $this->address = $address; + } + $this->setCachedValue(null); + } - /** - * Get the address which is used in this Header (if any). - * - * Null is returned if no address is set. - * - * @return string - */ - public function getAddress() - { - return $this->address; - } + /** + * Get the address which is used in this Header (if any). + * + * Null is returned if no address is set. + * + * @return string + */ + public function getAddress() + { + return $this->address; + } - /** - * Get the string value of the body in this Header. - * - * This is not necessarily RFC 2822 compliant since folding white space will - * not be added at this stage (see {@link toString()} for that). - * - * @see toString() - * - * @return string - */ - public function getFieldBody() - { - if (!$this->getCachedValue()) { - if (isset($this->address)) { - $address = $this->addressEncoder->encodeString($this->address); - $this->setCachedValue('<'.$address.'>'); - } - } + /** + * Get the string value of the body in this Header. + * + * This is not necessarily RFC 2822 compliant since folding white space will + * not be added at this stage (see {@link toString()} for that). + * + * @see toString() + * + * @return string + */ + public function getFieldBody() + { + if (!$this->getCachedValue()) { + if (isset($this->address)) { + $address = $this->addressEncoder->encodeString($this->address); + $this->setCachedValue('<'.$address.'>'); + } + } - return $this->getCachedValue(); - } + return $this->getCachedValue(); + } - /** - * Throws an Exception if the address passed does not comply with RFC 2822. - * - * @param string $address - * - * @throws Swift_RfcComplianceException If address is invalid - */ - private function assertValidAddress($address) - { - if (!$this->emailValidator->isValid($address, new RFCValidation())) { - throw new Swift_RfcComplianceException('Address set in PathHeader does not comply with addr-spec of RFC 2822.'); - } - } + /** + * Throws an Exception if the address passed does not comply with RFC 2822. + * + * @param string $address + * + * @throws Swift_RfcComplianceException If address is invalid + */ + private function assertValidAddress($address) + { + if (!$this->emailValidator->isValid($address, new RFCValidation())) { + throw new Swift_RfcComplianceException('Address set in PathHeader does not comply with addr-spec of RFC 2822.'); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/UnstructuredHeader.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/UnstructuredHeader.php index 7d51945aabb..64f160dec7c 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/UnstructuredHeader.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/Headers/UnstructuredHeader.php @@ -15,95 +15,95 @@ */ class Swift_Mime_Headers_UnstructuredHeader extends Swift_Mime_Headers_AbstractHeader { - /** - * The value of this Header. - * - * @var string - */ - private $value; + /** + * The value of this Header. + * + * @var string + */ + private $value; - /** - * Creates a new SimpleHeader with $name. - * - * @param string $name - */ - public function __construct($name, Swift_Mime_HeaderEncoder $encoder) - { - $this->setFieldName($name); - $this->setEncoder($encoder); - } + /** + * Creates a new SimpleHeader with $name. + * + * @param string $name + */ + public function __construct($name, Swift_Mime_HeaderEncoder $encoder) + { + $this->setFieldName($name); + $this->setEncoder($encoder); + } - /** - * Get the type of Header that this instance represents. - * - * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX - * @see TYPE_DATE, TYPE_ID, TYPE_PATH - * - * @return int - */ - public function getFieldType() - { - return self::TYPE_TEXT; - } + /** + * Get the type of Header that this instance represents. + * + * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX + * @see TYPE_DATE, TYPE_ID, TYPE_PATH + * + * @return int + */ + public function getFieldType() + { + return self::TYPE_TEXT; + } - /** - * Set the model for the field body. - * - * This method takes a string for the field value. - * - * @param string $model - */ - public function setFieldBodyModel($model) - { - $this->setValue($model); - } + /** + * Set the model for the field body. + * + * This method takes a string for the field value. + * + * @param string $model + */ + public function setFieldBodyModel($model) + { + $this->setValue($model); + } - /** - * Get the model for the field body. - * - * This method returns a string. - * - * @return string - */ - public function getFieldBodyModel() - { - return $this->getValue(); - } + /** + * Get the model for the field body. + * + * This method returns a string. + * + * @return string + */ + public function getFieldBodyModel() + { + return $this->getValue(); + } - /** - * Get the (unencoded) value of this header. - * - * @return string - */ - public function getValue() - { - return $this->value; - } + /** + * Get the (unencoded) value of this header. + * + * @return string + */ + public function getValue() + { + return $this->value; + } - /** - * Set the (unencoded) value of this header. - * - * @param string $value - */ - public function setValue($value) - { - $this->clearCachedValueIf($this->value != $value); - $this->value = $value; - } + /** + * Set the (unencoded) value of this header. + * + * @param string $value + */ + public function setValue($value) + { + $this->clearCachedValueIf($this->value != $value); + $this->value = $value; + } - /** - * Get the value of this header prepared for rendering. - * - * @return string - */ - public function getFieldBody() - { - if (!$this->getCachedValue()) { - $this->setCachedValue( - $this->encodeWords($this, $this->value) - ); - } + /** + * Get the value of this header prepared for rendering. + * + * @return string + */ + public function getFieldBody() + { + if (!$this->getCachedValue()) { + $this->setCachedValue( + $this->encodeWords($this, $this->value) + ); + } - return $this->getCachedValue(); - } + return $this->getCachedValue(); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/IdGenerator.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/IdGenerator.php index a8fd141a26a..3ce35f27c03 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/IdGenerator.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/IdGenerator.php @@ -13,42 +13,42 @@ */ class Swift_Mime_IdGenerator implements Swift_IdGenerator { - private $idRight; + private $idRight; - /** - * @param string $idRight - */ - public function __construct($idRight) - { - $this->idRight = $idRight; - } + /** + * @param string $idRight + */ + public function __construct($idRight) + { + $this->idRight = $idRight; + } - /** - * Returns the right-hand side of the "@" used in all generated IDs. - * - * @return string - */ - public function getIdRight() - { - return $this->idRight; - } + /** + * Returns the right-hand side of the "@" used in all generated IDs. + * + * @return string + */ + public function getIdRight() + { + return $this->idRight; + } - /** - * Sets the right-hand side of the "@" to use in all generated IDs. - * - * @param string $idRight - */ - public function setIdRight($idRight) - { - $this->idRight = $idRight; - } + /** + * Sets the right-hand side of the "@" to use in all generated IDs. + * + * @param string $idRight + */ + public function setIdRight($idRight) + { + $this->idRight = $idRight; + } - /** - * @return string - */ - public function generateId() - { - // 32 hex values for the left part - return bin2hex(random_bytes(16)).'@'.$this->idRight; - } + /** + * @return string + */ + public function generateId() + { + // 32 hex values for the left part + return bin2hex(random_bytes(16)).'@'.$this->idRight; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/MimePart.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/MimePart.php index 560f5ba64a5..d0b2e6586b4 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/MimePart.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/MimePart.php @@ -15,185 +15,185 @@ */ class Swift_Mime_MimePart extends Swift_Mime_SimpleMimeEntity { - /** The format parameter last specified by the user */ - protected $userFormat; + /** The format parameter last specified by the user */ + protected $userFormat; - /** The charset last specified by the user */ - protected $userCharset; + /** The charset last specified by the user */ + protected $userCharset; - /** The delsp parameter last specified by the user */ - protected $userDelSp; + /** The delsp parameter last specified by the user */ + protected $userDelSp; - /** The nesting level of this MimePart */ - private $nestingLevel = self::LEVEL_ALTERNATIVE; + /** The nesting level of this MimePart */ + private $nestingLevel = self::LEVEL_ALTERNATIVE; - /** - * Create a new MimePart with $headers, $encoder and $cache. - * - * @param string $charset - */ - public function __construct(Swift_Mime_SimpleHeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_IdGenerator $idGenerator, $charset = null) - { - parent::__construct($headers, $encoder, $cache, $idGenerator); - $this->setContentType('text/plain'); - if (null !== $charset) { - $this->setCharset($charset); - } - } + /** + * Create a new MimePart with $headers, $encoder and $cache. + * + * @param string $charset + */ + public function __construct(Swift_Mime_SimpleHeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_IdGenerator $idGenerator, $charset = null) + { + parent::__construct($headers, $encoder, $cache, $idGenerator); + $this->setContentType('text/plain'); + if (null !== $charset) { + $this->setCharset($charset); + } + } - /** - * Set the body of this entity, either as a string, or as an instance of - * {@link Swift_OutputByteStream}. - * - * @param mixed $body - * @param string $contentType optional - * @param string $charset optional - * - * @return $this - */ - public function setBody($body, $contentType = null, $charset = null) - { - if (isset($charset)) { - $this->setCharset($charset); - } - $body = $this->convertString($body); + /** + * Set the body of this entity, either as a string, or as an instance of + * {@link Swift_OutputByteStream}. + * + * @param mixed $body + * @param string $contentType optional + * @param string $charset optional + * + * @return $this + */ + public function setBody($body, $contentType = null, $charset = null) + { + if (isset($charset)) { + $this->setCharset($charset); + } + $body = $this->convertString($body); - parent::setBody($body, $contentType); + parent::setBody($body, $contentType); - return $this; - } + return $this; + } - /** - * Get the character set of this entity. - * - * @return string - */ - public function getCharset() - { - return $this->getHeaderParameter('Content-Type', 'charset'); - } + /** + * Get the character set of this entity. + * + * @return string + */ + public function getCharset() + { + return $this->getHeaderParameter('Content-Type', 'charset'); + } - /** - * Set the character set of this entity. - * - * @param string $charset - * - * @return $this - */ - public function setCharset($charset) - { - $this->setHeaderParameter('Content-Type', 'charset', $charset); - if ($charset !== $this->userCharset) { - $this->clearCache(); - } - $this->userCharset = $charset; - parent::charsetChanged($charset); + /** + * Set the character set of this entity. + * + * @param string $charset + * + * @return $this + */ + public function setCharset($charset) + { + $this->setHeaderParameter('Content-Type', 'charset', $charset); + if ($charset !== $this->userCharset) { + $this->clearCache(); + } + $this->userCharset = $charset; + parent::charsetChanged($charset); - return $this; - } + return $this; + } - /** - * Get the format of this entity (i.e. flowed or fixed). - * - * @return string - */ - public function getFormat() - { - return $this->getHeaderParameter('Content-Type', 'format'); - } + /** + * Get the format of this entity (i.e. flowed or fixed). + * + * @return string + */ + public function getFormat() + { + return $this->getHeaderParameter('Content-Type', 'format'); + } - /** - * Set the format of this entity (flowed or fixed). - * - * @param string $format - * - * @return $this - */ - public function setFormat($format) - { - $this->setHeaderParameter('Content-Type', 'format', $format); - $this->userFormat = $format; + /** + * Set the format of this entity (flowed or fixed). + * + * @param string $format + * + * @return $this + */ + public function setFormat($format) + { + $this->setHeaderParameter('Content-Type', 'format', $format); + $this->userFormat = $format; - return $this; - } + return $this; + } - /** - * Test if delsp is being used for this entity. - * - * @return bool - */ - public function getDelSp() - { - return 'yes' === $this->getHeaderParameter('Content-Type', 'delsp'); - } + /** + * Test if delsp is being used for this entity. + * + * @return bool + */ + public function getDelSp() + { + return 'yes' === $this->getHeaderParameter('Content-Type', 'delsp'); + } - /** - * Turn delsp on or off for this entity. - * - * @param bool $delsp - * - * @return $this - */ - public function setDelSp($delsp = true) - { - $this->setHeaderParameter('Content-Type', 'delsp', $delsp ? 'yes' : null); - $this->userDelSp = $delsp; + /** + * Turn delsp on or off for this entity. + * + * @param bool $delsp + * + * @return $this + */ + public function setDelSp($delsp = true) + { + $this->setHeaderParameter('Content-Type', 'delsp', $delsp ? 'yes' : null); + $this->userDelSp = $delsp; - return $this; - } + return $this; + } - /** - * Get the nesting level of this entity. - * - * @see LEVEL_TOP, LEVEL_ALTERNATIVE, LEVEL_MIXED, LEVEL_RELATED - * - * @return int - */ - public function getNestingLevel() - { - return $this->nestingLevel; - } + /** + * Get the nesting level of this entity. + * + * @see LEVEL_TOP, LEVEL_ALTERNATIVE, LEVEL_MIXED, LEVEL_RELATED + * + * @return int + */ + public function getNestingLevel() + { + return $this->nestingLevel; + } - /** - * Receive notification that the charset has changed on this document, or a - * parent document. - * - * @param string $charset - */ - public function charsetChanged($charset) - { - $this->setCharset($charset); - } + /** + * Receive notification that the charset has changed on this document, or a + * parent document. + * + * @param string $charset + */ + public function charsetChanged($charset) + { + $this->setCharset($charset); + } - /** Fix the content-type and encoding of this entity */ - protected function fixHeaders() - { - parent::fixHeaders(); - if (\count($this->getChildren())) { - $this->setHeaderParameter('Content-Type', 'charset', null); - $this->setHeaderParameter('Content-Type', 'format', null); - $this->setHeaderParameter('Content-Type', 'delsp', null); - } else { - $this->setCharset($this->userCharset); - $this->setFormat($this->userFormat); - $this->setDelSp($this->userDelSp); - } - } + /** Fix the content-type and encoding of this entity */ + protected function fixHeaders() + { + parent::fixHeaders(); + if (\count($this->getChildren())) { + $this->setHeaderParameter('Content-Type', 'charset', null); + $this->setHeaderParameter('Content-Type', 'format', null); + $this->setHeaderParameter('Content-Type', 'delsp', null); + } else { + $this->setCharset($this->userCharset); + $this->setFormat($this->userFormat); + $this->setDelSp($this->userDelSp); + } + } - /** Set the nesting level of this entity */ - protected function setNestingLevel($level) - { - $this->nestingLevel = $level; - } + /** Set the nesting level of this entity */ + protected function setNestingLevel($level) + { + $this->nestingLevel = $level; + } - /** Encode charset when charset is not utf-8 */ - protected function convertString($string) - { - $charset = strtolower($this->getCharset() ?? ''); - if (!\in_array($charset, ['utf-8', 'iso-8859-1', 'iso-8859-15', ''])) { - return mb_convert_encoding($string, $charset, 'utf-8'); - } + /** Encode charset when charset is not utf-8 */ + protected function convertString($string) + { + $charset = strtolower($this->getCharset() ?? ''); + if (!\in_array($charset, ['utf-8', 'iso-8859-1', 'iso-8859-15', ''])) { + return mb_convert_encoding($string, $charset, 'utf-8'); + } - return $string; - } + return $string; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleHeaderFactory.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleHeaderFactory.php index 347fa74cf66..ab3ce6b1914 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleHeaderFactory.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleHeaderFactory.php @@ -17,179 +17,179 @@ use Egulias\EmailValidator\EmailValidator; */ class Swift_Mime_SimpleHeaderFactory implements Swift_Mime_CharsetObserver { - /** The HeaderEncoder used by these headers */ - private $encoder; + /** The HeaderEncoder used by these headers */ + private $encoder; - /** The Encoder used by parameters */ - private $paramEncoder; + /** The Encoder used by parameters */ + private $paramEncoder; - /** Strict EmailValidator */ - private $emailValidator; + /** Strict EmailValidator */ + private $emailValidator; - /** The charset of created Headers */ - private $charset; + /** The charset of created Headers */ + private $charset; - /** Swift_AddressEncoder */ - private $addressEncoder; + /** Swift_AddressEncoder */ + private $addressEncoder; - /** - * Creates a new SimpleHeaderFactory using $encoder and $paramEncoder. - * - * @param string|null $charset - */ - public function __construct(Swift_Mime_HeaderEncoder $encoder, Swift_Encoder $paramEncoder, EmailValidator $emailValidator, $charset = null, Swift_AddressEncoder $addressEncoder = null) - { - $this->encoder = $encoder; - $this->paramEncoder = $paramEncoder; - $this->emailValidator = $emailValidator; - $this->charset = $charset; - $this->addressEncoder = $addressEncoder ?? new Swift_AddressEncoder_IdnAddressEncoder(); - } + /** + * Creates a new SimpleHeaderFactory using $encoder and $paramEncoder. + * + * @param string|null $charset + */ + public function __construct(Swift_Mime_HeaderEncoder $encoder, Swift_Encoder $paramEncoder, EmailValidator $emailValidator, $charset = null, Swift_AddressEncoder $addressEncoder = null) + { + $this->encoder = $encoder; + $this->paramEncoder = $paramEncoder; + $this->emailValidator = $emailValidator; + $this->charset = $charset; + $this->addressEncoder = $addressEncoder ?? new Swift_AddressEncoder_IdnAddressEncoder(); + } - /** - * Create a new Mailbox Header with a list of $addresses. - * - * @param string $name - * @param array|string|null $addresses - * - * @return Swift_Mime_Header - */ - public function createMailboxHeader($name, $addresses = null) - { - $header = new Swift_Mime_Headers_MailboxHeader($name, $this->encoder, $this->emailValidator, $this->addressEncoder); - if (isset($addresses)) { - $header->setFieldBodyModel($addresses); - } - $this->setHeaderCharset($header); + /** + * Create a new Mailbox Header with a list of $addresses. + * + * @param string $name + * @param array|string|null $addresses + * + * @return Swift_Mime_Header + */ + public function createMailboxHeader($name, $addresses = null) + { + $header = new Swift_Mime_Headers_MailboxHeader($name, $this->encoder, $this->emailValidator, $this->addressEncoder); + if (isset($addresses)) { + $header->setFieldBodyModel($addresses); + } + $this->setHeaderCharset($header); - return $header; - } + return $header; + } - /** - * Create a new Date header using $dateTime. - * - * @param string $name - * - * @return Swift_Mime_Header - */ - public function createDateHeader($name, DateTimeInterface $dateTime = null) - { - $header = new Swift_Mime_Headers_DateHeader($name); - if (isset($dateTime)) { - $header->setFieldBodyModel($dateTime); - } - $this->setHeaderCharset($header); + /** + * Create a new Date header using $dateTime. + * + * @param string $name + * + * @return Swift_Mime_Header + */ + public function createDateHeader($name, DateTimeInterface $dateTime = null) + { + $header = new Swift_Mime_Headers_DateHeader($name); + if (isset($dateTime)) { + $header->setFieldBodyModel($dateTime); + } + $this->setHeaderCharset($header); - return $header; - } + return $header; + } - /** - * Create a new basic text header with $name and $value. - * - * @param string $name - * @param string $value - * - * @return Swift_Mime_Header - */ - public function createTextHeader($name, $value = null) - { - $header = new Swift_Mime_Headers_UnstructuredHeader($name, $this->encoder); - if (isset($value)) { - $header->setFieldBodyModel($value); - } - $this->setHeaderCharset($header); + /** + * Create a new basic text header with $name and $value. + * + * @param string $name + * @param string $value + * + * @return Swift_Mime_Header + */ + public function createTextHeader($name, $value = null) + { + $header = new Swift_Mime_Headers_UnstructuredHeader($name, $this->encoder); + if (isset($value)) { + $header->setFieldBodyModel($value); + } + $this->setHeaderCharset($header); - return $header; - } + return $header; + } - /** - * Create a new ParameterizedHeader with $name, $value and $params. - * - * @param string $name - * @param string $value - * @param array $params - * - * @return Swift_Mime_Headers_ParameterizedHeader - */ - public function createParameterizedHeader($name, $value = null, $params = []) - { - $header = new Swift_Mime_Headers_ParameterizedHeader($name, $this->encoder, ('content-disposition' == strtolower($name ?? '')) ? $this->paramEncoder : null); - if (isset($value)) { - $header->setFieldBodyModel($value); - } - foreach ($params as $k => $v) { - $header->setParameter($k, $v); - } - $this->setHeaderCharset($header); + /** + * Create a new ParameterizedHeader with $name, $value and $params. + * + * @param string $name + * @param string $value + * @param array $params + * + * @return Swift_Mime_Headers_ParameterizedHeader + */ + public function createParameterizedHeader($name, $value = null, $params = []) + { + $header = new Swift_Mime_Headers_ParameterizedHeader($name, $this->encoder, ('content-disposition' == strtolower($name ?? '')) ? $this->paramEncoder : null); + if (isset($value)) { + $header->setFieldBodyModel($value); + } + foreach ($params as $k => $v) { + $header->setParameter($k, $v); + } + $this->setHeaderCharset($header); - return $header; - } + return $header; + } - /** - * Create a new ID header for Message-ID or Content-ID. - * - * @param string $name - * @param string|array $ids - * - * @return Swift_Mime_Header - */ - public function createIdHeader($name, $ids = null) - { - $header = new Swift_Mime_Headers_IdentificationHeader($name, $this->emailValidator); - if (isset($ids)) { - $header->setFieldBodyModel($ids); - } - $this->setHeaderCharset($header); + /** + * Create a new ID header for Message-ID or Content-ID. + * + * @param string $name + * @param string|array $ids + * + * @return Swift_Mime_Header + */ + public function createIdHeader($name, $ids = null) + { + $header = new Swift_Mime_Headers_IdentificationHeader($name, $this->emailValidator); + if (isset($ids)) { + $header->setFieldBodyModel($ids); + } + $this->setHeaderCharset($header); - return $header; - } + return $header; + } - /** - * Create a new Path header with an address (path) in it. - * - * @param string $name - * @param string $path - * - * @return Swift_Mime_Header - */ - public function createPathHeader($name, $path = null) - { - $header = new Swift_Mime_Headers_PathHeader($name, $this->emailValidator); - if (isset($path)) { - $header->setFieldBodyModel($path); - } - $this->setHeaderCharset($header); + /** + * Create a new Path header with an address (path) in it. + * + * @param string $name + * @param string $path + * + * @return Swift_Mime_Header + */ + public function createPathHeader($name, $path = null) + { + $header = new Swift_Mime_Headers_PathHeader($name, $this->emailValidator); + if (isset($path)) { + $header->setFieldBodyModel($path); + } + $this->setHeaderCharset($header); - return $header; - } + return $header; + } - /** - * Notify this observer that the entity's charset has changed. - * - * @param string $charset - */ - public function charsetChanged($charset) - { - $this->charset = $charset; - $this->encoder->charsetChanged($charset); - $this->paramEncoder->charsetChanged($charset); - } + /** + * Notify this observer that the entity's charset has changed. + * + * @param string $charset + */ + public function charsetChanged($charset) + { + $this->charset = $charset; + $this->encoder->charsetChanged($charset); + $this->paramEncoder->charsetChanged($charset); + } - /** - * Make a deep copy of object. - */ - public function __clone() - { - $this->encoder = clone $this->encoder; - $this->paramEncoder = clone $this->paramEncoder; - $this->addressEncoder = clone $this->addressEncoder; - } + /** + * Make a deep copy of object. + */ + public function __clone() + { + $this->encoder = clone $this->encoder; + $this->paramEncoder = clone $this->paramEncoder; + $this->addressEncoder = clone $this->addressEncoder; + } - /** Apply the charset to the Header */ - private function setHeaderCharset(Swift_Mime_Header $header) - { - if (isset($this->charset)) { - $header->setCharset($this->charset); - } - } + /** Apply the charset to the Header */ + private function setHeaderCharset(Swift_Mime_Header $header) + { + if (isset($this->charset)) { + $header->setCharset($this->charset); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleHeaderSet.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleHeaderSet.php index 219c46f32ff..5195bcf48ae 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleHeaderSet.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleHeaderSet.php @@ -15,385 +15,385 @@ */ class Swift_Mime_SimpleHeaderSet implements Swift_Mime_CharsetObserver { - /** HeaderFactory */ - private $factory; + /** HeaderFactory */ + private $factory; - /** Collection of set Headers */ - private $headers = []; + /** Collection of set Headers */ + private $headers = []; - /** Field ordering details */ - private $order = []; + /** Field ordering details */ + private $order = []; - /** List of fields which are required to be displayed */ - private $required = []; + /** List of fields which are required to be displayed */ + private $required = []; - /** The charset used by Headers */ - private $charset; + /** The charset used by Headers */ + private $charset; - /** - * Create a new SimpleHeaderSet with the given $factory. - * - * @param string $charset - */ - public function __construct(Swift_Mime_SimpleHeaderFactory $factory, $charset = null) - { - $this->factory = $factory; - if (isset($charset)) { - $this->setCharset($charset); - } - } + /** + * Create a new SimpleHeaderSet with the given $factory. + * + * @param string $charset + */ + public function __construct(Swift_Mime_SimpleHeaderFactory $factory, $charset = null) + { + $this->factory = $factory; + if (isset($charset)) { + $this->setCharset($charset); + } + } - public function newInstance() - { - return new self($this->factory); - } + public function newInstance() + { + return new self($this->factory); + } - /** - * Set the charset used by these headers. - * - * @param string $charset - */ - public function setCharset($charset) - { - $this->charset = $charset; - $this->factory->charsetChanged($charset); - $this->notifyHeadersOfCharset($charset); - } + /** + * Set the charset used by these headers. + * + * @param string $charset + */ + public function setCharset($charset) + { + $this->charset = $charset; + $this->factory->charsetChanged($charset); + $this->notifyHeadersOfCharset($charset); + } - /** - * Add a new Mailbox Header with a list of $addresses. - * - * @param string $name - * @param array|string $addresses - */ - public function addMailboxHeader($name, $addresses = null) - { - $this->storeHeader($name, $this->factory->createMailboxHeader($name, $addresses)); - } + /** + * Add a new Mailbox Header with a list of $addresses. + * + * @param string $name + * @param array|string $addresses + */ + public function addMailboxHeader($name, $addresses = null) + { + $this->storeHeader($name, $this->factory->createMailboxHeader($name, $addresses)); + } - /** - * Add a new Date header using $dateTime. - * - * @param string $name - */ - public function addDateHeader($name, DateTimeInterface $dateTime = null) - { - $this->storeHeader($name, $this->factory->createDateHeader($name, $dateTime)); - } + /** + * Add a new Date header using $dateTime. + * + * @param string $name + */ + public function addDateHeader($name, DateTimeInterface $dateTime = null) + { + $this->storeHeader($name, $this->factory->createDateHeader($name, $dateTime)); + } - /** - * Add a new basic text header with $name and $value. - * - * @param string $name - * @param string $value - */ - public function addTextHeader($name, $value = null) - { - $this->storeHeader($name, $this->factory->createTextHeader($name, $value)); - } + /** + * Add a new basic text header with $name and $value. + * + * @param string $name + * @param string $value + */ + public function addTextHeader($name, $value = null) + { + $this->storeHeader($name, $this->factory->createTextHeader($name, $value)); + } - /** - * Add a new ParameterizedHeader with $name, $value and $params. - * - * @param string $name - * @param string $value - * @param array $params - */ - public function addParameterizedHeader($name, $value = null, $params = []) - { - $this->storeHeader($name, $this->factory->createParameterizedHeader($name, $value, $params)); - } + /** + * Add a new ParameterizedHeader with $name, $value and $params. + * + * @param string $name + * @param string $value + * @param array $params + */ + public function addParameterizedHeader($name, $value = null, $params = []) + { + $this->storeHeader($name, $this->factory->createParameterizedHeader($name, $value, $params)); + } - /** - * Add a new ID header for Message-ID or Content-ID. - * - * @param string $name - * @param string|array $ids - */ - public function addIdHeader($name, $ids = null) - { - $this->storeHeader($name, $this->factory->createIdHeader($name, $ids)); - } + /** + * Add a new ID header for Message-ID or Content-ID. + * + * @param string $name + * @param string|array $ids + */ + public function addIdHeader($name, $ids = null) + { + $this->storeHeader($name, $this->factory->createIdHeader($name, $ids)); + } - /** - * Add a new Path header with an address (path) in it. - * - * @param string $name - * @param string $path - */ - public function addPathHeader($name, $path = null) - { - $this->storeHeader($name, $this->factory->createPathHeader($name, $path)); - } + /** + * Add a new Path header with an address (path) in it. + * + * @param string $name + * @param string $path + */ + public function addPathHeader($name, $path = null) + { + $this->storeHeader($name, $this->factory->createPathHeader($name, $path)); + } - /** - * Returns true if at least one header with the given $name exists. - * - * If multiple headers match, the actual one may be specified by $index. - * - * @param string $name - * @param int $index - * - * @return bool - */ - public function has($name, $index = 0) - { - $lowerName = strtolower($name ?? ''); + /** + * Returns true if at least one header with the given $name exists. + * + * If multiple headers match, the actual one may be specified by $index. + * + * @param string $name + * @param int $index + * + * @return bool + */ + public function has($name, $index = 0) + { + $lowerName = strtolower($name ?? ''); - if (!\array_key_exists($lowerName, $this->headers)) { - return false; - } + if (!\array_key_exists($lowerName, $this->headers)) { + return false; + } - if (\func_num_args() < 2) { - // index was not specified, so we only need to check that there is at least one header value set - return (bool) \count($this->headers[$lowerName]); - } + if (\func_num_args() < 2) { + // index was not specified, so we only need to check that there is at least one header value set + return (bool) \count($this->headers[$lowerName]); + } - return \array_key_exists($index, $this->headers[$lowerName]); - } + return \array_key_exists($index, $this->headers[$lowerName]); + } - /** - * Set a header in the HeaderSet. - * - * The header may be a previously fetched header via {@link get()} or it may - * be one that has been created separately. - * - * If $index is specified, the header will be inserted into the set at this - * offset. - * - * @param int $index - */ - public function set(Swift_Mime_Header $header, $index = 0) - { - $this->storeHeader($header->getFieldName(), $header, $index); - } + /** + * Set a header in the HeaderSet. + * + * The header may be a previously fetched header via {@link get()} or it may + * be one that has been created separately. + * + * If $index is specified, the header will be inserted into the set at this + * offset. + * + * @param int $index + */ + public function set(Swift_Mime_Header $header, $index = 0) + { + $this->storeHeader($header->getFieldName(), $header, $index); + } - /** - * Get the header with the given $name. - * - * If multiple headers match, the actual one may be specified by $index. - * Returns NULL if none present. - * - * @param string $name - * @param int $index - * - * @return Swift_Mime_Header|null - */ - public function get($name, $index = 0) - { - $name = strtolower($name ?? ''); + /** + * Get the header with the given $name. + * + * If multiple headers match, the actual one may be specified by $index. + * Returns NULL if none present. + * + * @param string $name + * @param int $index + * + * @return Swift_Mime_Header|null + */ + public function get($name, $index = 0) + { + $name = strtolower($name ?? ''); - if (\func_num_args() < 2) { - if ($this->has($name)) { - $values = array_values($this->headers[$name]); + if (\func_num_args() < 2) { + if ($this->has($name)) { + $values = array_values($this->headers[$name]); - return array_shift($values); - } - } else { - if ($this->has($name, $index)) { - return $this->headers[$name][$index]; - } - } - } + return array_shift($values); + } + } else { + if ($this->has($name, $index)) { + return $this->headers[$name][$index]; + } + } + } - /** - * Get all headers with the given $name. - * - * @param string $name - * - * @return array - */ - public function getAll($name = null) - { - if (!isset($name)) { - $headers = []; - foreach ($this->headers as $collection) { - $headers = array_merge($headers, $collection); - } + /** + * Get all headers with the given $name. + * + * @param string $name + * + * @return array + */ + public function getAll($name = null) + { + if (!isset($name)) { + $headers = []; + foreach ($this->headers as $collection) { + $headers = array_merge($headers, $collection); + } - return $headers; - } + return $headers; + } - $lowerName = strtolower($name ?? ''); - if (!\array_key_exists($lowerName, $this->headers)) { - return []; - } + $lowerName = strtolower($name ?? ''); + if (!\array_key_exists($lowerName, $this->headers)) { + return []; + } - return $this->headers[$lowerName]; - } + return $this->headers[$lowerName]; + } - /** - * Return the name of all Headers. - * - * @return array - */ - public function listAll() - { - $headers = $this->headers; - if ($this->canSort()) { - uksort($headers, [$this, 'sortHeaders']); - } + /** + * Return the name of all Headers. + * + * @return array + */ + public function listAll() + { + $headers = $this->headers; + if ($this->canSort()) { + uksort($headers, [$this, 'sortHeaders']); + } - return array_keys($headers); - } + return array_keys($headers); + } - /** - * Remove the header with the given $name if it's set. - * - * If multiple headers match, the actual one may be specified by $index. - * - * @param string $name - * @param int $index - */ - public function remove($name, $index = 0) - { - $lowerName = strtolower($name ?? ''); - unset($this->headers[$lowerName][$index]); - } + /** + * Remove the header with the given $name if it's set. + * + * If multiple headers match, the actual one may be specified by $index. + * + * @param string $name + * @param int $index + */ + public function remove($name, $index = 0) + { + $lowerName = strtolower($name ?? ''); + unset($this->headers[$lowerName][$index]); + } - /** - * Remove all headers with the given $name. - * - * @param string $name - */ - public function removeAll($name) - { - $lowerName = strtolower($name ?? ''); - unset($this->headers[$lowerName]); - } + /** + * Remove all headers with the given $name. + * + * @param string $name + */ + public function removeAll($name) + { + $lowerName = strtolower($name ?? ''); + unset($this->headers[$lowerName]); + } - /** - * Define a list of Header names as an array in the correct order. - * - * These Headers will be output in the given order where present. - */ - public function defineOrdering(array $sequence) - { - $this->order = array_flip(array_map('strtolower', $sequence)); - } + /** + * Define a list of Header names as an array in the correct order. + * + * These Headers will be output in the given order where present. + */ + public function defineOrdering(array $sequence) + { + $this->order = array_flip(array_map('strtolower', $sequence)); + } - /** - * Set a list of header names which must always be displayed when set. - * - * Usually headers without a field value won't be output unless set here. - */ - public function setAlwaysDisplayed(array $names) - { - $this->required = array_flip(array_map('strtolower', $names)); - } + /** + * Set a list of header names which must always be displayed when set. + * + * Usually headers without a field value won't be output unless set here. + */ + public function setAlwaysDisplayed(array $names) + { + $this->required = array_flip(array_map('strtolower', $names)); + } - /** - * Notify this observer that the entity's charset has changed. - * - * @param string $charset - */ - public function charsetChanged($charset) - { - $this->setCharset($charset); - } + /** + * Notify this observer that the entity's charset has changed. + * + * @param string $charset + */ + public function charsetChanged($charset) + { + $this->setCharset($charset); + } - /** - * Returns a string with a representation of all headers. - * - * @return string - */ - public function toString() - { - $string = ''; - $headers = $this->headers; - if ($this->canSort()) { - uksort($headers, [$this, 'sortHeaders']); - } - foreach ($headers as $collection) { - foreach ($collection as $header) { - if ($this->isDisplayed($header) || '' != $header->getFieldBody()) { - $string .= $header->toString(); - } - } - } + /** + * Returns a string with a representation of all headers. + * + * @return string + */ + public function toString() + { + $string = ''; + $headers = $this->headers; + if ($this->canSort()) { + uksort($headers, [$this, 'sortHeaders']); + } + foreach ($headers as $collection) { + foreach ($collection as $header) { + if ($this->isDisplayed($header) || '' != $header->getFieldBody()) { + $string .= $header->toString(); + } + } + } - return $string; - } + return $string; + } - /** - * Returns a string representation of this object. - * - * @return string - * - * @see toString() - */ - public function __toString() - { - return $this->toString(); - } + /** + * Returns a string representation of this object. + * + * @return string + * + * @see toString() + */ + public function __toString() + { + return $this->toString(); + } - /** Save a Header to the internal collection */ - private function storeHeader($name, Swift_Mime_Header $header, $offset = null) - { - if (!isset($this->headers[strtolower($name ?? '')])) { - $this->headers[strtolower($name ?? '')] = []; - } - if (!isset($offset)) { - $this->headers[strtolower($name ?? '')][] = $header; - } else { - $this->headers[strtolower($name ?? '')][$offset] = $header; - } - } + /** Save a Header to the internal collection */ + private function storeHeader($name, Swift_Mime_Header $header, $offset = null) + { + if (!isset($this->headers[strtolower($name ?? '')])) { + $this->headers[strtolower($name ?? '')] = []; + } + if (!isset($offset)) { + $this->headers[strtolower($name ?? '')][] = $header; + } else { + $this->headers[strtolower($name ?? '')][$offset] = $header; + } + } - /** Test if the headers can be sorted */ - private function canSort() - { - return \count($this->order) > 0; - } + /** Test if the headers can be sorted */ + private function canSort() + { + return \count($this->order) > 0; + } - /** uksort() algorithm for Header ordering */ - private function sortHeaders($a, $b) - { - $lowerA = strtolower($a ?? ''); - $lowerB = strtolower($b ?? ''); - $aPos = \array_key_exists($lowerA, $this->order) ? $this->order[$lowerA] : -1; - $bPos = \array_key_exists($lowerB, $this->order) ? $this->order[$lowerB] : -1; + /** uksort() algorithm for Header ordering */ + private function sortHeaders($a, $b) + { + $lowerA = strtolower($a ?? ''); + $lowerB = strtolower($b ?? ''); + $aPos = \array_key_exists($lowerA, $this->order) ? $this->order[$lowerA] : -1; + $bPos = \array_key_exists($lowerB, $this->order) ? $this->order[$lowerB] : -1; - if (-1 === $aPos && -1 === $bPos) { - // just be sure to be determinist here - return $a > $b ? -1 : 1; - } + if (-1 === $aPos && -1 === $bPos) { + // just be sure to be determinist here + return $a > $b ? -1 : 1; + } - if (-1 == $aPos) { - return 1; - } elseif (-1 == $bPos) { - return -1; - } + if (-1 == $aPos) { + return 1; + } elseif (-1 == $bPos) { + return -1; + } - return $aPos < $bPos ? -1 : 1; - } + return $aPos < $bPos ? -1 : 1; + } - /** Test if the given Header is always displayed */ - private function isDisplayed(Swift_Mime_Header $header) - { - return \array_key_exists(strtolower($header->getFieldName() ?? ''), $this->required); - } + /** Test if the given Header is always displayed */ + private function isDisplayed(Swift_Mime_Header $header) + { + return \array_key_exists(strtolower($header->getFieldName() ?? ''), $this->required); + } - /** Notify all Headers of the new charset */ - private function notifyHeadersOfCharset($charset) - { - foreach ($this->headers as $headerGroup) { - foreach ($headerGroup as $header) { - $header->setCharset($charset); - } - } - } + /** Notify all Headers of the new charset */ + private function notifyHeadersOfCharset($charset) + { + foreach ($this->headers as $headerGroup) { + foreach ($headerGroup as $header) { + $header->setCharset($charset); + } + } + } - /** - * Make a deep copy of object. - */ - public function __clone() - { - $this->factory = clone $this->factory; - foreach ($this->headers as $groupKey => $headerGroup) { - foreach ($headerGroup as $key => $header) { - $this->headers[$groupKey][$key] = clone $header; - } - } - } + /** + * Make a deep copy of object. + */ + public function __clone() + { + $this->factory = clone $this->factory; + foreach ($this->headers as $groupKey => $headerGroup) { + foreach ($headerGroup as $key => $header) { + $this->headers[$groupKey][$key] = clone $header; + } + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleMessage.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleMessage.php index 1f87ce06452..62da1650a7b 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleMessage.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleMessage.php @@ -15,628 +15,628 @@ */ class Swift_Mime_SimpleMessage extends Swift_Mime_MimePart { - const PRIORITY_HIGHEST = 1; - const PRIORITY_HIGH = 2; - const PRIORITY_NORMAL = 3; - const PRIORITY_LOW = 4; - const PRIORITY_LOWEST = 5; - - /** - * Create a new SimpleMessage with $headers, $encoder and $cache. - * - * @param string $charset - */ - public function __construct(Swift_Mime_SimpleHeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_IdGenerator $idGenerator, $charset = null) - { - parent::__construct($headers, $encoder, $cache, $idGenerator, $charset); - $this->getHeaders()->defineOrdering([ - 'Return-Path', - 'Received', - 'DKIM-Signature', - 'DomainKey-Signature', - 'Sender', - 'Message-ID', - 'Date', - 'Subject', - 'From', - 'Reply-To', - 'To', - 'Cc', - 'Bcc', - 'MIME-Version', - 'Content-Type', - 'Content-Transfer-Encoding', - ]); - $this->getHeaders()->setAlwaysDisplayed(['Date', 'Message-ID', 'From']); - $this->getHeaders()->addTextHeader('MIME-Version', '1.0'); - $this->setDate(new DateTimeImmutable()); - $this->setId($this->getId()); - $this->getHeaders()->addMailboxHeader('From'); - } - - /** - * Always returns {@link LEVEL_TOP} for a message instance. - * - * @return int - */ - public function getNestingLevel() - { - return self::LEVEL_TOP; - } - - /** - * Set the subject of this message. - * - * @param string $subject - * - * @return $this - */ - public function setSubject($subject) - { - if (!$this->setHeaderFieldModel('Subject', $subject)) { - $this->getHeaders()->addTextHeader('Subject', $subject); - } - - return $this; - } - - /** - * Get the subject of this message. - * - * @return string - */ - public function getSubject() - { - return $this->getHeaderFieldModel('Subject'); - } - - /** - * Set the date at which this message was created. - * - * @return $this - */ - public function setDate(DateTimeInterface $dateTime) - { - if (!$this->setHeaderFieldModel('Date', $dateTime)) { - $this->getHeaders()->addDateHeader('Date', $dateTime); - } - - return $this; - } - - /** - * Get the date at which this message was created. - * - * @return DateTimeInterface - */ - public function getDate() - { - return $this->getHeaderFieldModel('Date'); - } - - /** - * Set the return-path (the bounce address) of this message. - * - * @param string $address - * - * @return $this - */ - public function setReturnPath($address) - { - if (!$this->setHeaderFieldModel('Return-Path', $address)) { - $this->getHeaders()->addPathHeader('Return-Path', $address); - } - - return $this; - } - - /** - * Get the return-path (bounce address) of this message. - * - * @return string - */ - public function getReturnPath() - { - return $this->getHeaderFieldModel('Return-Path'); - } - - /** - * Set the sender of this message. - * - * This does not override the From field, but it has a higher significance. - * - * @param string $address - * @param string $name optional - * - * @return $this - */ - public function setSender($address, $name = null) - { - if (!\is_array($address) && isset($name)) { - $address = [$address => $name]; - } - - if (!$this->setHeaderFieldModel('Sender', (array) $address)) { - $this->getHeaders()->addMailboxHeader('Sender', (array) $address); - } - - return $this; - } - - /** - * Get the sender of this message. - * - * @return string - */ - public function getSender() - { - return $this->getHeaderFieldModel('Sender'); - } - - /** - * Add a From: address to this message. - * - * If $name is passed this name will be associated with the address. - * - * @param string $address - * @param string $name optional - * - * @return $this - */ - public function addFrom($address, $name = null) - { - $current = $this->getFrom(); - $current[$address] = $name; - - return $this->setFrom($current); - } - - /** - * Set the from address of this message. - * - * You may pass an array of addresses if this message is from multiple people. - * - * If $name is passed and the first parameter is a string, this name will be - * associated with the address. - * - * @param string|array $addresses - * @param string $name optional - * - * @return $this - */ - public function setFrom($addresses, $name = null) - { - if (!\is_array($addresses) && isset($name)) { - $addresses = [$addresses => $name]; - } - - if (!$this->setHeaderFieldModel('From', (array) $addresses)) { - $this->getHeaders()->addMailboxHeader('From', (array) $addresses); - } - - return $this; - } - - /** - * Get the from address of this message. - * - * @return mixed - */ - public function getFrom() - { - return $this->getHeaderFieldModel('From'); - } - - /** - * Add a Reply-To: address to this message. - * - * If $name is passed this name will be associated with the address. - * - * @param string $address - * @param string $name optional - * - * @return $this - */ - public function addReplyTo($address, $name = null) - { - $current = $this->getReplyTo(); - $current[$address] = $name; - - return $this->setReplyTo($current); - } - - /** - * Set the reply-to address of this message. - * - * You may pass an array of addresses if replies will go to multiple people. - * - * If $name is passed and the first parameter is a string, this name will be - * associated with the address. - * - * @param mixed $addresses - * @param string $name optional - * - * @return $this - */ - public function setReplyTo($addresses, $name = null) - { - if (!\is_array($addresses) && isset($name)) { - $addresses = [$addresses => $name]; - } - - if (!$this->setHeaderFieldModel('Reply-To', (array) $addresses)) { - $this->getHeaders()->addMailboxHeader('Reply-To', (array) $addresses); - } - - return $this; - } - - /** - * Get the reply-to address of this message. - * - * @return string - */ - public function getReplyTo() - { - return $this->getHeaderFieldModel('Reply-To'); - } - - /** - * Add a To: address to this message. - * - * If $name is passed this name will be associated with the address. - * - * @param string $address - * @param string $name optional - * - * @return $this - */ - public function addTo($address, $name = null) - { - $current = $this->getTo(); - $current[$address] = $name; - - return $this->setTo($current); - } - - /** - * Set the to addresses of this message. - * - * If multiple recipients will receive the message an array should be used. - * Example: array('receiver@domain.org', 'other@domain.org' => 'A name') - * - * If $name is passed and the first parameter is a string, this name will be - * associated with the address. - * - * @param mixed $addresses - * @param string $name optional - * - * @return $this - */ - public function setTo($addresses, $name = null) - { - if (!\is_array($addresses) && isset($name)) { - $addresses = [$addresses => $name]; - } - - if (!$this->setHeaderFieldModel('To', (array) $addresses)) { - $this->getHeaders()->addMailboxHeader('To', (array) $addresses); - } - - return $this; - } - - /** - * Get the To addresses of this message. - * - * @return array - */ - public function getTo() - { - return $this->getHeaderFieldModel('To'); - } - - /** - * Add a Cc: address to this message. - * - * If $name is passed this name will be associated with the address. - * - * @param string $address - * @param string $name optional - * - * @return $this - */ - public function addCc($address, $name = null) - { - $current = $this->getCc(); - $current[$address] = $name; - - return $this->setCc($current); - } - - /** - * Set the Cc addresses of this message. - * - * If $name is passed and the first parameter is a string, this name will be - * associated with the address. - * - * @param mixed $addresses - * @param string $name optional - * - * @return $this - */ - public function setCc($addresses, $name = null) - { - if (!\is_array($addresses) && isset($name)) { - $addresses = [$addresses => $name]; - } - - if (!$this->setHeaderFieldModel('Cc', (array) $addresses)) { - $this->getHeaders()->addMailboxHeader('Cc', (array) $addresses); - } - - return $this; - } - - /** - * Get the Cc address of this message. - * - * @return array - */ - public function getCc() - { - return $this->getHeaderFieldModel('Cc'); - } - - /** - * Add a Bcc: address to this message. - * - * If $name is passed this name will be associated with the address. - * - * @param string $address - * @param string $name optional - * - * @return $this - */ - public function addBcc($address, $name = null) - { - $current = $this->getBcc(); - $current[$address] = $name; - - return $this->setBcc($current); - } - - /** - * Set the Bcc addresses of this message. - * - * If $name is passed and the first parameter is a string, this name will be - * associated with the address. - * - * @param mixed $addresses - * @param string $name optional - * - * @return $this - */ - public function setBcc($addresses, $name = null) - { - if (!\is_array($addresses) && isset($name)) { - $addresses = [$addresses => $name]; - } - - if (!$this->setHeaderFieldModel('Bcc', (array) $addresses)) { - $this->getHeaders()->addMailboxHeader('Bcc', (array) $addresses); - } - - return $this; - } - - /** - * Get the Bcc addresses of this message. - * - * @return array - */ - public function getBcc() - { - return $this->getHeaderFieldModel('Bcc'); - } - - /** - * Set the priority of this message. - * - * The value is an integer where 1 is the highest priority and 5 is the lowest. - * - * @param int $priority - * - * @return $this - */ - public function setPriority($priority) - { - $priorityMap = [ - self::PRIORITY_HIGHEST => 'Highest', - self::PRIORITY_HIGH => 'High', - self::PRIORITY_NORMAL => 'Normal', - self::PRIORITY_LOW => 'Low', - self::PRIORITY_LOWEST => 'Lowest', - ]; - $pMapKeys = array_keys($priorityMap); - if ($priority > max($pMapKeys)) { - $priority = max($pMapKeys); - } elseif ($priority < min($pMapKeys)) { - $priority = min($pMapKeys); - } - if (!$this->setHeaderFieldModel('X-Priority', - sprintf('%d (%s)', $priority, $priorityMap[$priority]))) { - $this->getHeaders()->addTextHeader('X-Priority', - sprintf('%d (%s)', $priority, $priorityMap[$priority])); - } - - return $this; - } - - /** - * Get the priority of this message. - * - * The returned value is an integer where 1 is the highest priority and 5 - * is the lowest. - * - * @return int - */ - public function getPriority() - { - list($priority) = sscanf($this->getHeaderFieldModel('X-Priority'), - '%[1-5]' - ); - - return $priority ?? 3; - } - - /** - * Ask for a delivery receipt from the recipient to be sent to $addresses. - * - * @param array $addresses - * - * @return $this - */ - public function setReadReceiptTo($addresses) - { - if (!$this->setHeaderFieldModel('Disposition-Notification-To', $addresses)) { - $this->getHeaders() - ->addMailboxHeader('Disposition-Notification-To', $addresses); - } - - return $this; - } - - /** - * Get the addresses to which a read-receipt will be sent. - * - * @return string - */ - public function getReadReceiptTo() - { - return $this->getHeaderFieldModel('Disposition-Notification-To'); - } - - /** - * Attach a {@link Swift_Mime_SimpleMimeEntity} such as an Attachment or MimePart. - * - * @return $this - */ - public function attach(Swift_Mime_SimpleMimeEntity $entity) - { - $this->setChildren(array_merge($this->getChildren(), [$entity])); - - return $this; - } - - /** - * Remove an already attached entity. - * - * @return $this - */ - public function detach(Swift_Mime_SimpleMimeEntity $entity) - { - $newChildren = []; - foreach ($this->getChildren() as $child) { - if ($entity !== $child) { - $newChildren[] = $child; - } - } - $this->setChildren($newChildren); - - return $this; - } - - /** - * Attach a {@link Swift_Mime_SimpleMimeEntity} and return it's CID source. - * - * This method should be used when embedding images or other data in a message. - * - * @return string - */ - public function embed(Swift_Mime_SimpleMimeEntity $entity) - { - $this->attach($entity); - - return 'cid:'.$entity->getId(); - } - - /** - * Get this message as a complete string. - * - * @return string - */ - public function toString() - { - if (\count($children = $this->getChildren()) > 0 && '' != $this->getBody()) { - $this->setChildren(array_merge([$this->becomeMimePart()], $children)); - $string = parent::toString(); - $this->setChildren($children); - } else { - $string = parent::toString(); - } - - return $string; - } - - /** - * Returns a string representation of this object. - * - * @see toString() - * - * @return string - */ - public function __toString() - { - return $this->toString(); - } - - /** - * Write this message to a {@link Swift_InputByteStream}. - */ - public function toByteStream(Swift_InputByteStream $is) - { - if (\count($children = $this->getChildren()) > 0 && '' != $this->getBody()) { - $this->setChildren(array_merge([$this->becomeMimePart()], $children)); - parent::toByteStream($is); - $this->setChildren($children); - } else { - parent::toByteStream($is); - } - } - - /** @see Swift_Mime_SimpleMimeEntity::getIdField() */ - protected function getIdField() - { - return 'Message-ID'; - } - - /** Turn the body of this message into a child of itself if needed */ - protected function becomeMimePart() - { - $part = new parent($this->getHeaders()->newInstance(), $this->getEncoder(), - $this->getCache(), $this->getIdGenerator(), $this->userCharset - ); - $part->setContentType($this->userContentType); - $part->setBody($this->getBody()); - $part->setFormat($this->userFormat); - $part->setDelSp($this->userDelSp); - $part->setNestingLevel($this->getTopNestingLevel()); - - return $part; - } - - /** Get the highest nesting level nested inside this message */ - private function getTopNestingLevel() - { - $highestLevel = $this->getNestingLevel(); - foreach ($this->getChildren() as $child) { - $childLevel = $child->getNestingLevel(); - if ($highestLevel < $childLevel) { - $highestLevel = $childLevel; - } - } - - return $highestLevel; - } + const PRIORITY_HIGHEST = 1; + const PRIORITY_HIGH = 2; + const PRIORITY_NORMAL = 3; + const PRIORITY_LOW = 4; + const PRIORITY_LOWEST = 5; + + /** + * Create a new SimpleMessage with $headers, $encoder and $cache. + * + * @param string $charset + */ + public function __construct(Swift_Mime_SimpleHeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_IdGenerator $idGenerator, $charset = null) + { + parent::__construct($headers, $encoder, $cache, $idGenerator, $charset); + $this->getHeaders()->defineOrdering([ + 'Return-Path', + 'Received', + 'DKIM-Signature', + 'DomainKey-Signature', + 'Sender', + 'Message-ID', + 'Date', + 'Subject', + 'From', + 'Reply-To', + 'To', + 'Cc', + 'Bcc', + 'MIME-Version', + 'Content-Type', + 'Content-Transfer-Encoding', + ]); + $this->getHeaders()->setAlwaysDisplayed(['Date', 'Message-ID', 'From']); + $this->getHeaders()->addTextHeader('MIME-Version', '1.0'); + $this->setDate(new DateTimeImmutable()); + $this->setId($this->getId()); + $this->getHeaders()->addMailboxHeader('From'); + } + + /** + * Always returns {@link LEVEL_TOP} for a message instance. + * + * @return int + */ + public function getNestingLevel() + { + return self::LEVEL_TOP; + } + + /** + * Set the subject of this message. + * + * @param string $subject + * + * @return $this + */ + public function setSubject($subject) + { + if (!$this->setHeaderFieldModel('Subject', $subject)) { + $this->getHeaders()->addTextHeader('Subject', $subject); + } + + return $this; + } + + /** + * Get the subject of this message. + * + * @return string + */ + public function getSubject() + { + return $this->getHeaderFieldModel('Subject'); + } + + /** + * Set the date at which this message was created. + * + * @return $this + */ + public function setDate(DateTimeInterface $dateTime) + { + if (!$this->setHeaderFieldModel('Date', $dateTime)) { + $this->getHeaders()->addDateHeader('Date', $dateTime); + } + + return $this; + } + + /** + * Get the date at which this message was created. + * + * @return DateTimeInterface + */ + public function getDate() + { + return $this->getHeaderFieldModel('Date'); + } + + /** + * Set the return-path (the bounce address) of this message. + * + * @param string $address + * + * @return $this + */ + public function setReturnPath($address) + { + if (!$this->setHeaderFieldModel('Return-Path', $address)) { + $this->getHeaders()->addPathHeader('Return-Path', $address); + } + + return $this; + } + + /** + * Get the return-path (bounce address) of this message. + * + * @return string + */ + public function getReturnPath() + { + return $this->getHeaderFieldModel('Return-Path'); + } + + /** + * Set the sender of this message. + * + * This does not override the From field, but it has a higher significance. + * + * @param string $address + * @param string $name optional + * + * @return $this + */ + public function setSender($address, $name = null) + { + if (!\is_array($address) && isset($name)) { + $address = [$address => $name]; + } + + if (!$this->setHeaderFieldModel('Sender', (array) $address)) { + $this->getHeaders()->addMailboxHeader('Sender', (array) $address); + } + + return $this; + } + + /** + * Get the sender of this message. + * + * @return string + */ + public function getSender() + { + return $this->getHeaderFieldModel('Sender'); + } + + /** + * Add a From: address to this message. + * + * If $name is passed this name will be associated with the address. + * + * @param string $address + * @param string $name optional + * + * @return $this + */ + public function addFrom($address, $name = null) + { + $current = $this->getFrom(); + $current[$address] = $name; + + return $this->setFrom($current); + } + + /** + * Set the from address of this message. + * + * You may pass an array of addresses if this message is from multiple people. + * + * If $name is passed and the first parameter is a string, this name will be + * associated with the address. + * + * @param string|array $addresses + * @param string $name optional + * + * @return $this + */ + public function setFrom($addresses, $name = null) + { + if (!\is_array($addresses) && isset($name)) { + $addresses = [$addresses => $name]; + } + + if (!$this->setHeaderFieldModel('From', (array) $addresses)) { + $this->getHeaders()->addMailboxHeader('From', (array) $addresses); + } + + return $this; + } + + /** + * Get the from address of this message. + * + * @return mixed + */ + public function getFrom() + { + return $this->getHeaderFieldModel('From'); + } + + /** + * Add a Reply-To: address to this message. + * + * If $name is passed this name will be associated with the address. + * + * @param string $address + * @param string $name optional + * + * @return $this + */ + public function addReplyTo($address, $name = null) + { + $current = $this->getReplyTo(); + $current[$address] = $name; + + return $this->setReplyTo($current); + } + + /** + * Set the reply-to address of this message. + * + * You may pass an array of addresses if replies will go to multiple people. + * + * If $name is passed and the first parameter is a string, this name will be + * associated with the address. + * + * @param mixed $addresses + * @param string $name optional + * + * @return $this + */ + public function setReplyTo($addresses, $name = null) + { + if (!\is_array($addresses) && isset($name)) { + $addresses = [$addresses => $name]; + } + + if (!$this->setHeaderFieldModel('Reply-To', (array) $addresses)) { + $this->getHeaders()->addMailboxHeader('Reply-To', (array) $addresses); + } + + return $this; + } + + /** + * Get the reply-to address of this message. + * + * @return string + */ + public function getReplyTo() + { + return $this->getHeaderFieldModel('Reply-To'); + } + + /** + * Add a To: address to this message. + * + * If $name is passed this name will be associated with the address. + * + * @param string $address + * @param string $name optional + * + * @return $this + */ + public function addTo($address, $name = null) + { + $current = $this->getTo(); + $current[$address] = $name; + + return $this->setTo($current); + } + + /** + * Set the to addresses of this message. + * + * If multiple recipients will receive the message an array should be used. + * Example: array('receiver@domain.org', 'other@domain.org' => 'A name') + * + * If $name is passed and the first parameter is a string, this name will be + * associated with the address. + * + * @param mixed $addresses + * @param string $name optional + * + * @return $this + */ + public function setTo($addresses, $name = null) + { + if (!\is_array($addresses) && isset($name)) { + $addresses = [$addresses => $name]; + } + + if (!$this->setHeaderFieldModel('To', (array) $addresses)) { + $this->getHeaders()->addMailboxHeader('To', (array) $addresses); + } + + return $this; + } + + /** + * Get the To addresses of this message. + * + * @return array + */ + public function getTo() + { + return $this->getHeaderFieldModel('To'); + } + + /** + * Add a Cc: address to this message. + * + * If $name is passed this name will be associated with the address. + * + * @param string $address + * @param string $name optional + * + * @return $this + */ + public function addCc($address, $name = null) + { + $current = $this->getCc(); + $current[$address] = $name; + + return $this->setCc($current); + } + + /** + * Set the Cc addresses of this message. + * + * If $name is passed and the first parameter is a string, this name will be + * associated with the address. + * + * @param mixed $addresses + * @param string $name optional + * + * @return $this + */ + public function setCc($addresses, $name = null) + { + if (!\is_array($addresses) && isset($name)) { + $addresses = [$addresses => $name]; + } + + if (!$this->setHeaderFieldModel('Cc', (array) $addresses)) { + $this->getHeaders()->addMailboxHeader('Cc', (array) $addresses); + } + + return $this; + } + + /** + * Get the Cc address of this message. + * + * @return array + */ + public function getCc() + { + return $this->getHeaderFieldModel('Cc'); + } + + /** + * Add a Bcc: address to this message. + * + * If $name is passed this name will be associated with the address. + * + * @param string $address + * @param string $name optional + * + * @return $this + */ + public function addBcc($address, $name = null) + { + $current = $this->getBcc(); + $current[$address] = $name; + + return $this->setBcc($current); + } + + /** + * Set the Bcc addresses of this message. + * + * If $name is passed and the first parameter is a string, this name will be + * associated with the address. + * + * @param mixed $addresses + * @param string $name optional + * + * @return $this + */ + public function setBcc($addresses, $name = null) + { + if (!\is_array($addresses) && isset($name)) { + $addresses = [$addresses => $name]; + } + + if (!$this->setHeaderFieldModel('Bcc', (array) $addresses)) { + $this->getHeaders()->addMailboxHeader('Bcc', (array) $addresses); + } + + return $this; + } + + /** + * Get the Bcc addresses of this message. + * + * @return array + */ + public function getBcc() + { + return $this->getHeaderFieldModel('Bcc'); + } + + /** + * Set the priority of this message. + * + * The value is an integer where 1 is the highest priority and 5 is the lowest. + * + * @param int $priority + * + * @return $this + */ + public function setPriority($priority) + { + $priorityMap = [ + self::PRIORITY_HIGHEST => 'Highest', + self::PRIORITY_HIGH => 'High', + self::PRIORITY_NORMAL => 'Normal', + self::PRIORITY_LOW => 'Low', + self::PRIORITY_LOWEST => 'Lowest', + ]; + $pMapKeys = array_keys($priorityMap); + if ($priority > max($pMapKeys)) { + $priority = max($pMapKeys); + } elseif ($priority < min($pMapKeys)) { + $priority = min($pMapKeys); + } + if (!$this->setHeaderFieldModel('X-Priority', + sprintf('%d (%s)', $priority, $priorityMap[$priority]))) { + $this->getHeaders()->addTextHeader('X-Priority', + sprintf('%d (%s)', $priority, $priorityMap[$priority])); + } + + return $this; + } + + /** + * Get the priority of this message. + * + * The returned value is an integer where 1 is the highest priority and 5 + * is the lowest. + * + * @return int + */ + public function getPriority() + { + list($priority) = sscanf($this->getHeaderFieldModel('X-Priority'), + '%[1-5]' + ); + + return $priority ?? 3; + } + + /** + * Ask for a delivery receipt from the recipient to be sent to $addresses. + * + * @param array $addresses + * + * @return $this + */ + public function setReadReceiptTo($addresses) + { + if (!$this->setHeaderFieldModel('Disposition-Notification-To', $addresses)) { + $this->getHeaders() + ->addMailboxHeader('Disposition-Notification-To', $addresses); + } + + return $this; + } + + /** + * Get the addresses to which a read-receipt will be sent. + * + * @return string + */ + public function getReadReceiptTo() + { + return $this->getHeaderFieldModel('Disposition-Notification-To'); + } + + /** + * Attach a {@link Swift_Mime_SimpleMimeEntity} such as an Attachment or MimePart. + * + * @return $this + */ + public function attach(Swift_Mime_SimpleMimeEntity $entity) + { + $this->setChildren(array_merge($this->getChildren(), [$entity])); + + return $this; + } + + /** + * Remove an already attached entity. + * + * @return $this + */ + public function detach(Swift_Mime_SimpleMimeEntity $entity) + { + $newChildren = []; + foreach ($this->getChildren() as $child) { + if ($entity !== $child) { + $newChildren[] = $child; + } + } + $this->setChildren($newChildren); + + return $this; + } + + /** + * Attach a {@link Swift_Mime_SimpleMimeEntity} and return it's CID source. + * + * This method should be used when embedding images or other data in a message. + * + * @return string + */ + public function embed(Swift_Mime_SimpleMimeEntity $entity) + { + $this->attach($entity); + + return 'cid:'.$entity->getId(); + } + + /** + * Get this message as a complete string. + * + * @return string + */ + public function toString() + { + if (\count($children = $this->getChildren()) > 0 && '' != $this->getBody()) { + $this->setChildren(array_merge([$this->becomeMimePart()], $children)); + $string = parent::toString(); + $this->setChildren($children); + } else { + $string = parent::toString(); + } + + return $string; + } + + /** + * Returns a string representation of this object. + * + * @see toString() + * + * @return string + */ + public function __toString() + { + return $this->toString(); + } + + /** + * Write this message to a {@link Swift_InputByteStream}. + */ + public function toByteStream(Swift_InputByteStream $is) + { + if (\count($children = $this->getChildren()) > 0 && '' != $this->getBody()) { + $this->setChildren(array_merge([$this->becomeMimePart()], $children)); + parent::toByteStream($is); + $this->setChildren($children); + } else { + parent::toByteStream($is); + } + } + + /** @see Swift_Mime_SimpleMimeEntity::getIdField() */ + protected function getIdField() + { + return 'Message-ID'; + } + + /** Turn the body of this message into a child of itself if needed */ + protected function becomeMimePart() + { + $part = new parent($this->getHeaders()->newInstance(), $this->getEncoder(), + $this->getCache(), $this->getIdGenerator(), $this->userCharset + ); + $part->setContentType($this->userContentType); + $part->setBody($this->getBody()); + $part->setFormat($this->userFormat); + $part->setDelSp($this->userDelSp); + $part->setNestingLevel($this->getTopNestingLevel()); + + return $part; + } + + /** Get the highest nesting level nested inside this message */ + private function getTopNestingLevel() + { + $highestLevel = $this->getNestingLevel(); + foreach ($this->getChildren() as $child) { + $childLevel = $child->getNestingLevel(); + if ($highestLevel < $childLevel) { + $highestLevel = $childLevel; + } + } + + return $highestLevel; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleMimeEntity.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleMimeEntity.php index 668d076fb32..03eaf472dd5 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleMimeEntity.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Mime/SimpleMimeEntity.php @@ -15,812 +15,812 @@ */ class Swift_Mime_SimpleMimeEntity implements Swift_Mime_CharsetObserver, Swift_Mime_EncodingObserver { - /** Main message document; there can only be one of these */ - const LEVEL_TOP = 16; - - /** An entity which nests with the same precedence as an attachment */ - const LEVEL_MIXED = 256; - - /** An entity which nests with the same precedence as a mime part */ - const LEVEL_ALTERNATIVE = 4096; - - /** An entity which nests with the same precedence as embedded content */ - const LEVEL_RELATED = 65536; - - /** A collection of Headers for this mime entity */ - private $headers; - - /** The body as a string, or a stream */ - private $body; - - /** The encoder that encodes the body into a streamable format */ - private $encoder; - - /** Message ID generator */ - private $idGenerator; - - /** A mime boundary, if any is used */ - private $boundary; - - /** Mime types to be used based on the nesting level */ - private $compositeRanges = [ - 'multipart/mixed' => [self::LEVEL_TOP, self::LEVEL_MIXED], - 'multipart/alternative' => [self::LEVEL_MIXED, self::LEVEL_ALTERNATIVE], - 'multipart/related' => [self::LEVEL_ALTERNATIVE, self::LEVEL_RELATED], - ]; - - /** A set of filter rules to define what level an entity should be nested at */ - private $compoundLevelFilters = []; - - /** The nesting level of this entity */ - private $nestingLevel = self::LEVEL_ALTERNATIVE; - - /** A KeyCache instance used during encoding and streaming */ - private $cache; - - /** Direct descendants of this entity */ - private $immediateChildren = []; - - /** All descendants of this entity */ - private $children = []; - - /** The maximum line length of the body of this entity */ - private $maxLineLength = 78; - - /** The order in which alternative mime types should appear */ - private $alternativePartOrder = [ - 'text/plain' => 1, - 'text/html' => 2, - 'multipart/related' => 3, - ]; - - /** The CID of this entity */ - private $id; - - /** The key used for accessing the cache */ - private $cacheKey; - - protected $userContentType; - - /** - * Create a new SimpleMimeEntity with $headers, $encoder and $cache. - */ - public function __construct(Swift_Mime_SimpleHeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_IdGenerator $idGenerator) - { - $this->cacheKey = bin2hex(random_bytes(16)); // set 32 hex values - $this->cache = $cache; - $this->headers = $headers; - $this->idGenerator = $idGenerator; - $this->setEncoder($encoder); - $this->headers->defineOrdering(['Content-Type', 'Content-Transfer-Encoding']); - - // This array specifies that, when the entire MIME document contains - // $compoundLevel, then for each child within $level, if its Content-Type - // is $contentType then it should be treated as if it's level is - // $neededLevel instead. I tried to write that unambiguously! :-\ - // Data Structure: - // array ( - // $compoundLevel => array( - // $level => array( - // $contentType => $neededLevel - // ) - // ) - // ) - - $this->compoundLevelFilters = [ - (self::LEVEL_ALTERNATIVE + self::LEVEL_RELATED) => [ - self::LEVEL_ALTERNATIVE => [ - 'text/plain' => self::LEVEL_ALTERNATIVE, - 'text/html' => self::LEVEL_RELATED, - ], - ], - ]; - - $this->id = $this->idGenerator->generateId(); - } - - /** - * Generate a new Content-ID or Message-ID for this MIME entity. - * - * @return string - */ - public function generateId() - { - $this->setId($this->idGenerator->generateId()); - - return $this->id; - } - - /** - * Get the {@link Swift_Mime_SimpleHeaderSet} for this entity. - * - * @return Swift_Mime_SimpleHeaderSet - */ - public function getHeaders() - { - return $this->headers; - } - - /** - * Get the nesting level of this entity. - * - * @see LEVEL_TOP, LEVEL_MIXED, LEVEL_RELATED, LEVEL_ALTERNATIVE - * - * @return int - */ - public function getNestingLevel() - { - return $this->nestingLevel; - } - - /** - * Get the Content-type of this entity. - * - * @return string - */ - public function getContentType() - { - return $this->getHeaderFieldModel('Content-Type'); - } - - /** - * Get the Body Content-type of this entity. - * - * @return string - */ - public function getBodyContentType() - { - return $this->userContentType; - } - - /** - * Set the Content-type of this entity. - * - * @param string $type - * - * @return $this - */ - public function setContentType($type) - { - $this->setContentTypeInHeaders($type); - // Keep track of the value so that if the content-type changes automatically - // due to added child entities, it can be restored if they are later removed - $this->userContentType = $type; - - return $this; - } - - /** - * Get the CID of this entity. - * - * The CID will only be present in headers if a Content-ID header is present. - * - * @return string - */ - public function getId() - { - $tmp = (array) $this->getHeaderFieldModel($this->getIdField()); - - return $this->headers->has($this->getIdField()) ? current($tmp) : $this->id; - } - - /** - * Set the CID of this entity. - * - * @param string $id - * - * @return $this - */ - public function setId($id) - { - if (!$this->setHeaderFieldModel($this->getIdField(), $id)) { - $this->headers->addIdHeader($this->getIdField(), $id); - } - $this->id = $id; - - return $this; - } - - /** - * Get the description of this entity. - * - * This value comes from the Content-Description header if set. - * - * @return string - */ - public function getDescription() - { - return $this->getHeaderFieldModel('Content-Description'); - } - - /** - * Set the description of this entity. - * - * This method sets a value in the Content-ID header. - * - * @param string $description - * - * @return $this - */ - public function setDescription($description) - { - if (!$this->setHeaderFieldModel('Content-Description', $description)) { - $this->headers->addTextHeader('Content-Description', $description); - } - - return $this; - } - - /** - * Get the maximum line length of the body of this entity. - * - * @return int - */ - public function getMaxLineLength() - { - return $this->maxLineLength; - } - - /** - * Set the maximum line length of lines in this body. - * - * Though not enforced by the library, lines should not exceed 1000 chars. - * - * @param int $length - * - * @return $this - */ - public function setMaxLineLength($length) - { - $this->maxLineLength = $length; - - return $this; - } - - /** - * Get all children added to this entity. - * - * @return Swift_Mime_SimpleMimeEntity[] - */ - public function getChildren() - { - return $this->children; - } - - /** - * Set all children of this entity. - * - * @param Swift_Mime_SimpleMimeEntity[] $children - * @param int $compoundLevel For internal use only - * - * @return $this - */ - public function setChildren(array $children, $compoundLevel = null) - { - // TODO: Try to refactor this logic - $compoundLevel = $compoundLevel ?? $this->getCompoundLevel($children); - $immediateChildren = []; - $grandchildren = []; - $newContentType = $this->userContentType; - - foreach ($children as $child) { - $level = $this->getNeededChildLevel($child, $compoundLevel); - if (empty($immediateChildren)) { - //first iteration - $immediateChildren = [$child]; - } else { - $nextLevel = $this->getNeededChildLevel($immediateChildren[0], $compoundLevel); - if ($nextLevel == $level) { - $immediateChildren[] = $child; - } elseif ($level < $nextLevel) { - // Re-assign immediateChildren to grandchildren - $grandchildren = array_merge($grandchildren, $immediateChildren); - // Set new children - $immediateChildren = [$child]; - } else { - $grandchildren[] = $child; - } - } - } - - if ($immediateChildren) { - $lowestLevel = $this->getNeededChildLevel($immediateChildren[0], $compoundLevel); - - // Determine which composite media type is needed to accommodate the - // immediate children - foreach ($this->compositeRanges as $mediaType => $range) { - if ($lowestLevel > $range[0] && $lowestLevel <= $range[1]) { - $newContentType = $mediaType; - - break; - } - } - - // Put any grandchildren in a subpart - if (!empty($grandchildren)) { - $subentity = $this->createChild(); - $subentity->setNestingLevel($lowestLevel); - $subentity->setChildren($grandchildren, $compoundLevel); - array_unshift($immediateChildren, $subentity); - } - } - - $this->immediateChildren = $immediateChildren; - $this->children = $children; - $this->setContentTypeInHeaders($newContentType); - $this->fixHeaders(); - $this->sortChildren(); - - return $this; - } - - /** - * Get the body of this entity as a string. - * - * @return string - */ - public function getBody() - { - return $this->body instanceof Swift_OutputByteStream ? $this->readStream($this->body) : $this->body; - } - - /** - * Set the body of this entity, either as a string, or as an instance of - * {@link Swift_OutputByteStream}. - * - * @param mixed $body - * @param string $contentType optional - * - * @return $this - */ - public function setBody($body, $contentType = null) - { - if ($body !== $this->body) { - $this->clearCache(); - } - - $this->body = $body; - if (null !== $contentType) { - $this->setContentType($contentType); - } - - return $this; - } - - /** - * Get the encoder used for the body of this entity. - * - * @return Swift_Mime_ContentEncoder - */ - public function getEncoder() - { - return $this->encoder; - } - - /** - * Set the encoder used for the body of this entity. - * - * @return $this - */ - public function setEncoder(Swift_Mime_ContentEncoder $encoder) - { - if ($encoder !== $this->encoder) { - $this->clearCache(); - } - - $this->encoder = $encoder; - $this->setEncoding($encoder->getName()); - $this->notifyEncoderChanged($encoder); - - return $this; - } - - /** - * Get the boundary used to separate children in this entity. - * - * @return string - */ - public function getBoundary() - { - if (!isset($this->boundary)) { - $this->boundary = '_=_swift_'.time().'_'.bin2hex(random_bytes(16)).'_=_'; - } - - return $this->boundary; - } - - /** - * Set the boundary used to separate children in this entity. - * - * @param string $boundary - * - * @throws Swift_RfcComplianceException - * - * @return $this - */ - public function setBoundary($boundary) - { - $this->assertValidBoundary($boundary); - $this->boundary = $boundary; - - return $this; - } - - /** - * Receive notification that the charset of this entity, or a parent entity - * has changed. - * - * @param string $charset - */ - public function charsetChanged($charset) - { - $this->notifyCharsetChanged($charset); - } - - /** - * Receive notification that the encoder of this entity or a parent entity - * has changed. - */ - public function encoderChanged(Swift_Mime_ContentEncoder $encoder) - { - $this->notifyEncoderChanged($encoder); - } - - /** - * Get this entire entity as a string. - * - * @return string - */ - public function toString() - { - $string = $this->headers->toString(); - $string .= $this->bodyToString(); - - return $string; - } - - /** - * Get this entire entity as a string. - * - * @return string - */ - protected function bodyToString() - { - $string = ''; - - if (isset($this->body) && empty($this->immediateChildren)) { - if ($this->cache->hasKey($this->cacheKey, 'body')) { - $body = $this->cache->getString($this->cacheKey, 'body'); - } else { - $body = "\r\n".$this->encoder->encodeString($this->getBody(), 0, $this->getMaxLineLength()); - $this->cache->setString($this->cacheKey, 'body', $body, Swift_KeyCache::MODE_WRITE); - } - $string .= $body; - } - - if (!empty($this->immediateChildren)) { - foreach ($this->immediateChildren as $child) { - $string .= "\r\n\r\n--".$this->getBoundary()."\r\n"; - $string .= $child->toString(); - } - $string .= "\r\n\r\n--".$this->getBoundary()."--\r\n"; - } - - return $string; - } - - /** - * Returns a string representation of this object. - * - * @see toString() - * - * @return string - */ - public function __toString() - { - return $this->toString(); - } - - /** - * Write this entire entity to a {@see Swift_InputByteStream}. - */ - public function toByteStream(Swift_InputByteStream $is) - { - $is->write($this->headers->toString()); - $is->commit(); - - $this->bodyToByteStream($is); - } - - /** - * Write this entire entity to a {@link Swift_InputByteStream}. - */ - protected function bodyToByteStream(Swift_InputByteStream $is) - { - if (empty($this->immediateChildren)) { - if (isset($this->body)) { - if ($this->cache->hasKey($this->cacheKey, 'body')) { - $this->cache->exportToByteStream($this->cacheKey, 'body', $is); - } else { - $cacheIs = $this->cache->getInputByteStream($this->cacheKey, 'body'); - if ($cacheIs) { - $is->bind($cacheIs); - } - - $is->write("\r\n"); - - if ($this->body instanceof Swift_OutputByteStream) { - $this->body->setReadPointer(0); - - $this->encoder->encodeByteStream($this->body, $is, 0, $this->getMaxLineLength()); - } else { - $is->write($this->encoder->encodeString($this->getBody(), 0, $this->getMaxLineLength())); - } - - if ($cacheIs) { - $is->unbind($cacheIs); - } - } - } - } - - if (!empty($this->immediateChildren)) { - foreach ($this->immediateChildren as $child) { - $is->write("\r\n\r\n--".$this->getBoundary()."\r\n"); - $child->toByteStream($is); - } - $is->write("\r\n\r\n--".$this->getBoundary()."--\r\n"); - } - } - - /** - * Get the name of the header that provides the ID of this entity. - */ - protected function getIdField() - { - return 'Content-ID'; - } - - /** - * Get the model data (usually an array or a string) for $field. - */ - protected function getHeaderFieldModel($field) - { - if ($this->headers->has($field)) { - return $this->headers->get($field)->getFieldBodyModel(); - } - } - - /** - * Set the model data for $field. - */ - protected function setHeaderFieldModel($field, $model) - { - if ($this->headers->has($field)) { - $this->headers->get($field)->setFieldBodyModel($model); - - return true; - } - - return false; - } - - /** - * Get the parameter value of $parameter on $field header. - */ - protected function getHeaderParameter($field, $parameter) - { - if ($this->headers->has($field)) { - return $this->headers->get($field)->getParameter($parameter); - } - } - - /** - * Set the parameter value of $parameter on $field header. - */ - protected function setHeaderParameter($field, $parameter, $value) - { - if ($this->headers->has($field)) { - $this->headers->get($field)->setParameter($parameter, $value); - - return true; - } - - return false; - } - - /** - * Re-evaluate what content type and encoding should be used on this entity. - */ - protected function fixHeaders() - { - if (\count($this->immediateChildren)) { - $this->setHeaderParameter('Content-Type', 'boundary', - $this->getBoundary() - ); - $this->headers->remove('Content-Transfer-Encoding'); - } else { - $this->setHeaderParameter('Content-Type', 'boundary', null); - $this->setEncoding($this->encoder->getName()); - } - } - - /** - * Get the KeyCache used in this entity. - * - * @return Swift_KeyCache - */ - protected function getCache() - { - return $this->cache; - } - - /** - * Get the ID generator. - * - * @return Swift_IdGenerator - */ - protected function getIdGenerator() - { - return $this->idGenerator; - } - - /** - * Empty the KeyCache for this entity. - */ - protected function clearCache() - { - $this->cache->clearKey($this->cacheKey, 'body'); - } - - private function readStream(Swift_OutputByteStream $os) - { - $string = ''; - while (false !== $bytes = $os->read(8192)) { - $string .= $bytes; - } - - $os->setReadPointer(0); - - return $string; - } - - private function setEncoding($encoding) - { - if (!$this->setHeaderFieldModel('Content-Transfer-Encoding', $encoding)) { - $this->headers->addTextHeader('Content-Transfer-Encoding', $encoding); - } - } - - private function assertValidBoundary($boundary) - { - if (!preg_match('/^[a-z0-9\'\(\)\+_\-,\.\/:=\?\ ]{0,69}[a-z0-9\'\(\)\+_\-,\.\/:=\?]$/Di', $boundary)) { - throw new Swift_RfcComplianceException('Mime boundary set is not RFC 2046 compliant.'); - } - } - - private function setContentTypeInHeaders($type) - { - if (!$this->setHeaderFieldModel('Content-Type', $type)) { - $this->headers->addParameterizedHeader('Content-Type', $type); - } - } - - private function setNestingLevel($level) - { - $this->nestingLevel = $level; - } - - private function getCompoundLevel($children) - { - $level = 0; - foreach ($children as $child) { - $level |= $child->getNestingLevel(); - } - - return $level; - } - - private function getNeededChildLevel($child, $compoundLevel) - { - $filter = []; - foreach ($this->compoundLevelFilters as $bitmask => $rules) { - if (($compoundLevel & $bitmask) === $bitmask) { - $filter = $rules + $filter; - } - } - - $realLevel = $child->getNestingLevel(); - $lowercaseType = strtolower($child->getContentType() ?? ''); - - if (isset($filter[$realLevel]) && isset($filter[$realLevel][$lowercaseType])) { - return $filter[$realLevel][$lowercaseType]; - } - - return $realLevel; - } - - private function createChild() - { - return new self($this->headers->newInstance(), $this->encoder, $this->cache, $this->idGenerator); - } - - private function notifyEncoderChanged(Swift_Mime_ContentEncoder $encoder) - { - foreach ($this->immediateChildren as $child) { - $child->encoderChanged($encoder); - } - } - - private function notifyCharsetChanged($charset) - { - $this->encoder->charsetChanged($charset); - $this->headers->charsetChanged($charset); - foreach ($this->immediateChildren as $child) { - $child->charsetChanged($charset); - } - } - - private function sortChildren() - { - $shouldSort = false; - foreach ($this->immediateChildren as $child) { - // NOTE: This include alternative parts moved into a related part - if (self::LEVEL_ALTERNATIVE == $child->getNestingLevel()) { - $shouldSort = true; - break; - } - } - - // Sort in order of preference, if there is one - if ($shouldSort) { - // Group the messages by order of preference - $sorted = []; - foreach ($this->immediateChildren as $child) { - $type = $child->getContentType(); - $level = \array_key_exists($type, $this->alternativePartOrder) ? $this->alternativePartOrder[$type] : max($this->alternativePartOrder) + 1; - - if (empty($sorted[$level])) { - $sorted[$level] = []; - } - - $sorted[$level][] = $child; - } - - ksort($sorted); - - $this->immediateChildren = array_reduce($sorted, 'array_merge', []); - } - } - - /** - * Empties it's own contents from the cache. - */ - public function __destruct() - { - if ($this->cache instanceof Swift_KeyCache) { - $this->cache->clearAll($this->cacheKey); - } - } - - /** - * Make a deep copy of object. - */ - public function __clone() - { - $this->headers = clone $this->headers; - $this->encoder = clone $this->encoder; - $this->cacheKey = bin2hex(random_bytes(16)); // set 32 hex values - $children = []; - foreach ($this->children as $pos => $child) { - $children[$pos] = clone $child; - } - $this->setChildren($children); - } - - public function __wakeup() - { - $this->cacheKey = bin2hex(random_bytes(16)); // set 32 hex values - $this->cache = new Swift_KeyCache_ArrayKeyCache(new Swift_KeyCache_SimpleKeyCacheInputStream()); - } + /** Main message document; there can only be one of these */ + const LEVEL_TOP = 16; + + /** An entity which nests with the same precedence as an attachment */ + const LEVEL_MIXED = 256; + + /** An entity which nests with the same precedence as a mime part */ + const LEVEL_ALTERNATIVE = 4096; + + /** An entity which nests with the same precedence as embedded content */ + const LEVEL_RELATED = 65536; + + /** A collection of Headers for this mime entity */ + private $headers; + + /** The body as a string, or a stream */ + private $body; + + /** The encoder that encodes the body into a streamable format */ + private $encoder; + + /** Message ID generator */ + private $idGenerator; + + /** A mime boundary, if any is used */ + private $boundary; + + /** Mime types to be used based on the nesting level */ + private $compositeRanges = [ + 'multipart/mixed' => [self::LEVEL_TOP, self::LEVEL_MIXED], + 'multipart/alternative' => [self::LEVEL_MIXED, self::LEVEL_ALTERNATIVE], + 'multipart/related' => [self::LEVEL_ALTERNATIVE, self::LEVEL_RELATED], + ]; + + /** A set of filter rules to define what level an entity should be nested at */ + private $compoundLevelFilters = []; + + /** The nesting level of this entity */ + private $nestingLevel = self::LEVEL_ALTERNATIVE; + + /** A KeyCache instance used during encoding and streaming */ + private $cache; + + /** Direct descendants of this entity */ + private $immediateChildren = []; + + /** All descendants of this entity */ + private $children = []; + + /** The maximum line length of the body of this entity */ + private $maxLineLength = 78; + + /** The order in which alternative mime types should appear */ + private $alternativePartOrder = [ + 'text/plain' => 1, + 'text/html' => 2, + 'multipart/related' => 3, + ]; + + /** The CID of this entity */ + private $id; + + /** The key used for accessing the cache */ + private $cacheKey; + + protected $userContentType; + + /** + * Create a new SimpleMimeEntity with $headers, $encoder and $cache. + */ + public function __construct(Swift_Mime_SimpleHeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_IdGenerator $idGenerator) + { + $this->cacheKey = bin2hex(random_bytes(16)); // set 32 hex values + $this->cache = $cache; + $this->headers = $headers; + $this->idGenerator = $idGenerator; + $this->setEncoder($encoder); + $this->headers->defineOrdering(['Content-Type', 'Content-Transfer-Encoding']); + + // This array specifies that, when the entire MIME document contains + // $compoundLevel, then for each child within $level, if its Content-Type + // is $contentType then it should be treated as if it's level is + // $neededLevel instead. I tried to write that unambiguously! :-\ + // Data Structure: + // array ( + // $compoundLevel => array( + // $level => array( + // $contentType => $neededLevel + // ) + // ) + // ) + + $this->compoundLevelFilters = [ + (self::LEVEL_ALTERNATIVE + self::LEVEL_RELATED) => [ + self::LEVEL_ALTERNATIVE => [ + 'text/plain' => self::LEVEL_ALTERNATIVE, + 'text/html' => self::LEVEL_RELATED, + ], + ], + ]; + + $this->id = $this->idGenerator->generateId(); + } + + /** + * Generate a new Content-ID or Message-ID for this MIME entity. + * + * @return string + */ + public function generateId() + { + $this->setId($this->idGenerator->generateId()); + + return $this->id; + } + + /** + * Get the {@link Swift_Mime_SimpleHeaderSet} for this entity. + * + * @return Swift_Mime_SimpleHeaderSet + */ + public function getHeaders() + { + return $this->headers; + } + + /** + * Get the nesting level of this entity. + * + * @see LEVEL_TOP, LEVEL_MIXED, LEVEL_RELATED, LEVEL_ALTERNATIVE + * + * @return int + */ + public function getNestingLevel() + { + return $this->nestingLevel; + } + + /** + * Get the Content-type of this entity. + * + * @return string + */ + public function getContentType() + { + return $this->getHeaderFieldModel('Content-Type'); + } + + /** + * Get the Body Content-type of this entity. + * + * @return string + */ + public function getBodyContentType() + { + return $this->userContentType; + } + + /** + * Set the Content-type of this entity. + * + * @param string $type + * + * @return $this + */ + public function setContentType($type) + { + $this->setContentTypeInHeaders($type); + // Keep track of the value so that if the content-type changes automatically + // due to added child entities, it can be restored if they are later removed + $this->userContentType = $type; + + return $this; + } + + /** + * Get the CID of this entity. + * + * The CID will only be present in headers if a Content-ID header is present. + * + * @return string + */ + public function getId() + { + $tmp = (array) $this->getHeaderFieldModel($this->getIdField()); + + return $this->headers->has($this->getIdField()) ? current($tmp) : $this->id; + } + + /** + * Set the CID of this entity. + * + * @param string $id + * + * @return $this + */ + public function setId($id) + { + if (!$this->setHeaderFieldModel($this->getIdField(), $id)) { + $this->headers->addIdHeader($this->getIdField(), $id); + } + $this->id = $id; + + return $this; + } + + /** + * Get the description of this entity. + * + * This value comes from the Content-Description header if set. + * + * @return string + */ + public function getDescription() + { + return $this->getHeaderFieldModel('Content-Description'); + } + + /** + * Set the description of this entity. + * + * This method sets a value in the Content-ID header. + * + * @param string $description + * + * @return $this + */ + public function setDescription($description) + { + if (!$this->setHeaderFieldModel('Content-Description', $description)) { + $this->headers->addTextHeader('Content-Description', $description); + } + + return $this; + } + + /** + * Get the maximum line length of the body of this entity. + * + * @return int + */ + public function getMaxLineLength() + { + return $this->maxLineLength; + } + + /** + * Set the maximum line length of lines in this body. + * + * Though not enforced by the library, lines should not exceed 1000 chars. + * + * @param int $length + * + * @return $this + */ + public function setMaxLineLength($length) + { + $this->maxLineLength = $length; + + return $this; + } + + /** + * Get all children added to this entity. + * + * @return Swift_Mime_SimpleMimeEntity[] + */ + public function getChildren() + { + return $this->children; + } + + /** + * Set all children of this entity. + * + * @param Swift_Mime_SimpleMimeEntity[] $children + * @param int $compoundLevel For internal use only + * + * @return $this + */ + public function setChildren(array $children, $compoundLevel = null) + { + // TODO: Try to refactor this logic + $compoundLevel = $compoundLevel ?? $this->getCompoundLevel($children); + $immediateChildren = []; + $grandchildren = []; + $newContentType = $this->userContentType; + + foreach ($children as $child) { + $level = $this->getNeededChildLevel($child, $compoundLevel); + if (empty($immediateChildren)) { + //first iteration + $immediateChildren = [$child]; + } else { + $nextLevel = $this->getNeededChildLevel($immediateChildren[0], $compoundLevel); + if ($nextLevel == $level) { + $immediateChildren[] = $child; + } elseif ($level < $nextLevel) { + // Re-assign immediateChildren to grandchildren + $grandchildren = array_merge($grandchildren, $immediateChildren); + // Set new children + $immediateChildren = [$child]; + } else { + $grandchildren[] = $child; + } + } + } + + if ($immediateChildren) { + $lowestLevel = $this->getNeededChildLevel($immediateChildren[0], $compoundLevel); + + // Determine which composite media type is needed to accommodate the + // immediate children + foreach ($this->compositeRanges as $mediaType => $range) { + if ($lowestLevel > $range[0] && $lowestLevel <= $range[1]) { + $newContentType = $mediaType; + + break; + } + } + + // Put any grandchildren in a subpart + if (!empty($grandchildren)) { + $subentity = $this->createChild(); + $subentity->setNestingLevel($lowestLevel); + $subentity->setChildren($grandchildren, $compoundLevel); + array_unshift($immediateChildren, $subentity); + } + } + + $this->immediateChildren = $immediateChildren; + $this->children = $children; + $this->setContentTypeInHeaders($newContentType); + $this->fixHeaders(); + $this->sortChildren(); + + return $this; + } + + /** + * Get the body of this entity as a string. + * + * @return string + */ + public function getBody() + { + return $this->body instanceof Swift_OutputByteStream ? $this->readStream($this->body) : $this->body; + } + + /** + * Set the body of this entity, either as a string, or as an instance of + * {@link Swift_OutputByteStream}. + * + * @param mixed $body + * @param string $contentType optional + * + * @return $this + */ + public function setBody($body, $contentType = null) + { + if ($body !== $this->body) { + $this->clearCache(); + } + + $this->body = $body; + if (null !== $contentType) { + $this->setContentType($contentType); + } + + return $this; + } + + /** + * Get the encoder used for the body of this entity. + * + * @return Swift_Mime_ContentEncoder + */ + public function getEncoder() + { + return $this->encoder; + } + + /** + * Set the encoder used for the body of this entity. + * + * @return $this + */ + public function setEncoder(Swift_Mime_ContentEncoder $encoder) + { + if ($encoder !== $this->encoder) { + $this->clearCache(); + } + + $this->encoder = $encoder; + $this->setEncoding($encoder->getName()); + $this->notifyEncoderChanged($encoder); + + return $this; + } + + /** + * Get the boundary used to separate children in this entity. + * + * @return string + */ + public function getBoundary() + { + if (!isset($this->boundary)) { + $this->boundary = '_=_swift_'.time().'_'.bin2hex(random_bytes(16)).'_=_'; + } + + return $this->boundary; + } + + /** + * Set the boundary used to separate children in this entity. + * + * @param string $boundary + * + * @throws Swift_RfcComplianceException + * + * @return $this + */ + public function setBoundary($boundary) + { + $this->assertValidBoundary($boundary); + $this->boundary = $boundary; + + return $this; + } + + /** + * Receive notification that the charset of this entity, or a parent entity + * has changed. + * + * @param string $charset + */ + public function charsetChanged($charset) + { + $this->notifyCharsetChanged($charset); + } + + /** + * Receive notification that the encoder of this entity or a parent entity + * has changed. + */ + public function encoderChanged(Swift_Mime_ContentEncoder $encoder) + { + $this->notifyEncoderChanged($encoder); + } + + /** + * Get this entire entity as a string. + * + * @return string + */ + public function toString() + { + $string = $this->headers->toString(); + $string .= $this->bodyToString(); + + return $string; + } + + /** + * Get this entire entity as a string. + * + * @return string + */ + protected function bodyToString() + { + $string = ''; + + if (isset($this->body) && empty($this->immediateChildren)) { + if ($this->cache->hasKey($this->cacheKey, 'body')) { + $body = $this->cache->getString($this->cacheKey, 'body'); + } else { + $body = "\r\n".$this->encoder->encodeString($this->getBody(), 0, $this->getMaxLineLength()); + $this->cache->setString($this->cacheKey, 'body', $body, Swift_KeyCache::MODE_WRITE); + } + $string .= $body; + } + + if (!empty($this->immediateChildren)) { + foreach ($this->immediateChildren as $child) { + $string .= "\r\n\r\n--".$this->getBoundary()."\r\n"; + $string .= $child->toString(); + } + $string .= "\r\n\r\n--".$this->getBoundary()."--\r\n"; + } + + return $string; + } + + /** + * Returns a string representation of this object. + * + * @see toString() + * + * @return string + */ + public function __toString() + { + return $this->toString(); + } + + /** + * Write this entire entity to a {@see Swift_InputByteStream}. + */ + public function toByteStream(Swift_InputByteStream $is) + { + $is->write($this->headers->toString()); + $is->commit(); + + $this->bodyToByteStream($is); + } + + /** + * Write this entire entity to a {@link Swift_InputByteStream}. + */ + protected function bodyToByteStream(Swift_InputByteStream $is) + { + if (empty($this->immediateChildren)) { + if (isset($this->body)) { + if ($this->cache->hasKey($this->cacheKey, 'body')) { + $this->cache->exportToByteStream($this->cacheKey, 'body', $is); + } else { + $cacheIs = $this->cache->getInputByteStream($this->cacheKey, 'body'); + if ($cacheIs) { + $is->bind($cacheIs); + } + + $is->write("\r\n"); + + if ($this->body instanceof Swift_OutputByteStream) { + $this->body->setReadPointer(0); + + $this->encoder->encodeByteStream($this->body, $is, 0, $this->getMaxLineLength()); + } else { + $is->write($this->encoder->encodeString($this->getBody(), 0, $this->getMaxLineLength())); + } + + if ($cacheIs) { + $is->unbind($cacheIs); + } + } + } + } + + if (!empty($this->immediateChildren)) { + foreach ($this->immediateChildren as $child) { + $is->write("\r\n\r\n--".$this->getBoundary()."\r\n"); + $child->toByteStream($is); + } + $is->write("\r\n\r\n--".$this->getBoundary()."--\r\n"); + } + } + + /** + * Get the name of the header that provides the ID of this entity. + */ + protected function getIdField() + { + return 'Content-ID'; + } + + /** + * Get the model data (usually an array or a string) for $field. + */ + protected function getHeaderFieldModel($field) + { + if ($this->headers->has($field)) { + return $this->headers->get($field)->getFieldBodyModel(); + } + } + + /** + * Set the model data for $field. + */ + protected function setHeaderFieldModel($field, $model) + { + if ($this->headers->has($field)) { + $this->headers->get($field)->setFieldBodyModel($model); + + return true; + } + + return false; + } + + /** + * Get the parameter value of $parameter on $field header. + */ + protected function getHeaderParameter($field, $parameter) + { + if ($this->headers->has($field)) { + return $this->headers->get($field)->getParameter($parameter); + } + } + + /** + * Set the parameter value of $parameter on $field header. + */ + protected function setHeaderParameter($field, $parameter, $value) + { + if ($this->headers->has($field)) { + $this->headers->get($field)->setParameter($parameter, $value); + + return true; + } + + return false; + } + + /** + * Re-evaluate what content type and encoding should be used on this entity. + */ + protected function fixHeaders() + { + if (\count($this->immediateChildren)) { + $this->setHeaderParameter('Content-Type', 'boundary', + $this->getBoundary() + ); + $this->headers->remove('Content-Transfer-Encoding'); + } else { + $this->setHeaderParameter('Content-Type', 'boundary', null); + $this->setEncoding($this->encoder->getName()); + } + } + + /** + * Get the KeyCache used in this entity. + * + * @return Swift_KeyCache + */ + protected function getCache() + { + return $this->cache; + } + + /** + * Get the ID generator. + * + * @return Swift_IdGenerator + */ + protected function getIdGenerator() + { + return $this->idGenerator; + } + + /** + * Empty the KeyCache for this entity. + */ + protected function clearCache() + { + $this->cache->clearKey($this->cacheKey, 'body'); + } + + private function readStream(Swift_OutputByteStream $os) + { + $string = ''; + while (false !== $bytes = $os->read(8192)) { + $string .= $bytes; + } + + $os->setReadPointer(0); + + return $string; + } + + private function setEncoding($encoding) + { + if (!$this->setHeaderFieldModel('Content-Transfer-Encoding', $encoding)) { + $this->headers->addTextHeader('Content-Transfer-Encoding', $encoding); + } + } + + private function assertValidBoundary($boundary) + { + if (!preg_match('/^[a-z0-9\'\(\)\+_\-,\.\/:=\?\ ]{0,69}[a-z0-9\'\(\)\+_\-,\.\/:=\?]$/Di', $boundary)) { + throw new Swift_RfcComplianceException('Mime boundary set is not RFC 2046 compliant.'); + } + } + + private function setContentTypeInHeaders($type) + { + if (!$this->setHeaderFieldModel('Content-Type', $type)) { + $this->headers->addParameterizedHeader('Content-Type', $type); + } + } + + private function setNestingLevel($level) + { + $this->nestingLevel = $level; + } + + private function getCompoundLevel($children) + { + $level = 0; + foreach ($children as $child) { + $level |= $child->getNestingLevel(); + } + + return $level; + } + + private function getNeededChildLevel($child, $compoundLevel) + { + $filter = []; + foreach ($this->compoundLevelFilters as $bitmask => $rules) { + if (($compoundLevel & $bitmask) === $bitmask) { + $filter = $rules + $filter; + } + } + + $realLevel = $child->getNestingLevel(); + $lowercaseType = strtolower($child->getContentType() ?? ''); + + if (isset($filter[$realLevel]) && isset($filter[$realLevel][$lowercaseType])) { + return $filter[$realLevel][$lowercaseType]; + } + + return $realLevel; + } + + private function createChild() + { + return new self($this->headers->newInstance(), $this->encoder, $this->cache, $this->idGenerator); + } + + private function notifyEncoderChanged(Swift_Mime_ContentEncoder $encoder) + { + foreach ($this->immediateChildren as $child) { + $child->encoderChanged($encoder); + } + } + + private function notifyCharsetChanged($charset) + { + $this->encoder->charsetChanged($charset); + $this->headers->charsetChanged($charset); + foreach ($this->immediateChildren as $child) { + $child->charsetChanged($charset); + } + } + + private function sortChildren() + { + $shouldSort = false; + foreach ($this->immediateChildren as $child) { + // NOTE: This include alternative parts moved into a related part + if (self::LEVEL_ALTERNATIVE == $child->getNestingLevel()) { + $shouldSort = true; + break; + } + } + + // Sort in order of preference, if there is one + if ($shouldSort) { + // Group the messages by order of preference + $sorted = []; + foreach ($this->immediateChildren as $child) { + $type = $child->getContentType(); + $level = \array_key_exists($type, $this->alternativePartOrder) ? $this->alternativePartOrder[$type] : max($this->alternativePartOrder) + 1; + + if (empty($sorted[$level])) { + $sorted[$level] = []; + } + + $sorted[$level][] = $child; + } + + ksort($sorted); + + $this->immediateChildren = array_reduce($sorted, 'array_merge', []); + } + } + + /** + * Empties it's own contents from the cache. + */ + public function __destruct() + { + if ($this->cache instanceof Swift_KeyCache) { + $this->cache->clearAll($this->cacheKey); + } + } + + /** + * Make a deep copy of object. + */ + public function __clone() + { + $this->headers = clone $this->headers; + $this->encoder = clone $this->encoder; + $this->cacheKey = bin2hex(random_bytes(16)); // set 32 hex values + $children = []; + foreach ($this->children as $pos => $child) { + $children[$pos] = clone $child; + } + $this->setChildren($children); + } + + public function __wakeup() + { + $this->cacheKey = bin2hex(random_bytes(16)); // set 32 hex values + $this->cache = new Swift_KeyCache_ArrayKeyCache(new Swift_KeyCache_SimpleKeyCacheInputStream()); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/MimePart.php b/htdocs/includes/swiftmailer/lib/classes/Swift/MimePart.php index e3440ae0cc3..ea97619ad69 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/MimePart.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/MimePart.php @@ -15,31 +15,31 @@ */ class Swift_MimePart extends Swift_Mime_MimePart { - /** - * Create a new MimePart. - * - * Details may be optionally passed into the constructor. - * - * @param string $body - * @param string $contentType - * @param string $charset - */ - public function __construct($body = null, $contentType = null, $charset = null) - { - \call_user_func_array( - [$this, 'Swift_Mime_MimePart::__construct'], - Swift_DependencyContainer::getInstance() - ->createDependenciesFor('mime.part') - ); + /** + * Create a new MimePart. + * + * Details may be optionally passed into the constructor. + * + * @param string $body + * @param string $contentType + * @param string $charset + */ + public function __construct($body = null, $contentType = null, $charset = null) + { + \call_user_func_array( + [$this, 'Swift_Mime_MimePart::__construct'], + Swift_DependencyContainer::getInstance() + ->createDependenciesFor('mime.part') + ); - if (!isset($charset)) { - $charset = Swift_DependencyContainer::getInstance() - ->lookup('properties.charset'); - } - $this->setBody($body); - $this->setCharset($charset); - if ($contentType) { - $this->setContentType($contentType); - } - } + if (!isset($charset)) { + $charset = Swift_DependencyContainer::getInstance() + ->lookup('properties.charset'); + } + $this->setBody($body); + $this->setCharset($charset); + if ($contentType) { + $this->setContentType($contentType); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/NullTransport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/NullTransport.php index 5be32bfabac..e44b7af982f 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/NullTransport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/NullTransport.php @@ -15,12 +15,12 @@ */ class Swift_NullTransport extends Swift_Transport_NullTransport { - public function __construct() - { - \call_user_func_array( - [$this, 'Swift_Transport_NullTransport::__construct'], - Swift_DependencyContainer::getInstance() - ->createDependenciesFor('transport.null') - ); - } + public function __construct() + { + \call_user_func_array( + [$this, 'Swift_Transport_NullTransport::__construct'], + Swift_DependencyContainer::getInstance() + ->createDependenciesFor('transport.null') + ); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/AntiFloodPlugin.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/AntiFloodPlugin.php index 083ee263ec5..5b1d7deefff 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/AntiFloodPlugin.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/AntiFloodPlugin.php @@ -15,123 +15,123 @@ */ class Swift_Plugins_AntiFloodPlugin implements Swift_Events_SendListener, Swift_Plugins_Sleeper { - /** - * The number of emails to send before restarting Transport. - * - * @var int - */ - private $threshold; + /** + * The number of emails to send before restarting Transport. + * + * @var int + */ + private $threshold; - /** - * The number of seconds to sleep for during a restart. - * - * @var int - */ - private $sleep; + /** + * The number of seconds to sleep for during a restart. + * + * @var int + */ + private $sleep; - /** - * The internal counter. - * - * @var int - */ - private $counter = 0; + /** + * The internal counter. + * + * @var int + */ + private $counter = 0; - /** - * The Sleeper instance for sleeping. - * - * @var Swift_Plugins_Sleeper - */ - private $sleeper; + /** + * The Sleeper instance for sleeping. + * + * @var Swift_Plugins_Sleeper + */ + private $sleeper; - /** - * Create a new AntiFloodPlugin with $threshold and $sleep time. - * - * @param int $threshold - * @param int $sleep time - * @param Swift_Plugins_Sleeper $sleeper (not needed really) - */ - public function __construct($threshold = 99, $sleep = 0, Swift_Plugins_Sleeper $sleeper = null) - { - $this->setThreshold($threshold); - $this->setSleepTime($sleep); - $this->sleeper = $sleeper; - } + /** + * Create a new AntiFloodPlugin with $threshold and $sleep time. + * + * @param int $threshold + * @param int $sleep time + * @param Swift_Plugins_Sleeper $sleeper (not needed really) + */ + public function __construct($threshold = 99, $sleep = 0, Swift_Plugins_Sleeper $sleeper = null) + { + $this->setThreshold($threshold); + $this->setSleepTime($sleep); + $this->sleeper = $sleeper; + } - /** - * Set the number of emails to send before restarting. - * - * @param int $threshold - */ - public function setThreshold($threshold) - { - $this->threshold = $threshold; - } + /** + * Set the number of emails to send before restarting. + * + * @param int $threshold + */ + public function setThreshold($threshold) + { + $this->threshold = $threshold; + } - /** - * Get the number of emails to send before restarting. - * - * @return int - */ - public function getThreshold() - { - return $this->threshold; - } + /** + * Get the number of emails to send before restarting. + * + * @return int + */ + public function getThreshold() + { + return $this->threshold; + } - /** - * Set the number of seconds to sleep for during a restart. - * - * @param int $sleep time - */ - public function setSleepTime($sleep) - { - $this->sleep = $sleep; - } + /** + * Set the number of seconds to sleep for during a restart. + * + * @param int $sleep time + */ + public function setSleepTime($sleep) + { + $this->sleep = $sleep; + } - /** - * Get the number of seconds to sleep for during a restart. - * - * @return int - */ - public function getSleepTime() - { - return $this->sleep; - } + /** + * Get the number of seconds to sleep for during a restart. + * + * @return int + */ + public function getSleepTime() + { + return $this->sleep; + } - /** - * Invoked immediately before the Message is sent. - */ - public function beforeSendPerformed(Swift_Events_SendEvent $evt) - { - } + /** + * Invoked immediately before the Message is sent. + */ + public function beforeSendPerformed(Swift_Events_SendEvent $evt) + { + } - /** - * Invoked immediately after the Message is sent. - */ - public function sendPerformed(Swift_Events_SendEvent $evt) - { - ++$this->counter; - if ($this->counter >= $this->threshold) { - $transport = $evt->getTransport(); - $transport->stop(); - if ($this->sleep) { - $this->sleep($this->sleep); - } - $transport->start(); - $this->counter = 0; - } - } + /** + * Invoked immediately after the Message is sent. + */ + public function sendPerformed(Swift_Events_SendEvent $evt) + { + ++$this->counter; + if ($this->counter >= $this->threshold) { + $transport = $evt->getTransport(); + $transport->stop(); + if ($this->sleep) { + $this->sleep($this->sleep); + } + $transport->start(); + $this->counter = 0; + } + } - /** - * Sleep for $seconds. - * - * @param int $seconds - */ - public function sleep($seconds) - { - if (isset($this->sleeper)) { - $this->sleeper->sleep($seconds); - } else { - sleep($seconds); - } - } + /** + * Sleep for $seconds. + * + * @param int $seconds + */ + public function sleep($seconds) + { + if (isset($this->sleeper)) { + $this->sleeper->sleep($seconds); + } else { + sleep($seconds); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/BandwidthMonitorPlugin.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/BandwidthMonitorPlugin.php index efffe57c9fb..36451f44f1f 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/BandwidthMonitorPlugin.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/BandwidthMonitorPlugin.php @@ -15,140 +15,140 @@ */ class Swift_Plugins_BandwidthMonitorPlugin implements Swift_Events_SendListener, Swift_Events_CommandListener, Swift_Events_ResponseListener, Swift_InputByteStream { - /** - * The outgoing traffic counter. - * - * @var int - */ - private $out = 0; + /** + * The outgoing traffic counter. + * + * @var int + */ + private $out = 0; - /** - * The incoming traffic counter. - * - * @var int - */ - private $in = 0; + /** + * The incoming traffic counter. + * + * @var int + */ + private $in = 0; - /** Bound byte streams */ - private $mirrors = []; + /** Bound byte streams */ + private $mirrors = []; - /** - * Not used. - */ - public function beforeSendPerformed(Swift_Events_SendEvent $evt) - { - } + /** + * Not used. + */ + public function beforeSendPerformed(Swift_Events_SendEvent $evt) + { + } - /** - * Invoked immediately after the Message is sent. - */ - public function sendPerformed(Swift_Events_SendEvent $evt) - { - $message = $evt->getMessage(); - $message->toByteStream($this); - } + /** + * Invoked immediately after the Message is sent. + */ + public function sendPerformed(Swift_Events_SendEvent $evt) + { + $message = $evt->getMessage(); + $message->toByteStream($this); + } - /** - * Invoked immediately following a command being sent. - */ - public function commandSent(Swift_Events_CommandEvent $evt) - { - $command = $evt->getCommand(); - $this->out += \strlen($command); - } + /** + * Invoked immediately following a command being sent. + */ + public function commandSent(Swift_Events_CommandEvent $evt) + { + $command = $evt->getCommand(); + $this->out += \strlen($command); + } - /** - * Invoked immediately following a response coming back. - */ - public function responseReceived(Swift_Events_ResponseEvent $evt) - { - $response = $evt->getResponse(); - $this->in += \strlen($response); - } + /** + * Invoked immediately following a response coming back. + */ + public function responseReceived(Swift_Events_ResponseEvent $evt) + { + $response = $evt->getResponse(); + $this->in += \strlen($response); + } - /** - * Called when a message is sent so that the outgoing counter can be increased. - * - * @param string $bytes - */ - public function write($bytes) - { - $this->out += \strlen($bytes); - foreach ($this->mirrors as $stream) { - $stream->write($bytes); - } - } + /** + * Called when a message is sent so that the outgoing counter can be increased. + * + * @param string $bytes + */ + public function write($bytes) + { + $this->out += \strlen($bytes); + foreach ($this->mirrors as $stream) { + $stream->write($bytes); + } + } - /** - * Not used. - */ - public function commit() - { - } + /** + * Not used. + */ + public function commit() + { + } - /** - * Attach $is to this stream. - * - * The stream acts as an observer, receiving all data that is written. - * All {@link write()} and {@link flushBuffers()} operations will be mirrored. - */ - public function bind(Swift_InputByteStream $is) - { - $this->mirrors[] = $is; - } + /** + * Attach $is to this stream. + * + * The stream acts as an observer, receiving all data that is written. + * All {@link write()} and {@link flushBuffers()} operations will be mirrored. + */ + public function bind(Swift_InputByteStream $is) + { + $this->mirrors[] = $is; + } - /** - * Remove an already bound stream. - * - * If $is is not bound, no errors will be raised. - * If the stream currently has any buffered data it will be written to $is - * before unbinding occurs. - */ - public function unbind(Swift_InputByteStream $is) - { - foreach ($this->mirrors as $k => $stream) { - if ($is === $stream) { - unset($this->mirrors[$k]); - } - } - } + /** + * Remove an already bound stream. + * + * If $is is not bound, no errors will be raised. + * If the stream currently has any buffered data it will be written to $is + * before unbinding occurs. + */ + public function unbind(Swift_InputByteStream $is) + { + foreach ($this->mirrors as $k => $stream) { + if ($is === $stream) { + unset($this->mirrors[$k]); + } + } + } - /** - * Not used. - */ - public function flushBuffers() - { - foreach ($this->mirrors as $stream) { - $stream->flushBuffers(); - } - } + /** + * Not used. + */ + public function flushBuffers() + { + foreach ($this->mirrors as $stream) { + $stream->flushBuffers(); + } + } - /** - * Get the total number of bytes sent to the server. - * - * @return int - */ - public function getBytesOut() - { - return $this->out; - } + /** + * Get the total number of bytes sent to the server. + * + * @return int + */ + public function getBytesOut() + { + return $this->out; + } - /** - * Get the total number of bytes received from the server. - * - * @return int - */ - public function getBytesIn() - { - return $this->in; - } + /** + * Get the total number of bytes received from the server. + * + * @return int + */ + public function getBytesIn() + { + return $this->in; + } - /** - * Reset the internal counters to zero. - */ - public function reset() - { - $this->out = 0; - $this->in = 0; - } + /** + * Reset the internal counters to zero. + */ + public function reset() + { + $this->out = 0; + $this->in = 0; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/DecoratorPlugin.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/DecoratorPlugin.php index 796965dca4b..93124c9a5f4 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/DecoratorPlugin.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/DecoratorPlugin.php @@ -16,185 +16,185 @@ */ class Swift_Plugins_DecoratorPlugin implements Swift_Events_SendListener, Swift_Plugins_Decorator_Replacements { - /** The replacement map */ - private $replacements; + /** The replacement map */ + private $replacements; - /** The body as it was before replacements */ - private $originalBody; + /** The body as it was before replacements */ + private $originalBody; - /** The original headers of the message, before replacements */ - private $originalHeaders = []; + /** The original headers of the message, before replacements */ + private $originalHeaders = []; - /** Bodies of children before they are replaced */ - private $originalChildBodies = []; + /** Bodies of children before they are replaced */ + private $originalChildBodies = []; - /** The Message that was last replaced */ - private $lastMessage; + /** The Message that was last replaced */ + private $lastMessage; - /** - * Create a new DecoratorPlugin with $replacements. - * - * The $replacements can either be an associative array, or an implementation - * of {@link Swift_Plugins_Decorator_Replacements}. - * - * When using an array, it should be of the form: - * - * $replacements = array( - * "address1@domain.tld" => array("{a}" => "b", "{c}" => "d"), - * "address2@domain.tld" => array("{a}" => "x", "{c}" => "y") - * ) - * - * - * When using an instance of {@link Swift_Plugins_Decorator_Replacements}, - * the object should return just the array of replacements for the address - * given to {@link Swift_Plugins_Decorator_Replacements::getReplacementsFor()}. - * - * @param mixed $replacements Array or Swift_Plugins_Decorator_Replacements - */ - public function __construct($replacements) - { - $this->setReplacements($replacements); - } + /** + * Create a new DecoratorPlugin with $replacements. + * + * The $replacements can either be an associative array, or an implementation + * of {@link Swift_Plugins_Decorator_Replacements}. + * + * When using an array, it should be of the form: + * + * $replacements = array( + * "address1@domain.tld" => array("{a}" => "b", "{c}" => "d"), + * "address2@domain.tld" => array("{a}" => "x", "{c}" => "y") + * ) + * + * + * When using an instance of {@link Swift_Plugins_Decorator_Replacements}, + * the object should return just the array of replacements for the address + * given to {@link Swift_Plugins_Decorator_Replacements::getReplacementsFor()}. + * + * @param mixed $replacements Array or Swift_Plugins_Decorator_Replacements + */ + public function __construct($replacements) + { + $this->setReplacements($replacements); + } - /** - * Sets replacements. - * - * @param mixed $replacements Array or Swift_Plugins_Decorator_Replacements - * - * @see __construct() - */ - public function setReplacements($replacements) - { - if (!($replacements instanceof Swift_Plugins_Decorator_Replacements)) { - $this->replacements = (array) $replacements; - } else { - $this->replacements = $replacements; - } - } + /** + * Sets replacements. + * + * @param mixed $replacements Array or Swift_Plugins_Decorator_Replacements + * + * @see __construct() + */ + public function setReplacements($replacements) + { + if (!($replacements instanceof Swift_Plugins_Decorator_Replacements)) { + $this->replacements = (array) $replacements; + } else { + $this->replacements = $replacements; + } + } - /** - * Invoked immediately before the Message is sent. - */ - public function beforeSendPerformed(Swift_Events_SendEvent $evt) - { - $message = $evt->getMessage(); - $this->restoreMessage($message); - $to = array_keys($message->getTo()); - $address = array_shift($to); - if ($replacements = $this->getReplacementsFor($address)) { - $body = $message->getBody(); - $search = array_keys($replacements); - $replace = array_values($replacements); - $bodyReplaced = str_replace( - $search, $replace, $body - ); - if ($body != $bodyReplaced) { - $this->originalBody = $body; - $message->setBody($bodyReplaced); - } + /** + * Invoked immediately before the Message is sent. + */ + public function beforeSendPerformed(Swift_Events_SendEvent $evt) + { + $message = $evt->getMessage(); + $this->restoreMessage($message); + $to = array_keys($message->getTo()); + $address = array_shift($to); + if ($replacements = $this->getReplacementsFor($address)) { + $body = $message->getBody(); + $search = array_keys($replacements); + $replace = array_values($replacements); + $bodyReplaced = str_replace( + $search, $replace, $body + ); + if ($body != $bodyReplaced) { + $this->originalBody = $body; + $message->setBody($bodyReplaced); + } - foreach ($message->getHeaders()->getAll() as $header) { - $body = $header->getFieldBodyModel(); - $count = 0; - if (\is_array($body)) { - $bodyReplaced = []; - foreach ($body as $key => $value) { - $count1 = 0; - $count2 = 0; - $key = \is_string($key) ? str_replace($search, $replace, $key, $count1) : $key; - $value = \is_string($value) ? str_replace($search, $replace, $value, $count2) : $value; - $bodyReplaced[$key] = $value; + foreach ($message->getHeaders()->getAll() as $header) { + $body = $header->getFieldBodyModel(); + $count = 0; + if (\is_array($body)) { + $bodyReplaced = []; + foreach ($body as $key => $value) { + $count1 = 0; + $count2 = 0; + $key = \is_string($key) ? str_replace($search, $replace, $key, $count1) : $key; + $value = \is_string($value) ? str_replace($search, $replace, $value, $count2) : $value; + $bodyReplaced[$key] = $value; - if (!$count && ($count1 || $count2)) { - $count = 1; - } - } - } elseif (\is_string($body)) { - $bodyReplaced = str_replace($search, $replace, $body, $count); - } + if (!$count && ($count1 || $count2)) { + $count = 1; + } + } + } elseif (\is_string($body)) { + $bodyReplaced = str_replace($search, $replace, $body, $count); + } - if ($count) { - $this->originalHeaders[$header->getFieldName()] = $body; - $header->setFieldBodyModel($bodyReplaced); - } - } + if ($count) { + $this->originalHeaders[$header->getFieldName()] = $body; + $header->setFieldBodyModel($bodyReplaced); + } + } - $children = (array) $message->getChildren(); - foreach ($children as $child) { - list($type) = sscanf($child->getContentType(), '%[^/]/%s'); - if ('text' == $type) { - $body = $child->getBody(); - $bodyReplaced = str_replace( - $search, $replace, $body - ); - if ($body != $bodyReplaced) { - $child->setBody($bodyReplaced); - $this->originalChildBodies[$child->getId()] = $body; - } - } - } - $this->lastMessage = $message; - } - } + $children = (array) $message->getChildren(); + foreach ($children as $child) { + list($type) = sscanf($child->getContentType(), '%[^/]/%s'); + if ('text' == $type) { + $body = $child->getBody(); + $bodyReplaced = str_replace( + $search, $replace, $body + ); + if ($body != $bodyReplaced) { + $child->setBody($bodyReplaced); + $this->originalChildBodies[$child->getId()] = $body; + } + } + } + $this->lastMessage = $message; + } + } - /** - * Find a map of replacements for the address. - * - * If this plugin was provided with a delegate instance of - * {@link Swift_Plugins_Decorator_Replacements} then the call will be - * delegated to it. Otherwise, it will attempt to find the replacements - * from the array provided in the constructor. - * - * If no replacements can be found, an empty value (NULL) is returned. - * - * @param string $address - * - * @return array - */ - public function getReplacementsFor($address) - { - if ($this->replacements instanceof Swift_Plugins_Decorator_Replacements) { - return $this->replacements->getReplacementsFor($address); - } + /** + * Find a map of replacements for the address. + * + * If this plugin was provided with a delegate instance of + * {@link Swift_Plugins_Decorator_Replacements} then the call will be + * delegated to it. Otherwise, it will attempt to find the replacements + * from the array provided in the constructor. + * + * If no replacements can be found, an empty value (NULL) is returned. + * + * @param string $address + * + * @return array + */ + public function getReplacementsFor($address) + { + if ($this->replacements instanceof Swift_Plugins_Decorator_Replacements) { + return $this->replacements->getReplacementsFor($address); + } - return $this->replacements[$address] ?? null; - } + return $this->replacements[$address] ?? null; + } - /** - * Invoked immediately after the Message is sent. - */ - public function sendPerformed(Swift_Events_SendEvent $evt) - { - $this->restoreMessage($evt->getMessage()); - } + /** + * Invoked immediately after the Message is sent. + */ + public function sendPerformed(Swift_Events_SendEvent $evt) + { + $this->restoreMessage($evt->getMessage()); + } - /** Restore a changed message back to its original state */ - private function restoreMessage(Swift_Mime_SimpleMessage $message) - { - if ($this->lastMessage === $message) { - if (isset($this->originalBody)) { - $message->setBody($this->originalBody); - $this->originalBody = null; - } - if (!empty($this->originalHeaders)) { - foreach ($message->getHeaders()->getAll() as $header) { - if (\array_key_exists($header->getFieldName(), $this->originalHeaders)) { - $header->setFieldBodyModel($this->originalHeaders[$header->getFieldName()]); - } - } - $this->originalHeaders = []; - } - if (!empty($this->originalChildBodies)) { - $children = (array) $message->getChildren(); - foreach ($children as $child) { - $id = $child->getId(); - if (\array_key_exists($id, $this->originalChildBodies)) { - $child->setBody($this->originalChildBodies[$id]); - } - } - $this->originalChildBodies = []; - } - $this->lastMessage = null; - } - } + /** Restore a changed message back to its original state */ + private function restoreMessage(Swift_Mime_SimpleMessage $message) + { + if ($this->lastMessage === $message) { + if (isset($this->originalBody)) { + $message->setBody($this->originalBody); + $this->originalBody = null; + } + if (!empty($this->originalHeaders)) { + foreach ($message->getHeaders()->getAll() as $header) { + if (\array_key_exists($header->getFieldName(), $this->originalHeaders)) { + $header->setFieldBodyModel($this->originalHeaders[$header->getFieldName()]); + } + } + $this->originalHeaders = []; + } + if (!empty($this->originalChildBodies)) { + $children = (array) $message->getChildren(); + foreach ($children as $child) { + $id = $child->getId(); + if (\array_key_exists($id, $this->originalChildBodies)) { + $child->setBody($this->originalChildBodies[$id]); + } + } + $this->originalChildBodies = []; + } + $this->lastMessage = null; + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/ImpersonatePlugin.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/ImpersonatePlugin.php index 69d31f0a465..3f4dbbfa40f 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/ImpersonatePlugin.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/ImpersonatePlugin.php @@ -15,51 +15,51 @@ */ class Swift_Plugins_ImpersonatePlugin implements Swift_Events_SendListener { - /** - * The sender to impersonate. - * - * @var string - */ - private $sender; + /** + * The sender to impersonate. + * + * @var string + */ + private $sender; - /** - * Create a new ImpersonatePlugin to impersonate $sender. - * - * @param string $sender address - */ - public function __construct($sender) - { - $this->sender = $sender; - } + /** + * Create a new ImpersonatePlugin to impersonate $sender. + * + * @param string $sender address + */ + public function __construct($sender) + { + $this->sender = $sender; + } - /** - * Invoked immediately before the Message is sent. - */ - public function beforeSendPerformed(Swift_Events_SendEvent $evt) - { - $message = $evt->getMessage(); - $headers = $message->getHeaders(); + /** + * Invoked immediately before the Message is sent. + */ + public function beforeSendPerformed(Swift_Events_SendEvent $evt) + { + $message = $evt->getMessage(); + $headers = $message->getHeaders(); - // save current recipients - $headers->addPathHeader('X-Swift-Return-Path', $message->getReturnPath()); + // save current recipients + $headers->addPathHeader('X-Swift-Return-Path', $message->getReturnPath()); - // replace them with the one to send to - $message->setReturnPath($this->sender); - } + // replace them with the one to send to + $message->setReturnPath($this->sender); + } - /** - * Invoked immediately after the Message is sent. - */ - public function sendPerformed(Swift_Events_SendEvent $evt) - { - $message = $evt->getMessage(); + /** + * Invoked immediately after the Message is sent. + */ + public function sendPerformed(Swift_Events_SendEvent $evt) + { + $message = $evt->getMessage(); - // restore original headers - $headers = $message->getHeaders(); + // restore original headers + $headers = $message->getHeaders(); - if ($headers->has('X-Swift-Return-Path')) { - $message->setReturnPath($headers->get('X-Swift-Return-Path')->getAddress()); - $headers->removeAll('X-Swift-Return-Path'); - } - } + if ($headers->has('X-Swift-Return-Path')) { + $message->setReturnPath($headers->get('X-Swift-Return-Path')->getAddress()); + $headers->removeAll('X-Swift-Return-Path'); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/LoggerPlugin.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/LoggerPlugin.php index afb0a3df297..e183749b7ec 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/LoggerPlugin.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/LoggerPlugin.php @@ -15,112 +15,112 @@ */ class Swift_Plugins_LoggerPlugin implements Swift_Events_CommandListener, Swift_Events_ResponseListener, Swift_Events_TransportChangeListener, Swift_Events_TransportExceptionListener, Swift_Plugins_Logger { - /** The logger which is delegated to */ - private $logger; + /** The logger which is delegated to */ + private $logger; - /** - * Create a new LoggerPlugin using $logger. - */ - public function __construct(Swift_Plugins_Logger $logger) - { - $this->logger = $logger; - } + /** + * Create a new LoggerPlugin using $logger. + */ + public function __construct(Swift_Plugins_Logger $logger) + { + $this->logger = $logger; + } - /** - * Add a log entry. - * - * @param string $entry - */ - public function add($entry) - { - $this->logger->add($entry); - } + /** + * Add a log entry. + * + * @param string $entry + */ + public function add($entry) + { + $this->logger->add($entry); + } - /** - * Clear the log contents. - */ - public function clear() - { - $this->logger->clear(); - } + /** + * Clear the log contents. + */ + public function clear() + { + $this->logger->clear(); + } - /** - * Get this log as a string. - * - * @return string - */ - public function dump() - { - return $this->logger->dump(); - } + /** + * Get this log as a string. + * + * @return string + */ + public function dump() + { + return $this->logger->dump(); + } - /** - * Invoked immediately following a command being sent. - */ - public function commandSent(Swift_Events_CommandEvent $evt) - { - $command = $evt->getCommand(); - $this->logger->add(sprintf('>> %s', $command)); - } + /** + * Invoked immediately following a command being sent. + */ + public function commandSent(Swift_Events_CommandEvent $evt) + { + $command = $evt->getCommand(); + $this->logger->add(sprintf('>> %s', $command)); + } - /** - * Invoked immediately following a response coming back. - */ - public function responseReceived(Swift_Events_ResponseEvent $evt) - { - $response = $evt->getResponse(); - $this->logger->add(sprintf('<< %s', $response)); - } + /** + * Invoked immediately following a response coming back. + */ + public function responseReceived(Swift_Events_ResponseEvent $evt) + { + $response = $evt->getResponse(); + $this->logger->add(sprintf('<< %s', $response)); + } - /** - * Invoked just before a Transport is started. - */ - public function beforeTransportStarted(Swift_Events_TransportChangeEvent $evt) - { - $transportName = \get_class($evt->getSource()); - $this->logger->add(sprintf('++ Starting %s', $transportName)); - } + /** + * Invoked just before a Transport is started. + */ + public function beforeTransportStarted(Swift_Events_TransportChangeEvent $evt) + { + $transportName = \get_class($evt->getSource()); + $this->logger->add(sprintf('++ Starting %s', $transportName)); + } - /** - * Invoked immediately after the Transport is started. - */ - public function transportStarted(Swift_Events_TransportChangeEvent $evt) - { - $transportName = \get_class($evt->getSource()); - $this->logger->add(sprintf('++ %s started', $transportName)); - } + /** + * Invoked immediately after the Transport is started. + */ + public function transportStarted(Swift_Events_TransportChangeEvent $evt) + { + $transportName = \get_class($evt->getSource()); + $this->logger->add(sprintf('++ %s started', $transportName)); + } - /** - * Invoked just before a Transport is stopped. - */ - public function beforeTransportStopped(Swift_Events_TransportChangeEvent $evt) - { - $transportName = \get_class($evt->getSource()); - $this->logger->add(sprintf('++ Stopping %s', $transportName)); - } + /** + * Invoked just before a Transport is stopped. + */ + public function beforeTransportStopped(Swift_Events_TransportChangeEvent $evt) + { + $transportName = \get_class($evt->getSource()); + $this->logger->add(sprintf('++ Stopping %s', $transportName)); + } - /** - * Invoked immediately after the Transport is stopped. - */ - public function transportStopped(Swift_Events_TransportChangeEvent $evt) - { - $transportName = \get_class($evt->getSource()); - $this->logger->add(sprintf('++ %s stopped', $transportName)); - } + /** + * Invoked immediately after the Transport is stopped. + */ + public function transportStopped(Swift_Events_TransportChangeEvent $evt) + { + $transportName = \get_class($evt->getSource()); + $this->logger->add(sprintf('++ %s stopped', $transportName)); + } - /** - * Invoked as a TransportException is thrown in the Transport system. - */ - public function exceptionThrown(Swift_Events_TransportExceptionEvent $evt) - { - $e = $evt->getException(); - $message = $e->getMessage(); - $code = $e->getCode(); - $this->logger->add(sprintf('!! %s (code: %s)', $message, $code)); - $message .= PHP_EOL; - $message .= 'Log data:'.PHP_EOL; - $message .= $this->logger->dump(); - $evt->cancelBubble(); - throw new Swift_TransportException($message, $code, $e->getPrevious()); - } + /** + * Invoked as a TransportException is thrown in the Transport system. + */ + public function exceptionThrown(Swift_Events_TransportExceptionEvent $evt) + { + $e = $evt->getException(); + $message = $e->getMessage(); + $code = $e->getCode(); + $this->logger->add(sprintf('!! %s (code: %s)', $message, $code)); + $message .= PHP_EOL; + $message .= 'Log data:'.PHP_EOL; + $message .= $this->logger->dump(); + $evt->cancelBubble(); + throw new Swift_TransportException($message, $code, $e->getPrevious()); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Loggers/ArrayLogger.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Loggers/ArrayLogger.php index 0761b84f83d..6f595adaa4d 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Loggers/ArrayLogger.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Loggers/ArrayLogger.php @@ -15,58 +15,58 @@ */ class Swift_Plugins_Loggers_ArrayLogger implements Swift_Plugins_Logger { - /** - * The log contents. - * - * @var array - */ - private $log = []; + /** + * The log contents. + * + * @var array + */ + private $log = []; - /** - * Max size of the log. - * - * @var int - */ - private $size = 0; + /** + * Max size of the log. + * + * @var int + */ + private $size = 0; - /** - * Create a new ArrayLogger with a maximum of $size entries. - * - * @var int - */ - public function __construct($size = 50) - { - $this->size = $size; - } + /** + * Create a new ArrayLogger with a maximum of $size entries. + * + * @var int + */ + public function __construct($size = 50) + { + $this->size = $size; + } - /** - * Add a log entry. - * - * @param string $entry - */ - public function add($entry) - { - $this->log[] = $entry; - while (\count($this->log) > $this->size) { - array_shift($this->log); - } - } + /** + * Add a log entry. + * + * @param string $entry + */ + public function add($entry) + { + $this->log[] = $entry; + while (\count($this->log) > $this->size) { + array_shift($this->log); + } + } - /** - * Clear the log contents. - */ - public function clear() - { - $this->log = []; - } + /** + * Clear the log contents. + */ + public function clear() + { + $this->log = []; + } - /** - * Get this log as a string. - * - * @return string - */ - public function dump() - { - return implode(PHP_EOL, $this->log); - } + /** + * Get this log as a string. + * + * @return string + */ + public function dump() + { + return implode(PHP_EOL, $this->log); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/MessageLogger.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/MessageLogger.php index 6aaf87599cb..39c48ed18f5 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/MessageLogger.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/MessageLogger.php @@ -15,56 +15,56 @@ */ class Swift_Plugins_MessageLogger implements Swift_Events_SendListener { - /** - * @var Swift_Mime_SimpleMessage[] - */ - private $messages; + /** + * @var Swift_Mime_SimpleMessage[] + */ + private $messages; - public function __construct() - { - $this->messages = []; - } + public function __construct() + { + $this->messages = []; + } - /** - * Get the message list. - * - * @return Swift_Mime_SimpleMessage[] - */ - public function getMessages() - { - return $this->messages; - } + /** + * Get the message list. + * + * @return Swift_Mime_SimpleMessage[] + */ + public function getMessages() + { + return $this->messages; + } - /** - * Get the message count. - * - * @return int count - */ - public function countMessages() - { - return \count($this->messages); - } + /** + * Get the message count. + * + * @return int count + */ + public function countMessages() + { + return \count($this->messages); + } - /** - * Empty the message list. - */ - public function clear() - { - $this->messages = []; - } + /** + * Empty the message list. + */ + public function clear() + { + $this->messages = []; + } - /** - * Invoked immediately before the Message is sent. - */ - public function beforeSendPerformed(Swift_Events_SendEvent $evt) - { - $this->messages[] = clone $evt->getMessage(); - } + /** + * Invoked immediately before the Message is sent. + */ + public function beforeSendPerformed(Swift_Events_SendEvent $evt) + { + $this->messages[] = clone $evt->getMessage(); + } - /** - * Invoked immediately after the Message is sent. - */ - public function sendPerformed(Swift_Events_SendEvent $evt) - { - } + /** + * Invoked immediately after the Message is sent. + */ + public function sendPerformed(Swift_Events_SendEvent $evt) + { + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/PopBeforeSmtpPlugin.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/PopBeforeSmtpPlugin.php index cf4f2438ec0..9448594090b 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/PopBeforeSmtpPlugin.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/PopBeforeSmtpPlugin.php @@ -15,228 +15,228 @@ */ class Swift_Plugins_PopBeforeSmtpPlugin implements Swift_Events_TransportChangeListener, Swift_Plugins_Pop_Pop3Connection { - /** A delegate connection to use (mostly a test hook) */ - private $connection; + /** A delegate connection to use (mostly a test hook) */ + private $connection; - /** Hostname of the POP3 server */ - private $host; + /** Hostname of the POP3 server */ + private $host; - /** Port number to connect on */ - private $port; + /** Port number to connect on */ + private $port; - /** Encryption type to use (if any) */ - private $crypto; + /** Encryption type to use (if any) */ + private $crypto; - /** Username to use (if any) */ - private $username; + /** Username to use (if any) */ + private $username; - /** Password to use (if any) */ - private $password; + /** Password to use (if any) */ + private $password; - /** Established connection via TCP socket */ - private $socket; + /** Established connection via TCP socket */ + private $socket; - /** Connect timeout in seconds */ - private $timeout = 10; + /** Connect timeout in seconds */ + private $timeout = 10; - /** SMTP Transport to bind to */ - private $transport; + /** SMTP Transport to bind to */ + private $transport; - /** - * Create a new PopBeforeSmtpPlugin for $host and $port. - * - * @param string $host Hostname or IP. Literal IPv6 addresses should be - * wrapped in square brackets. - * @param int $port - * @param string $crypto as "tls" or "ssl" - */ - public function __construct($host, $port = 110, $crypto = null) - { - $this->host = $host; - $this->port = $port; - $this->crypto = $crypto; - } + /** + * Create a new PopBeforeSmtpPlugin for $host and $port. + * + * @param string $host Hostname or IP. Literal IPv6 addresses should be + * wrapped in square brackets. + * @param int $port + * @param string $crypto as "tls" or "ssl" + */ + public function __construct($host, $port = 110, $crypto = null) + { + $this->host = $host; + $this->port = $port; + $this->crypto = $crypto; + } - /** - * Set a Pop3Connection to delegate to instead of connecting directly. - * - * @return $this - */ - public function setConnection(Swift_Plugins_Pop_Pop3Connection $connection) - { - $this->connection = $connection; + /** + * Set a Pop3Connection to delegate to instead of connecting directly. + * + * @return $this + */ + public function setConnection(Swift_Plugins_Pop_Pop3Connection $connection) + { + $this->connection = $connection; - return $this; - } + return $this; + } - /** - * Bind this plugin to a specific SMTP transport instance. - */ - public function bindSmtp(Swift_Transport $smtp) - { - $this->transport = $smtp; - } + /** + * Bind this plugin to a specific SMTP transport instance. + */ + public function bindSmtp(Swift_Transport $smtp) + { + $this->transport = $smtp; + } - /** - * Set the connection timeout in seconds (default 10). - * - * @param int $timeout - * - * @return $this - */ - public function setTimeout($timeout) - { - $this->timeout = (int) $timeout; + /** + * Set the connection timeout in seconds (default 10). + * + * @param int $timeout + * + * @return $this + */ + public function setTimeout($timeout) + { + $this->timeout = (int) $timeout; - return $this; - } + return $this; + } - /** - * Set the username to use when connecting (if needed). - * - * @param string $username - * - * @return $this - */ - public function setUsername($username) - { - $this->username = $username; + /** + * Set the username to use when connecting (if needed). + * + * @param string $username + * + * @return $this + */ + public function setUsername($username) + { + $this->username = $username; - return $this; - } + return $this; + } - /** - * Set the password to use when connecting (if needed). - * - * @param string $password - * - * @return $this - */ - public function setPassword($password) - { - $this->password = $password; + /** + * Set the password to use when connecting (if needed). + * + * @param string $password + * + * @return $this + */ + public function setPassword($password) + { + $this->password = $password; - return $this; - } + return $this; + } - /** - * Connect to the POP3 host and authenticate. - * - * @throws Swift_Plugins_Pop_Pop3Exception if connection fails - */ - public function connect() - { - if (isset($this->connection)) { - $this->connection->connect(); - } else { - if (!isset($this->socket)) { - if (!$socket = fsockopen( - $this->getHostString(), $this->port, $errno, $errstr, $this->timeout)) { - throw new Swift_Plugins_Pop_Pop3Exception(sprintf('Failed to connect to POP3 host [%s]: %s', $this->host, $errstr)); - } - $this->socket = $socket; + /** + * Connect to the POP3 host and authenticate. + * + * @throws Swift_Plugins_Pop_Pop3Exception if connection fails + */ + public function connect() + { + if (isset($this->connection)) { + $this->connection->connect(); + } else { + if (!isset($this->socket)) { + if (!$socket = fsockopen( + $this->getHostString(), $this->port, $errno, $errstr, $this->timeout)) { + throw new Swift_Plugins_Pop_Pop3Exception(sprintf('Failed to connect to POP3 host [%s]: %s', $this->host, $errstr)); + } + $this->socket = $socket; - if (false === $greeting = fgets($this->socket)) { - throw new Swift_Plugins_Pop_Pop3Exception(sprintf('Failed to connect to POP3 host [%s]', trim($greeting ?? ''))); - } + if (false === $greeting = fgets($this->socket)) { + throw new Swift_Plugins_Pop_Pop3Exception(sprintf('Failed to connect to POP3 host [%s]', trim($greeting ?? ''))); + } - $this->assertOk($greeting); + $this->assertOk($greeting); - if ($this->username) { - $this->command(sprintf("USER %s\r\n", $this->username)); - $this->command(sprintf("PASS %s\r\n", $this->password)); - } - } - } - } + if ($this->username) { + $this->command(sprintf("USER %s\r\n", $this->username)); + $this->command(sprintf("PASS %s\r\n", $this->password)); + } + } + } + } - /** - * Disconnect from the POP3 host. - */ - public function disconnect() - { - if (isset($this->connection)) { - $this->connection->disconnect(); - } else { - $this->command("QUIT\r\n"); - if (!fclose($this->socket)) { - throw new Swift_Plugins_Pop_Pop3Exception(sprintf('POP3 host [%s] connection could not be stopped', $this->host)); - } - $this->socket = null; - } - } + /** + * Disconnect from the POP3 host. + */ + public function disconnect() + { + if (isset($this->connection)) { + $this->connection->disconnect(); + } else { + $this->command("QUIT\r\n"); + if (!fclose($this->socket)) { + throw new Swift_Plugins_Pop_Pop3Exception(sprintf('POP3 host [%s] connection could not be stopped', $this->host)); + } + $this->socket = null; + } + } - /** - * Invoked just before a Transport is started. - */ - public function beforeTransportStarted(Swift_Events_TransportChangeEvent $evt) - { - if (isset($this->transport)) { - if ($this->transport !== $evt->getTransport()) { - return; - } - } + /** + * Invoked just before a Transport is started. + */ + public function beforeTransportStarted(Swift_Events_TransportChangeEvent $evt) + { + if (isset($this->transport)) { + if ($this->transport !== $evt->getTransport()) { + return; + } + } - $this->connect(); - $this->disconnect(); - } + $this->connect(); + $this->disconnect(); + } - /** - * Not used. - */ - public function transportStarted(Swift_Events_TransportChangeEvent $evt) - { - } + /** + * Not used. + */ + public function transportStarted(Swift_Events_TransportChangeEvent $evt) + { + } - /** - * Not used. - */ - public function beforeTransportStopped(Swift_Events_TransportChangeEvent $evt) - { - } + /** + * Not used. + */ + public function beforeTransportStopped(Swift_Events_TransportChangeEvent $evt) + { + } - /** - * Not used. - */ - public function transportStopped(Swift_Events_TransportChangeEvent $evt) - { - } + /** + * Not used. + */ + public function transportStopped(Swift_Events_TransportChangeEvent $evt) + { + } - private function command($command) - { - if (!fwrite($this->socket, $command)) { - throw new Swift_Plugins_Pop_Pop3Exception(sprintf('Failed to write command [%s] to POP3 host', trim($command ?? ''))); - } + private function command($command) + { + if (!fwrite($this->socket, $command)) { + throw new Swift_Plugins_Pop_Pop3Exception(sprintf('Failed to write command [%s] to POP3 host', trim($command ?? ''))); + } - if (false === $response = fgets($this->socket)) { - throw new Swift_Plugins_Pop_Pop3Exception(sprintf('Failed to read from POP3 host after command [%s]', trim($command ?? ''))); - } + if (false === $response = fgets($this->socket)) { + throw new Swift_Plugins_Pop_Pop3Exception(sprintf('Failed to read from POP3 host after command [%s]', trim($command ?? ''))); + } - $this->assertOk($response); + $this->assertOk($response); - return $response; - } + return $response; + } - private function assertOk($response) - { - if ('+OK' != substr($response, 0, 3)) { - throw new Swift_Plugins_Pop_Pop3Exception(sprintf('POP3 command failed [%s]', trim($response ?? ''))); - } - } + private function assertOk($response) + { + if ('+OK' != substr($response, 0, 3)) { + throw new Swift_Plugins_Pop_Pop3Exception(sprintf('POP3 command failed [%s]', trim($response ?? ''))); + } + } - private function getHostString() - { - $host = $this->host; - switch (strtolower($this->crypto ?? '')) { - case 'ssl': - $host = 'ssl://'.$host; - break; + private function getHostString() + { + $host = $this->host; + switch (strtolower($this->crypto ?? '')) { + case 'ssl': + $host = 'ssl://'.$host; + break; - case 'tls': - $host = 'tls://'.$host; - break; - } + case 'tls': + $host = 'tls://'.$host; + break; + } - return $host; - } + return $host; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/RedirectingPlugin.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/RedirectingPlugin.php index 756faa89c67..f7373b2424c 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/RedirectingPlugin.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/RedirectingPlugin.php @@ -15,187 +15,187 @@ */ class Swift_Plugins_RedirectingPlugin implements Swift_Events_SendListener { - /** - * The recipient who will receive all messages. - * - * @var mixed - */ - private $recipient; + /** + * The recipient who will receive all messages. + * + * @var mixed + */ + private $recipient; - /** - * List of regular expression for recipient whitelisting. - * - * @var array - */ - private $whitelist = []; + /** + * List of regular expression for recipient whitelisting. + * + * @var array + */ + private $whitelist = []; - /** - * Create a new RedirectingPlugin. - * - * @param mixed $recipient - */ - public function __construct($recipient, array $whitelist = []) - { - $this->recipient = $recipient; - $this->whitelist = $whitelist; - } + /** + * Create a new RedirectingPlugin. + * + * @param mixed $recipient + */ + public function __construct($recipient, array $whitelist = []) + { + $this->recipient = $recipient; + $this->whitelist = $whitelist; + } - /** - * Set the recipient of all messages. - * - * @param mixed $recipient - */ - public function setRecipient($recipient) - { - $this->recipient = $recipient; - } + /** + * Set the recipient of all messages. + * + * @param mixed $recipient + */ + public function setRecipient($recipient) + { + $this->recipient = $recipient; + } - /** - * Get the recipient of all messages. - * - * @return mixed - */ - public function getRecipient() - { - return $this->recipient; - } + /** + * Get the recipient of all messages. + * + * @return mixed + */ + public function getRecipient() + { + return $this->recipient; + } - /** - * Set a list of regular expressions to whitelist certain recipients. - */ - public function setWhitelist(array $whitelist) - { - $this->whitelist = $whitelist; - } + /** + * Set a list of regular expressions to whitelist certain recipients. + */ + public function setWhitelist(array $whitelist) + { + $this->whitelist = $whitelist; + } - /** - * Get the whitelist. - * - * @return array - */ - public function getWhitelist() - { - return $this->whitelist; - } + /** + * Get the whitelist. + * + * @return array + */ + public function getWhitelist() + { + return $this->whitelist; + } - /** - * Invoked immediately before the Message is sent. - */ - public function beforeSendPerformed(Swift_Events_SendEvent $evt) - { - $message = $evt->getMessage(); - $headers = $message->getHeaders(); + /** + * Invoked immediately before the Message is sent. + */ + public function beforeSendPerformed(Swift_Events_SendEvent $evt) + { + $message = $evt->getMessage(); + $headers = $message->getHeaders(); - // conditionally save current recipients + // conditionally save current recipients - if ($headers->has('to')) { - $headers->addMailboxHeader('X-Swift-To', $message->getTo()); - } + if ($headers->has('to')) { + $headers->addMailboxHeader('X-Swift-To', $message->getTo()); + } - if ($headers->has('cc')) { - $headers->addMailboxHeader('X-Swift-Cc', $message->getCc()); - } + if ($headers->has('cc')) { + $headers->addMailboxHeader('X-Swift-Cc', $message->getCc()); + } - if ($headers->has('bcc')) { - $headers->addMailboxHeader('X-Swift-Bcc', $message->getBcc()); - } + if ($headers->has('bcc')) { + $headers->addMailboxHeader('X-Swift-Bcc', $message->getBcc()); + } - // Filter remaining headers against whitelist - $this->filterHeaderSet($headers, 'To'); - $this->filterHeaderSet($headers, 'Cc'); - $this->filterHeaderSet($headers, 'Bcc'); + // Filter remaining headers against whitelist + $this->filterHeaderSet($headers, 'To'); + $this->filterHeaderSet($headers, 'Cc'); + $this->filterHeaderSet($headers, 'Bcc'); - // Add each hard coded recipient - $to = $message->getTo(); - if (null === $to) { - $to = []; - } + // Add each hard coded recipient + $to = $message->getTo(); + if (null === $to) { + $to = []; + } - foreach ((array) $this->recipient as $recipient) { - if (!\array_key_exists($recipient, $to)) { - $message->addTo($recipient); - } - } - } + foreach ((array) $this->recipient as $recipient) { + if (!\array_key_exists($recipient, $to)) { + $message->addTo($recipient); + } + } + } - /** - * Filter header set against a whitelist of regular expressions. - * - * @param string $type - */ - private function filterHeaderSet(Swift_Mime_SimpleHeaderSet $headerSet, $type) - { - foreach ($headerSet->getAll($type) as $headers) { - $headers->setNameAddresses($this->filterNameAddresses($headers->getNameAddresses())); - } - } + /** + * Filter header set against a whitelist of regular expressions. + * + * @param string $type + */ + private function filterHeaderSet(Swift_Mime_SimpleHeaderSet $headerSet, $type) + { + foreach ($headerSet->getAll($type) as $headers) { + $headers->setNameAddresses($this->filterNameAddresses($headers->getNameAddresses())); + } + } - /** - * Filtered list of addresses => name pairs. - * - * @return array - */ - private function filterNameAddresses(array $recipients) - { - $filtered = []; + /** + * Filtered list of addresses => name pairs. + * + * @return array + */ + private function filterNameAddresses(array $recipients) + { + $filtered = []; - foreach ($recipients as $address => $name) { - if ($this->isWhitelisted($address)) { - $filtered[$address] = $name; - } - } + foreach ($recipients as $address => $name) { + if ($this->isWhitelisted($address)) { + $filtered[$address] = $name; + } + } - return $filtered; - } + return $filtered; + } - /** - * Matches address against whitelist of regular expressions. - * - * @return bool - */ - protected function isWhitelisted($recipient) - { - if (\in_array($recipient, (array) $this->recipient)) { - return true; - } + /** + * Matches address against whitelist of regular expressions. + * + * @return bool + */ + protected function isWhitelisted($recipient) + { + if (\in_array($recipient, (array) $this->recipient)) { + return true; + } - foreach ($this->whitelist as $pattern) { - if (preg_match($pattern, $recipient)) { - return true; - } - } + foreach ($this->whitelist as $pattern) { + if (preg_match($pattern, $recipient)) { + return true; + } + } - return false; - } + return false; + } - /** - * Invoked immediately after the Message is sent. - */ - public function sendPerformed(Swift_Events_SendEvent $evt) - { - $this->restoreMessage($evt->getMessage()); - } + /** + * Invoked immediately after the Message is sent. + */ + public function sendPerformed(Swift_Events_SendEvent $evt) + { + $this->restoreMessage($evt->getMessage()); + } - private function restoreMessage(Swift_Mime_SimpleMessage $message) - { - // restore original headers - $headers = $message->getHeaders(); + private function restoreMessage(Swift_Mime_SimpleMessage $message) + { + // restore original headers + $headers = $message->getHeaders(); - if ($headers->has('X-Swift-To')) { - $message->setTo($headers->get('X-Swift-To')->getNameAddresses()); - $headers->removeAll('X-Swift-To'); - } else { - $message->setTo(null); - } + if ($headers->has('X-Swift-To')) { + $message->setTo($headers->get('X-Swift-To')->getNameAddresses()); + $headers->removeAll('X-Swift-To'); + } else { + $message->setTo(null); + } - if ($headers->has('X-Swift-Cc')) { - $message->setCc($headers->get('X-Swift-Cc')->getNameAddresses()); - $headers->removeAll('X-Swift-Cc'); - } + if ($headers->has('X-Swift-Cc')) { + $message->setCc($headers->get('X-Swift-Cc')->getNameAddresses()); + $headers->removeAll('X-Swift-Cc'); + } - if ($headers->has('X-Swift-Bcc')) { - $message->setBcc($headers->get('X-Swift-Bcc')->getNameAddresses()); - $headers->removeAll('X-Swift-Bcc'); - } - } + if ($headers->has('X-Swift-Bcc')) { + $message->setBcc($headers->get('X-Swift-Bcc')->getNameAddresses()); + $headers->removeAll('X-Swift-Bcc'); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Reporter.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Reporter.php index 384487ba6f8..b8818339722 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Reporter.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Reporter.php @@ -15,17 +15,17 @@ */ interface Swift_Plugins_Reporter { - /** The recipient was accepted for delivery */ - const RESULT_PASS = 0x01; + /** The recipient was accepted for delivery */ + const RESULT_PASS = 0x01; - /** The recipient could not be accepted */ - const RESULT_FAIL = 0x10; + /** The recipient could not be accepted */ + const RESULT_FAIL = 0x10; - /** - * Notifies this ReportNotifier that $address failed or succeeded. - * - * @param string $address - * @param int $result from {@link RESULT_PASS, RESULT_FAIL} - */ - public function notify(Swift_Mime_SimpleMessage $message, $address, $result); + /** + * Notifies this ReportNotifier that $address failed or succeeded. + * + * @param string $address + * @param int $result from {@link RESULT_PASS, RESULT_FAIL} + */ + public function notify(Swift_Mime_SimpleMessage $message, $address, $result); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/ReporterPlugin.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/ReporterPlugin.php index 2ac77ba2d13..c4a016520f6 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/ReporterPlugin.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/ReporterPlugin.php @@ -15,43 +15,43 @@ */ class Swift_Plugins_ReporterPlugin implements Swift_Events_SendListener { - /** - * The reporter backend which takes notifications. - * - * @var Swift_Plugins_Reporter - */ - private $reporter; + /** + * The reporter backend which takes notifications. + * + * @var Swift_Plugins_Reporter + */ + private $reporter; - /** - * Create a new ReporterPlugin using $reporter. - */ - public function __construct(Swift_Plugins_Reporter $reporter) - { - $this->reporter = $reporter; - } + /** + * Create a new ReporterPlugin using $reporter. + */ + public function __construct(Swift_Plugins_Reporter $reporter) + { + $this->reporter = $reporter; + } - /** - * Not used. - */ - public function beforeSendPerformed(Swift_Events_SendEvent $evt) - { - } + /** + * Not used. + */ + public function beforeSendPerformed(Swift_Events_SendEvent $evt) + { + } - /** - * Invoked immediately after the Message is sent. - */ - public function sendPerformed(Swift_Events_SendEvent $evt) - { - $message = $evt->getMessage(); - $failures = array_flip($evt->getFailedRecipients()); - foreach ((array) $message->getTo() as $address => $null) { - $this->reporter->notify($message, $address, (\array_key_exists($address, $failures) ? Swift_Plugins_Reporter::RESULT_FAIL : Swift_Plugins_Reporter::RESULT_PASS)); - } - foreach ((array) $message->getCc() as $address => $null) { - $this->reporter->notify($message, $address, (\array_key_exists($address, $failures) ? Swift_Plugins_Reporter::RESULT_FAIL : Swift_Plugins_Reporter::RESULT_PASS)); - } - foreach ((array) $message->getBcc() as $address => $null) { - $this->reporter->notify($message, $address, (\array_key_exists($address, $failures) ? Swift_Plugins_Reporter::RESULT_FAIL : Swift_Plugins_Reporter::RESULT_PASS)); - } - } + /** + * Invoked immediately after the Message is sent. + */ + public function sendPerformed(Swift_Events_SendEvent $evt) + { + $message = $evt->getMessage(); + $failures = array_flip($evt->getFailedRecipients()); + foreach ((array) $message->getTo() as $address => $null) { + $this->reporter->notify($message, $address, (\array_key_exists($address, $failures) ? Swift_Plugins_Reporter::RESULT_FAIL : Swift_Plugins_Reporter::RESULT_PASS)); + } + foreach ((array) $message->getCc() as $address => $null) { + $this->reporter->notify($message, $address, (\array_key_exists($address, $failures) ? Swift_Plugins_Reporter::RESULT_FAIL : Swift_Plugins_Reporter::RESULT_PASS)); + } + foreach ((array) $message->getBcc() as $address => $null) { + $this->reporter->notify($message, $address, (\array_key_exists($address, $failures) ? Swift_Plugins_Reporter::RESULT_FAIL : Swift_Plugins_Reporter::RESULT_PASS)); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Reporters/HitReporter.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Reporters/HitReporter.php index ef88d47119e..249cffbde7b 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Reporters/HitReporter.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Reporters/HitReporter.php @@ -15,44 +15,44 @@ */ class Swift_Plugins_Reporters_HitReporter implements Swift_Plugins_Reporter { - /** - * The list of failures. - * - * @var array - */ - private $failures = []; + /** + * The list of failures. + * + * @var array + */ + private $failures = []; - private $failures_cache = []; + private $failures_cache = []; - /** - * Notifies this ReportNotifier that $address failed or succeeded. - * - * @param string $address - * @param int $result from {@link RESULT_PASS, RESULT_FAIL} - */ - public function notify(Swift_Mime_SimpleMessage $message, $address, $result) - { - if (self::RESULT_FAIL == $result && !isset($this->failures_cache[$address])) { - $this->failures[] = $address; - $this->failures_cache[$address] = true; - } - } + /** + * Notifies this ReportNotifier that $address failed or succeeded. + * + * @param string $address + * @param int $result from {@link RESULT_PASS, RESULT_FAIL} + */ + public function notify(Swift_Mime_SimpleMessage $message, $address, $result) + { + if (self::RESULT_FAIL == $result && !isset($this->failures_cache[$address])) { + $this->failures[] = $address; + $this->failures_cache[$address] = true; + } + } - /** - * Get an array of addresses for which delivery failed. - * - * @return array - */ - public function getFailedRecipients() - { - return $this->failures; - } + /** + * Get an array of addresses for which delivery failed. + * + * @return array + */ + public function getFailedRecipients() + { + return $this->failures; + } - /** - * Clear the buffer (empty the list). - */ - public function clear() - { - $this->failures = $this->failures_cache = []; - } + /** + * Clear the buffer (empty the list). + */ + public function clear() + { + $this->failures = $this->failures_cache = []; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Reporters/HtmlReporter.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Reporters/HtmlReporter.php index 710a0b370dd..1cfc3f974f8 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Reporters/HtmlReporter.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/Reporters/HtmlReporter.php @@ -15,24 +15,24 @@ */ class Swift_Plugins_Reporters_HtmlReporter implements Swift_Plugins_Reporter { - /** - * Notifies this ReportNotifier that $address failed or succeeded. - * - * @param string $address - * @param int $result from {@see RESULT_PASS, RESULT_FAIL} - */ - public function notify(Swift_Mime_SimpleMessage $message, $address, $result) - { - if (self::RESULT_PASS == $result) { - echo '
'.PHP_EOL; - echo 'PASS '.$address.PHP_EOL; - echo '
'.PHP_EOL; - flush(); - } else { - echo '
'.PHP_EOL; - echo 'FAIL '.$address.PHP_EOL; - echo '
'.PHP_EOL; - flush(); - } - } + /** + * Notifies this ReportNotifier that $address failed or succeeded. + * + * @param string $address + * @param int $result from {@see RESULT_PASS, RESULT_FAIL} + */ + public function notify(Swift_Mime_SimpleMessage $message, $address, $result) + { + if (self::RESULT_PASS == $result) { + echo '
'.PHP_EOL; + echo 'PASS '.$address.PHP_EOL; + echo '
'.PHP_EOL; + flush(); + } else { + echo '
'.PHP_EOL; + echo 'FAIL '.$address.PHP_EOL; + echo '
'.PHP_EOL; + flush(); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/ThrottlerPlugin.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/ThrottlerPlugin.php index 82c5d9fb99f..83d3044927f 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/ThrottlerPlugin.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Plugins/ThrottlerPlugin.php @@ -15,182 +15,182 @@ */ class Swift_Plugins_ThrottlerPlugin extends Swift_Plugins_BandwidthMonitorPlugin implements Swift_Plugins_Sleeper, Swift_Plugins_Timer { - /** Flag for throttling in bytes per minute */ - const BYTES_PER_MINUTE = 0x01; + /** Flag for throttling in bytes per minute */ + const BYTES_PER_MINUTE = 0x01; - /** Flag for throttling in emails per second (Amazon SES) */ - const MESSAGES_PER_SECOND = 0x11; + /** Flag for throttling in emails per second (Amazon SES) */ + const MESSAGES_PER_SECOND = 0x11; - /** Flag for throttling in emails per minute */ - const MESSAGES_PER_MINUTE = 0x10; + /** Flag for throttling in emails per minute */ + const MESSAGES_PER_MINUTE = 0x10; - /** - * The Sleeper instance for sleeping. - * - * @var Swift_Plugins_Sleeper - */ - private $sleeper; + /** + * The Sleeper instance for sleeping. + * + * @var Swift_Plugins_Sleeper + */ + private $sleeper; - /** - * The Timer instance which provides the timestamp. - * - * @var Swift_Plugins_Timer - */ - private $timer; + /** + * The Timer instance which provides the timestamp. + * + * @var Swift_Plugins_Timer + */ + private $timer; - /** - * The time at which the first email was sent. - * - * @var int - */ - private $start; + /** + * The time at which the first email was sent. + * + * @var int + */ + private $start; - /** - * The rate at which messages should be sent. - * - * @var int - */ - private $rate; + /** + * The rate at which messages should be sent. + * + * @var int + */ + private $rate; - /** - * The mode for throttling. - * - * This is {@link BYTES_PER_MINUTE} or {@link MESSAGES_PER_MINUTE} - * - * @var int - */ - private $mode; + /** + * The mode for throttling. + * + * This is {@link BYTES_PER_MINUTE} or {@link MESSAGES_PER_MINUTE} + * + * @var int + */ + private $mode; - /** - * An internal counter of the number of messages sent. - * - * @var int - */ - private $messages = 0; + /** + * An internal counter of the number of messages sent. + * + * @var int + */ + private $messages = 0; - /** - * Create a new ThrottlerPlugin. - * - * @param int $rate - * @param int $mode defaults to {@link BYTES_PER_MINUTE} - * @param Swift_Plugins_Sleeper $sleeper (only needed in testing) - * @param Swift_Plugins_Timer $timer (only needed in testing) - */ - public function __construct($rate, $mode = self::BYTES_PER_MINUTE, Swift_Plugins_Sleeper $sleeper = null, Swift_Plugins_Timer $timer = null) - { - $this->rate = $rate; - $this->mode = $mode; - $this->sleeper = $sleeper; - $this->timer = $timer; - } + /** + * Create a new ThrottlerPlugin. + * + * @param int $rate + * @param int $mode defaults to {@link BYTES_PER_MINUTE} + * @param Swift_Plugins_Sleeper $sleeper (only needed in testing) + * @param Swift_Plugins_Timer $timer (only needed in testing) + */ + public function __construct($rate, $mode = self::BYTES_PER_MINUTE, Swift_Plugins_Sleeper $sleeper = null, Swift_Plugins_Timer $timer = null) + { + $this->rate = $rate; + $this->mode = $mode; + $this->sleeper = $sleeper; + $this->timer = $timer; + } - /** - * Invoked immediately before the Message is sent. - */ - public function beforeSendPerformed(Swift_Events_SendEvent $evt) - { - $time = $this->getTimestamp(); - if (!isset($this->start)) { - $this->start = $time; - } - $duration = $time - $this->start; + /** + * Invoked immediately before the Message is sent. + */ + public function beforeSendPerformed(Swift_Events_SendEvent $evt) + { + $time = $this->getTimestamp(); + if (!isset($this->start)) { + $this->start = $time; + } + $duration = $time - $this->start; - switch ($this->mode) { - case self::BYTES_PER_MINUTE: - $sleep = $this->throttleBytesPerMinute($duration); - break; - case self::MESSAGES_PER_SECOND: - $sleep = $this->throttleMessagesPerSecond($duration); - break; - case self::MESSAGES_PER_MINUTE: - $sleep = $this->throttleMessagesPerMinute($duration); - break; - default: - $sleep = 0; - break; - } + switch ($this->mode) { + case self::BYTES_PER_MINUTE: + $sleep = $this->throttleBytesPerMinute($duration); + break; + case self::MESSAGES_PER_SECOND: + $sleep = $this->throttleMessagesPerSecond($duration); + break; + case self::MESSAGES_PER_MINUTE: + $sleep = $this->throttleMessagesPerMinute($duration); + break; + default: + $sleep = 0; + break; + } - if ($sleep > 0) { - $this->sleep($sleep); - } - } + if ($sleep > 0) { + $this->sleep($sleep); + } + } - /** - * Invoked when a Message is sent. - */ - public function sendPerformed(Swift_Events_SendEvent $evt) - { - parent::sendPerformed($evt); - ++$this->messages; - } + /** + * Invoked when a Message is sent. + */ + public function sendPerformed(Swift_Events_SendEvent $evt) + { + parent::sendPerformed($evt); + ++$this->messages; + } - /** - * Sleep for $seconds. - * - * @param int $seconds - */ - public function sleep($seconds) - { - if (isset($this->sleeper)) { - $this->sleeper->sleep($seconds); - } else { - sleep($seconds); - } - } + /** + * Sleep for $seconds. + * + * @param int $seconds + */ + public function sleep($seconds) + { + if (isset($this->sleeper)) { + $this->sleeper->sleep($seconds); + } else { + sleep($seconds); + } + } - /** - * Get the current UNIX timestamp. - * - * @return int - */ - public function getTimestamp() - { - if (isset($this->timer)) { - return $this->timer->getTimestamp(); - } + /** + * Get the current UNIX timestamp. + * + * @return int + */ + public function getTimestamp() + { + if (isset($this->timer)) { + return $this->timer->getTimestamp(); + } - return time(); - } + return time(); + } - /** - * Get a number of seconds to sleep for. - * - * @param int $timePassed - * - * @return int - */ - private function throttleBytesPerMinute($timePassed) - { - $expectedDuration = $this->getBytesOut() / ($this->rate / 60); + /** + * Get a number of seconds to sleep for. + * + * @param int $timePassed + * + * @return int + */ + private function throttleBytesPerMinute($timePassed) + { + $expectedDuration = $this->getBytesOut() / ($this->rate / 60); - return (int) ceil($expectedDuration - $timePassed); - } + return (int) ceil($expectedDuration - $timePassed); + } - /** - * Get a number of seconds to sleep for. - * - * @param int $timePassed - * - * @return int - */ - private function throttleMessagesPerSecond($timePassed) - { - $expectedDuration = $this->messages / $this->rate; + /** + * Get a number of seconds to sleep for. + * + * @param int $timePassed + * + * @return int + */ + private function throttleMessagesPerSecond($timePassed) + { + $expectedDuration = $this->messages / $this->rate; - return (int) ceil($expectedDuration - $timePassed); - } + return (int) ceil($expectedDuration - $timePassed); + } - /** - * Get a number of seconds to sleep for. - * - * @param int $timePassed - * - * @return int - */ - private function throttleMessagesPerMinute($timePassed) - { - $expectedDuration = $this->messages / ($this->rate / 60); + /** + * Get a number of seconds to sleep for. + * + * @param int $timePassed + * + * @return int + */ + private function throttleMessagesPerMinute($timePassed) + { + $expectedDuration = $this->messages / ($this->rate / 60); - return (int) ceil($expectedDuration - $timePassed); - } + return (int) ceil($expectedDuration - $timePassed); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Preferences.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Preferences.php index 237824ea180..16103e11031 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Preferences.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Preferences.php @@ -15,86 +15,86 @@ */ class Swift_Preferences { - /** Singleton instance */ - private static $instance = null; + /** Singleton instance */ + private static $instance = null; - /** Constructor not to be used */ - private function __construct() - { - } + /** Constructor not to be used */ + private function __construct() + { + } - /** - * Gets the instance of Preferences. - * - * @return self - */ - public static function getInstance() - { - if (!isset(self::$instance)) { - self::$instance = new self(); - } + /** + * Gets the instance of Preferences. + * + * @return self + */ + public static function getInstance() + { + if (!isset(self::$instance)) { + self::$instance = new self(); + } - return self::$instance; - } + return self::$instance; + } - /** - * Set the default charset used. - * - * @param string $charset - * - * @return $this - */ - public function setCharset($charset) - { - Swift_DependencyContainer::getInstance()->register('properties.charset')->asValue($charset); + /** + * Set the default charset used. + * + * @param string $charset + * + * @return $this + */ + public function setCharset($charset) + { + Swift_DependencyContainer::getInstance()->register('properties.charset')->asValue($charset); - return $this; - } + return $this; + } - /** - * Set the directory where temporary files can be saved. - * - * @param string $dir - * - * @return $this - */ - public function setTempDir($dir) - { - Swift_DependencyContainer::getInstance()->register('tempdir')->asValue($dir); + /** + * Set the directory where temporary files can be saved. + * + * @param string $dir + * + * @return $this + */ + public function setTempDir($dir) + { + Swift_DependencyContainer::getInstance()->register('tempdir')->asValue($dir); - return $this; - } + return $this; + } - /** - * Set the type of cache to use (i.e. "disk" or "array"). - * - * @param string $type - * - * @return $this - */ - public function setCacheType($type) - { - Swift_DependencyContainer::getInstance()->register('cache')->asAliasOf(sprintf('cache.%s', $type)); + /** + * Set the type of cache to use (i.e. "disk" or "array"). + * + * @param string $type + * + * @return $this + */ + public function setCacheType($type) + { + Swift_DependencyContainer::getInstance()->register('cache')->asAliasOf(sprintf('cache.%s', $type)); - return $this; - } + return $this; + } - /** - * Set the QuotedPrintable dot escaper preference. - * - * @param bool $dotEscape - * - * @return $this - */ - public function setQPDotEscape($dotEscape) - { - $dotEscape = !empty($dotEscape); - Swift_DependencyContainer::getInstance() - ->register('mime.qpcontentencoder') - ->asNewInstanceOf('Swift_Mime_ContentEncoder_QpContentEncoder') - ->withDependencies(['mime.charstream', 'mime.bytecanonicalizer']) - ->addConstructorValue($dotEscape); + /** + * Set the QuotedPrintable dot escaper preference. + * + * @param bool $dotEscape + * + * @return $this + */ + public function setQPDotEscape($dotEscape) + { + $dotEscape = !empty($dotEscape); + Swift_DependencyContainer::getInstance() + ->register('mime.qpcontentencoder') + ->asNewInstanceOf('Swift_Mime_ContentEncoder_QpContentEncoder') + ->withDependencies(['mime.charstream', 'mime.bytecanonicalizer']) + ->addConstructorValue($dotEscape); - return $this; - } + return $this; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/SendmailTransport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/SendmailTransport.php index 9f159857a51..3c756436cc8 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/SendmailTransport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/SendmailTransport.php @@ -15,19 +15,19 @@ */ class Swift_SendmailTransport extends Swift_Transport_SendmailTransport { - /** - * Create a new SendmailTransport, optionally using $command for sending. - * - * @param string $command - */ - public function __construct($command = '/usr/sbin/sendmail -bs') - { - \call_user_func_array( - [$this, 'Swift_Transport_SendmailTransport::__construct'], - Swift_DependencyContainer::getInstance() - ->createDependenciesFor('transport.sendmail') - ); + /** + * Create a new SendmailTransport, optionally using $command for sending. + * + * @param string $command + */ + public function __construct($command = '/usr/sbin/sendmail -bs') + { + \call_user_func_array( + [$this, 'Swift_Transport_SendmailTransport::__construct'], + Swift_DependencyContainer::getInstance() + ->createDependenciesFor('transport.sendmail') + ); - $this->setCommand($command); - } + $this->setCommand($command); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Signer.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Signer.php index 4a681f83bfa..26c5e285c03 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Signer.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Signer.php @@ -15,5 +15,5 @@ */ interface Swift_Signer { - public function reset(); + public function reset(); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/BodySigner.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/BodySigner.php index a874e1ab2cb..b25c427af83 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/BodySigner.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/BodySigner.php @@ -15,17 +15,17 @@ */ interface Swift_Signers_BodySigner extends Swift_Signer { - /** - * Change the Swift_Signed_Message to apply the singing. - * - * @return self - */ - public function signMessage(Swift_Message $message); + /** + * Change the Swift_Signed_Message to apply the singing. + * + * @return self + */ + public function signMessage(Swift_Message $message); - /** - * Return the list of header a signer might tamper. - * - * @return array - */ - public function getAlteredHeaders(); + /** + * Return the list of header a signer might tamper. + * + * @return array + */ + public function getAlteredHeaders(); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/DKIMSigner.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/DKIMSigner.php index e7323cb19b9..ec82dc05663 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/DKIMSigner.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/DKIMSigner.php @@ -15,668 +15,668 @@ */ class Swift_Signers_DKIMSigner implements Swift_Signers_HeaderSigner { - /** - * PrivateKey. - * - * @var string - */ - protected $privateKey; - - /** - * DomainName. - * - * @var string - */ - protected $domainName; - - /** - * Selector. - * - * @var string - */ - protected $selector; - - private $passphrase = ''; - - /** - * Hash algorithm used. - * - * @see RFC6376 3.3: Signers MUST implement and SHOULD sign using rsa-sha256. - * - * @var string - */ - protected $hashAlgorithm = 'rsa-sha256'; - - /** - * Body canon method. - * - * @var string - */ - protected $bodyCanon = 'simple'; - - /** - * Header canon method. - * - * @var string - */ - protected $headerCanon = 'simple'; - - /** - * Headers not being signed. - * - * @var array - */ - protected $ignoredHeaders = ['return-path' => true]; - - /** - * Signer identity. - * - * @var string - */ - protected $signerIdentity; - - /** - * BodyLength. - * - * @var int - */ - protected $bodyLen = 0; - - /** - * Maximum signedLen. - * - * @var int - */ - protected $maxLen = PHP_INT_MAX; - - /** - * Embbed bodyLen in signature. - * - * @var bool - */ - protected $showLen = false; - - /** - * When the signature has been applied (true means time()), false means not embedded. - * - * @var mixed - */ - protected $signatureTimestamp = true; - - /** - * When will the signature expires false means not embedded, if sigTimestamp is auto - * Expiration is relative, otherwise it's absolute. - * - * @var int - */ - protected $signatureExpiration = false; - - /** - * Must we embed signed headers? - * - * @var bool - */ - protected $debugHeaders = false; - - // work variables - /** - * Headers used to generate hash. - * - * @var array - */ - protected $signedHeaders = []; - - /** - * If debugHeaders is set store debugData here. - * - * @var string[] - */ - private $debugHeadersData = []; - - /** - * Stores the bodyHash. - * - * @var string - */ - private $bodyHash = ''; - - /** - * Stores the signature header. - * - * @var Swift_Mime_Headers_ParameterizedHeader - */ - protected $dkimHeader; - - private $bodyHashHandler; - - private $headerHash; - - private $headerCanonData = ''; - - private $bodyCanonEmptyCounter = 0; - - private $bodyCanonIgnoreStart = 2; - - private $bodyCanonSpace = false; - - private $bodyCanonLastChar = null; - - private $bodyCanonLine = ''; - - private $bound = []; - - /** - * Constructor. - * - * @param string $privateKey - * @param string $domainName - * @param string $selector - * @param string $passphrase - */ - public function __construct($privateKey, $domainName, $selector, $passphrase = '') - { - $this->privateKey = $privateKey; - $this->domainName = $domainName; - $this->signerIdentity = '@'.$domainName; - $this->selector = $selector; - $this->passphrase = $passphrase; - } - - /** - * Reset the Signer. - * - * @see Swift_Signer::reset() - */ - public function reset() - { - $this->headerHash = null; - $this->signedHeaders = []; - $this->bodyHash = null; - $this->bodyHashHandler = null; - $this->bodyCanonIgnoreStart = 2; - $this->bodyCanonEmptyCounter = 0; - $this->bodyCanonLastChar = null; - $this->bodyCanonSpace = false; - } - - /** - * Writes $bytes to the end of the stream. - * - * Writing may not happen immediately if the stream chooses to buffer. If - * you want to write these bytes with immediate effect, call {@link commit()} - * after calling write(). - * - * This method returns the sequence ID of the write (i.e. 1 for first, 2 for - * second, etc etc). - * - * @param string $bytes - * - * @return int - * - * @throws Swift_IoException - */ - // TODO fix return - public function write($bytes) - { - $this->canonicalizeBody($bytes); - foreach ($this->bound as $is) { - $is->write($bytes); - } - } - - /** - * For any bytes that are currently buffered inside the stream, force them - * off the buffer. - */ - public function commit() - { - // Nothing to do - return; - } - - /** - * Attach $is to this stream. - * - * The stream acts as an observer, receiving all data that is written. - * All {@link write()} and {@link flushBuffers()} operations will be mirrored. - */ - public function bind(Swift_InputByteStream $is) - { - // Don't have to mirror anything - $this->bound[] = $is; - - return; - } - - /** - * Remove an already bound stream. - * - * If $is is not bound, no errors will be raised. - * If the stream currently has any buffered data it will be written to $is - * before unbinding occurs. - */ - public function unbind(Swift_InputByteStream $is) - { - // Don't have to mirror anything - foreach ($this->bound as $k => $stream) { - if ($stream === $is) { - unset($this->bound[$k]); - - return; - } - } - } - - /** - * Flush the contents of the stream (empty it) and set the internal pointer - * to the beginning. - * - * @throws Swift_IoException - */ - public function flushBuffers() - { - $this->reset(); - } - - /** - * Set hash_algorithm, must be one of rsa-sha256 | rsa-sha1. - * - * @param string $hash 'rsa-sha1' or 'rsa-sha256' - * - * @throws Swift_SwiftException - * - * @return $this - */ - public function setHashAlgorithm($hash) - { - switch ($hash) { - case 'rsa-sha1': - $this->hashAlgorithm = 'rsa-sha1'; - break; - case 'rsa-sha256': - $this->hashAlgorithm = 'rsa-sha256'; - if (!\defined('OPENSSL_ALGO_SHA256')) { - throw new Swift_SwiftException('Unable to set sha256 as it is not supported by OpenSSL.'); - } - break; - default: - throw new Swift_SwiftException('Unable to set the hash algorithm, must be one of rsa-sha1 or rsa-sha256 (%s given).', $hash); - } - - return $this; - } - - /** - * Set the body canonicalization algorithm. - * - * @param string $canon - * - * @return $this - */ - public function setBodyCanon($canon) - { - if ('relaxed' == $canon) { - $this->bodyCanon = 'relaxed'; - } else { - $this->bodyCanon = 'simple'; - } - - return $this; - } - - /** - * Set the header canonicalization algorithm. - * - * @param string $canon - * - * @return $this - */ - public function setHeaderCanon($canon) - { - if ('relaxed' == $canon) { - $this->headerCanon = 'relaxed'; - } else { - $this->headerCanon = 'simple'; - } - - return $this; - } - - /** - * Set the signer identity. - * - * @param string $identity - * - * @return $this - */ - public function setSignerIdentity($identity) - { - $this->signerIdentity = $identity; - - return $this; - } - - /** - * Set the length of the body to sign. - * - * @param mixed $len (bool or int) - * - * @return $this - */ - public function setBodySignedLen($len) - { - if (true === $len) { - $this->showLen = true; - $this->maxLen = PHP_INT_MAX; - } elseif (false === $len) { - $this->showLen = false; - $this->maxLen = PHP_INT_MAX; - } else { - $this->showLen = true; - $this->maxLen = (int) $len; - } - - return $this; - } - - /** - * Set the signature timestamp. - * - * @param int $time A timestamp - * - * @return $this - */ - public function setSignatureTimestamp($time) - { - $this->signatureTimestamp = $time; - - return $this; - } - - /** - * Set the signature expiration timestamp. - * - * @param int $time A timestamp - * - * @return $this - */ - public function setSignatureExpiration($time) - { - $this->signatureExpiration = $time; - - return $this; - } - - /** - * Enable / disable the DebugHeaders. - * - * @param bool $debug - * - * @return Swift_Signers_DKIMSigner - */ - public function setDebugHeaders($debug) - { - $this->debugHeaders = (bool) $debug; - - return $this; - } - - /** - * Start Body. - */ - public function startBody() - { - // Init - switch ($this->hashAlgorithm) { - case 'rsa-sha256': - $this->bodyHashHandler = hash_init('sha256'); - break; - case 'rsa-sha1': - $this->bodyHashHandler = hash_init('sha1'); - break; - } - $this->bodyCanonLine = ''; - } - - /** - * End Body. - */ - public function endBody() - { - $this->endOfBody(); - } - - /** - * Returns the list of Headers Tampered by this plugin. - * - * @return array - */ - public function getAlteredHeaders() - { - if ($this->debugHeaders) { - return ['DKIM-Signature', 'X-DebugHash']; - } else { - return ['DKIM-Signature']; - } - } - - /** - * Adds an ignored Header. - * - * @param string $header_name - * - * @return Swift_Signers_DKIMSigner - */ - public function ignoreHeader($header_name) - { - $this->ignoredHeaders[strtolower($header_name ?? '')] = true; - - return $this; - } - - /** - * Set the headers to sign. - * - * @return Swift_Signers_DKIMSigner - */ - public function setHeaders(Swift_Mime_SimpleHeaderSet $headers) - { - $this->headerCanonData = ''; - // Loop through Headers - $listHeaders = $headers->listAll(); - foreach ($listHeaders as $hName) { - // Check if we need to ignore Header - if (!isset($this->ignoredHeaders[strtolower($hName ?? '')])) { - if ($headers->has($hName)) { - $tmp = $headers->getAll($hName); - foreach ($tmp as $header) { - if ('' != $header->getFieldBody()) { - $this->addHeader($header->toString()); - $this->signedHeaders[] = $header->getFieldName(); - } - } - } - } - } - - return $this; - } - - /** - * Add the signature to the given Headers. - * - * @return Swift_Signers_DKIMSigner - */ - public function addSignature(Swift_Mime_SimpleHeaderSet $headers) - { - // Prepare the DKIM-Signature - $params = ['v' => '1', 'a' => $this->hashAlgorithm, 'bh' => base64_encode($this->bodyHash ?? ''), 'd' => $this->domainName, 'h' => implode(': ', $this->signedHeaders), 'i' => $this->signerIdentity, 's' => $this->selector]; - if ('simple' != $this->bodyCanon) { - $params['c'] = $this->headerCanon.'/'.$this->bodyCanon; - } elseif ('simple' != $this->headerCanon) { - $params['c'] = $this->headerCanon; - } - if ($this->showLen) { - $params['l'] = $this->bodyLen; - } - if (true === $this->signatureTimestamp) { - $params['t'] = time(); - if (false !== $this->signatureExpiration) { - $params['x'] = $params['t'] + $this->signatureExpiration; - } - } else { - if (false !== $this->signatureTimestamp) { - $params['t'] = $this->signatureTimestamp; - } - if (false !== $this->signatureExpiration) { - $params['x'] = $this->signatureExpiration; - } - } - if ($this->debugHeaders) { - $params['z'] = implode('|', $this->debugHeadersData); - } - $string = ''; - foreach ($params as $k => $v) { - $string .= $k.'='.$v.'; '; - } - $string = trim($string); - $headers->addTextHeader('DKIM-Signature', $string); - // Add the last DKIM-Signature - $tmp = $headers->getAll('DKIM-Signature'); - $this->dkimHeader = end($tmp); - $this->addHeader(trim($this->dkimHeader->toString() ?? '')."\r\n b=", true); - if ($this->debugHeaders) { - $headers->addTextHeader('X-DebugHash', base64_encode($this->headerHash ?? '')); - } - $this->dkimHeader->setValue($string.' b='.trim(chunk_split(base64_encode($this->getEncryptedHash() ?? ''), 73, ' '))); - - return $this; - } - - /* Private helpers */ - - protected function addHeader($header, $is_sig = false) - { - switch ($this->headerCanon) { - case 'relaxed': - // Prepare Header and cascade - $exploded = explode(':', $header, 2); - $name = strtolower(trim($exploded[0])); - $value = str_replace("\r\n", '', $exploded[1]); - $value = preg_replace("/[ \t][ \t]+/", ' ', $value); - $header = $name.':'.trim($value).($is_sig ? '' : "\r\n"); - // no break - case 'simple': - // Nothing to do - } - $this->addToHeaderHash($header); - } - - protected function canonicalizeBody($string) - { - $len = \strlen($string); - $canon = ''; - $method = ('relaxed' == $this->bodyCanon); - for ($i = 0; $i < $len; ++$i) { - if ($this->bodyCanonIgnoreStart > 0) { - --$this->bodyCanonIgnoreStart; - continue; - } - switch ($string[$i]) { - case "\r": - $this->bodyCanonLastChar = "\r"; - break; - case "\n": - if ("\r" == $this->bodyCanonLastChar) { - if ($method) { - $this->bodyCanonSpace = false; - } - if ('' == $this->bodyCanonLine) { - ++$this->bodyCanonEmptyCounter; - } else { - $this->bodyCanonLine = ''; - $canon .= "\r\n"; - } - } else { - // Wooops Error - // todo handle it but should never happen - } - break; - case ' ': - case "\t": - if ($method) { - $this->bodyCanonSpace = true; - break; - } - // no break - default: - if ($this->bodyCanonEmptyCounter > 0) { - $canon .= str_repeat("\r\n", $this->bodyCanonEmptyCounter); - $this->bodyCanonEmptyCounter = 0; - } - if ($this->bodyCanonSpace) { - $this->bodyCanonLine .= ' '; - $canon .= ' '; - $this->bodyCanonSpace = false; - } - $this->bodyCanonLine .= $string[$i]; - $canon .= $string[$i]; - } - } - $this->addToBodyHash($canon); - } - - protected function endOfBody() - { - // Add trailing Line return if last line is non empty - if (\strlen($this->bodyCanonLine) > 0) { - $this->addToBodyHash("\r\n"); - } - $this->bodyHash = hash_final($this->bodyHashHandler, true); - } - - private function addToBodyHash($string) - { - $len = \strlen($string); - if ($len > ($new_len = ($this->maxLen - $this->bodyLen))) { - $string = substr($string, 0, $new_len); - $len = $new_len; - } - hash_update($this->bodyHashHandler, $string); - $this->bodyLen += $len; - } - - private function addToHeaderHash($header) - { - if ($this->debugHeaders) { - $this->debugHeadersData[] = trim($header ?? ''); - } - $this->headerCanonData .= $header; - } - - /** - * @throws Swift_SwiftException - * - * @return string - */ - private function getEncryptedHash() - { - $signature = ''; - switch ($this->hashAlgorithm) { - case 'rsa-sha1': - $algorithm = OPENSSL_ALGO_SHA1; - break; - case 'rsa-sha256': - $algorithm = OPENSSL_ALGO_SHA256; - break; - } - $pkeyId = openssl_get_privatekey($this->privateKey, $this->passphrase); - if (!$pkeyId) { - throw new Swift_SwiftException('Unable to load DKIM Private Key ['.openssl_error_string().']'); - } - if (openssl_sign($this->headerCanonData, $signature, $pkeyId, $algorithm)) { - return $signature; - } - throw new Swift_SwiftException('Unable to sign DKIM Hash ['.openssl_error_string().']'); - } + /** + * PrivateKey. + * + * @var string + */ + protected $privateKey; + + /** + * DomainName. + * + * @var string + */ + protected $domainName; + + /** + * Selector. + * + * @var string + */ + protected $selector; + + private $passphrase = ''; + + /** + * Hash algorithm used. + * + * @see RFC6376 3.3: Signers MUST implement and SHOULD sign using rsa-sha256. + * + * @var string + */ + protected $hashAlgorithm = 'rsa-sha256'; + + /** + * Body canon method. + * + * @var string + */ + protected $bodyCanon = 'simple'; + + /** + * Header canon method. + * + * @var string + */ + protected $headerCanon = 'simple'; + + /** + * Headers not being signed. + * + * @var array + */ + protected $ignoredHeaders = ['return-path' => true]; + + /** + * Signer identity. + * + * @var string + */ + protected $signerIdentity; + + /** + * BodyLength. + * + * @var int + */ + protected $bodyLen = 0; + + /** + * Maximum signedLen. + * + * @var int + */ + protected $maxLen = PHP_INT_MAX; + + /** + * Embbed bodyLen in signature. + * + * @var bool + */ + protected $showLen = false; + + /** + * When the signature has been applied (true means time()), false means not embedded. + * + * @var mixed + */ + protected $signatureTimestamp = true; + + /** + * When will the signature expires false means not embedded, if sigTimestamp is auto + * Expiration is relative, otherwise it's absolute. + * + * @var int + */ + protected $signatureExpiration = false; + + /** + * Must we embed signed headers? + * + * @var bool + */ + protected $debugHeaders = false; + + // work variables + /** + * Headers used to generate hash. + * + * @var array + */ + protected $signedHeaders = []; + + /** + * If debugHeaders is set store debugData here. + * + * @var string[] + */ + private $debugHeadersData = []; + + /** + * Stores the bodyHash. + * + * @var string + */ + private $bodyHash = ''; + + /** + * Stores the signature header. + * + * @var Swift_Mime_Headers_ParameterizedHeader + */ + protected $dkimHeader; + + private $bodyHashHandler; + + private $headerHash; + + private $headerCanonData = ''; + + private $bodyCanonEmptyCounter = 0; + + private $bodyCanonIgnoreStart = 2; + + private $bodyCanonSpace = false; + + private $bodyCanonLastChar = null; + + private $bodyCanonLine = ''; + + private $bound = []; + + /** + * Constructor. + * + * @param string $privateKey + * @param string $domainName + * @param string $selector + * @param string $passphrase + */ + public function __construct($privateKey, $domainName, $selector, $passphrase = '') + { + $this->privateKey = $privateKey; + $this->domainName = $domainName; + $this->signerIdentity = '@'.$domainName; + $this->selector = $selector; + $this->passphrase = $passphrase; + } + + /** + * Reset the Signer. + * + * @see Swift_Signer::reset() + */ + public function reset() + { + $this->headerHash = null; + $this->signedHeaders = []; + $this->bodyHash = null; + $this->bodyHashHandler = null; + $this->bodyCanonIgnoreStart = 2; + $this->bodyCanonEmptyCounter = 0; + $this->bodyCanonLastChar = null; + $this->bodyCanonSpace = false; + } + + /** + * Writes $bytes to the end of the stream. + * + * Writing may not happen immediately if the stream chooses to buffer. If + * you want to write these bytes with immediate effect, call {@link commit()} + * after calling write(). + * + * This method returns the sequence ID of the write (i.e. 1 for first, 2 for + * second, etc etc). + * + * @param string $bytes + * + * @return int + * + * @throws Swift_IoException + */ + // TODO fix return + public function write($bytes) + { + $this->canonicalizeBody($bytes); + foreach ($this->bound as $is) { + $is->write($bytes); + } + } + + /** + * For any bytes that are currently buffered inside the stream, force them + * off the buffer. + */ + public function commit() + { + // Nothing to do + return; + } + + /** + * Attach $is to this stream. + * + * The stream acts as an observer, receiving all data that is written. + * All {@link write()} and {@link flushBuffers()} operations will be mirrored. + */ + public function bind(Swift_InputByteStream $is) + { + // Don't have to mirror anything + $this->bound[] = $is; + + return; + } + + /** + * Remove an already bound stream. + * + * If $is is not bound, no errors will be raised. + * If the stream currently has any buffered data it will be written to $is + * before unbinding occurs. + */ + public function unbind(Swift_InputByteStream $is) + { + // Don't have to mirror anything + foreach ($this->bound as $k => $stream) { + if ($stream === $is) { + unset($this->bound[$k]); + + return; + } + } + } + + /** + * Flush the contents of the stream (empty it) and set the internal pointer + * to the beginning. + * + * @throws Swift_IoException + */ + public function flushBuffers() + { + $this->reset(); + } + + /** + * Set hash_algorithm, must be one of rsa-sha256 | rsa-sha1. + * + * @param string $hash 'rsa-sha1' or 'rsa-sha256' + * + * @throws Swift_SwiftException + * + * @return $this + */ + public function setHashAlgorithm($hash) + { + switch ($hash) { + case 'rsa-sha1': + $this->hashAlgorithm = 'rsa-sha1'; + break; + case 'rsa-sha256': + $this->hashAlgorithm = 'rsa-sha256'; + if (!\defined('OPENSSL_ALGO_SHA256')) { + throw new Swift_SwiftException('Unable to set sha256 as it is not supported by OpenSSL.'); + } + break; + default: + throw new Swift_SwiftException('Unable to set the hash algorithm, must be one of rsa-sha1 or rsa-sha256 (%s given).', $hash); + } + + return $this; + } + + /** + * Set the body canonicalization algorithm. + * + * @param string $canon + * + * @return $this + */ + public function setBodyCanon($canon) + { + if ('relaxed' == $canon) { + $this->bodyCanon = 'relaxed'; + } else { + $this->bodyCanon = 'simple'; + } + + return $this; + } + + /** + * Set the header canonicalization algorithm. + * + * @param string $canon + * + * @return $this + */ + public function setHeaderCanon($canon) + { + if ('relaxed' == $canon) { + $this->headerCanon = 'relaxed'; + } else { + $this->headerCanon = 'simple'; + } + + return $this; + } + + /** + * Set the signer identity. + * + * @param string $identity + * + * @return $this + */ + public function setSignerIdentity($identity) + { + $this->signerIdentity = $identity; + + return $this; + } + + /** + * Set the length of the body to sign. + * + * @param mixed $len (bool or int) + * + * @return $this + */ + public function setBodySignedLen($len) + { + if (true === $len) { + $this->showLen = true; + $this->maxLen = PHP_INT_MAX; + } elseif (false === $len) { + $this->showLen = false; + $this->maxLen = PHP_INT_MAX; + } else { + $this->showLen = true; + $this->maxLen = (int) $len; + } + + return $this; + } + + /** + * Set the signature timestamp. + * + * @param int $time A timestamp + * + * @return $this + */ + public function setSignatureTimestamp($time) + { + $this->signatureTimestamp = $time; + + return $this; + } + + /** + * Set the signature expiration timestamp. + * + * @param int $time A timestamp + * + * @return $this + */ + public function setSignatureExpiration($time) + { + $this->signatureExpiration = $time; + + return $this; + } + + /** + * Enable / disable the DebugHeaders. + * + * @param bool $debug + * + * @return Swift_Signers_DKIMSigner + */ + public function setDebugHeaders($debug) + { + $this->debugHeaders = (bool) $debug; + + return $this; + } + + /** + * Start Body. + */ + public function startBody() + { + // Init + switch ($this->hashAlgorithm) { + case 'rsa-sha256': + $this->bodyHashHandler = hash_init('sha256'); + break; + case 'rsa-sha1': + $this->bodyHashHandler = hash_init('sha1'); + break; + } + $this->bodyCanonLine = ''; + } + + /** + * End Body. + */ + public function endBody() + { + $this->endOfBody(); + } + + /** + * Returns the list of Headers Tampered by this plugin. + * + * @return array + */ + public function getAlteredHeaders() + { + if ($this->debugHeaders) { + return ['DKIM-Signature', 'X-DebugHash']; + } else { + return ['DKIM-Signature']; + } + } + + /** + * Adds an ignored Header. + * + * @param string $header_name + * + * @return Swift_Signers_DKIMSigner + */ + public function ignoreHeader($header_name) + { + $this->ignoredHeaders[strtolower($header_name ?? '')] = true; + + return $this; + } + + /** + * Set the headers to sign. + * + * @return Swift_Signers_DKIMSigner + */ + public function setHeaders(Swift_Mime_SimpleHeaderSet $headers) + { + $this->headerCanonData = ''; + // Loop through Headers + $listHeaders = $headers->listAll(); + foreach ($listHeaders as $hName) { + // Check if we need to ignore Header + if (!isset($this->ignoredHeaders[strtolower($hName ?? '')])) { + if ($headers->has($hName)) { + $tmp = $headers->getAll($hName); + foreach ($tmp as $header) { + if ('' != $header->getFieldBody()) { + $this->addHeader($header->toString()); + $this->signedHeaders[] = $header->getFieldName(); + } + } + } + } + } + + return $this; + } + + /** + * Add the signature to the given Headers. + * + * @return Swift_Signers_DKIMSigner + */ + public function addSignature(Swift_Mime_SimpleHeaderSet $headers) + { + // Prepare the DKIM-Signature + $params = ['v' => '1', 'a' => $this->hashAlgorithm, 'bh' => base64_encode($this->bodyHash ?? ''), 'd' => $this->domainName, 'h' => implode(': ', $this->signedHeaders), 'i' => $this->signerIdentity, 's' => $this->selector]; + if ('simple' != $this->bodyCanon) { + $params['c'] = $this->headerCanon.'/'.$this->bodyCanon; + } elseif ('simple' != $this->headerCanon) { + $params['c'] = $this->headerCanon; + } + if ($this->showLen) { + $params['l'] = $this->bodyLen; + } + if (true === $this->signatureTimestamp) { + $params['t'] = time(); + if (false !== $this->signatureExpiration) { + $params['x'] = $params['t'] + $this->signatureExpiration; + } + } else { + if (false !== $this->signatureTimestamp) { + $params['t'] = $this->signatureTimestamp; + } + if (false !== $this->signatureExpiration) { + $params['x'] = $this->signatureExpiration; + } + } + if ($this->debugHeaders) { + $params['z'] = implode('|', $this->debugHeadersData); + } + $string = ''; + foreach ($params as $k => $v) { + $string .= $k.'='.$v.'; '; + } + $string = trim($string); + $headers->addTextHeader('DKIM-Signature', $string); + // Add the last DKIM-Signature + $tmp = $headers->getAll('DKIM-Signature'); + $this->dkimHeader = end($tmp); + $this->addHeader(trim($this->dkimHeader->toString() ?? '')."\r\n b=", true); + if ($this->debugHeaders) { + $headers->addTextHeader('X-DebugHash', base64_encode($this->headerHash ?? '')); + } + $this->dkimHeader->setValue($string.' b='.trim(chunk_split(base64_encode($this->getEncryptedHash() ?? ''), 73, ' '))); + + return $this; + } + + /* Private helpers */ + + protected function addHeader($header, $is_sig = false) + { + switch ($this->headerCanon) { + case 'relaxed': + // Prepare Header and cascade + $exploded = explode(':', $header, 2); + $name = strtolower(trim($exploded[0])); + $value = str_replace("\r\n", '', $exploded[1]); + $value = preg_replace("/[ \t][ \t]+/", ' ', $value); + $header = $name.':'.trim($value).($is_sig ? '' : "\r\n"); + // no break + case 'simple': + // Nothing to do + } + $this->addToHeaderHash($header); + } + + protected function canonicalizeBody($string) + { + $len = \strlen($string); + $canon = ''; + $method = ('relaxed' == $this->bodyCanon); + for ($i = 0; $i < $len; ++$i) { + if ($this->bodyCanonIgnoreStart > 0) { + --$this->bodyCanonIgnoreStart; + continue; + } + switch ($string[$i]) { + case "\r": + $this->bodyCanonLastChar = "\r"; + break; + case "\n": + if ("\r" == $this->bodyCanonLastChar) { + if ($method) { + $this->bodyCanonSpace = false; + } + if ('' == $this->bodyCanonLine) { + ++$this->bodyCanonEmptyCounter; + } else { + $this->bodyCanonLine = ''; + $canon .= "\r\n"; + } + } else { + // Wooops Error + // todo handle it but should never happen + } + break; + case ' ': + case "\t": + if ($method) { + $this->bodyCanonSpace = true; + break; + } + // no break + default: + if ($this->bodyCanonEmptyCounter > 0) { + $canon .= str_repeat("\r\n", $this->bodyCanonEmptyCounter); + $this->bodyCanonEmptyCounter = 0; + } + if ($this->bodyCanonSpace) { + $this->bodyCanonLine .= ' '; + $canon .= ' '; + $this->bodyCanonSpace = false; + } + $this->bodyCanonLine .= $string[$i]; + $canon .= $string[$i]; + } + } + $this->addToBodyHash($canon); + } + + protected function endOfBody() + { + // Add trailing Line return if last line is non empty + if (\strlen($this->bodyCanonLine) > 0) { + $this->addToBodyHash("\r\n"); + } + $this->bodyHash = hash_final($this->bodyHashHandler, true); + } + + private function addToBodyHash($string) + { + $len = \strlen($string); + if ($len > ($new_len = ($this->maxLen - $this->bodyLen))) { + $string = substr($string, 0, $new_len); + $len = $new_len; + } + hash_update($this->bodyHashHandler, $string); + $this->bodyLen += $len; + } + + private function addToHeaderHash($header) + { + if ($this->debugHeaders) { + $this->debugHeadersData[] = trim($header ?? ''); + } + $this->headerCanonData .= $header; + } + + /** + * @throws Swift_SwiftException + * + * @return string + */ + private function getEncryptedHash() + { + $signature = ''; + switch ($this->hashAlgorithm) { + case 'rsa-sha1': + $algorithm = OPENSSL_ALGO_SHA1; + break; + case 'rsa-sha256': + $algorithm = OPENSSL_ALGO_SHA256; + break; + } + $pkeyId = openssl_get_privatekey($this->privateKey, $this->passphrase); + if (!$pkeyId) { + throw new Swift_SwiftException('Unable to load DKIM Private Key ['.openssl_error_string().']'); + } + if (openssl_sign($this->headerCanonData, $signature, $pkeyId, $algorithm)) { + return $signature; + } + throw new Swift_SwiftException('Unable to sign DKIM Hash ['.openssl_error_string().']'); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/DomainKeySigner.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/DomainKeySigner.php index 884996b40eb..5e2b67b6520 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/DomainKeySigner.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/DomainKeySigner.php @@ -15,490 +15,490 @@ */ class Swift_Signers_DomainKeySigner implements Swift_Signers_HeaderSigner { - /** - * PrivateKey. - * - * @var string - */ - protected $privateKey; + /** + * PrivateKey. + * + * @var string + */ + protected $privateKey; - /** - * DomainName. - * - * @var string - */ - protected $domainName; + /** + * DomainName. + * + * @var string + */ + protected $domainName; - /** - * Selector. - * - * @var string - */ - protected $selector; + /** + * Selector. + * + * @var string + */ + protected $selector; - /** - * Hash algorithm used. - * - * @var string - */ - protected $hashAlgorithm = 'rsa-sha1'; + /** + * Hash algorithm used. + * + * @var string + */ + protected $hashAlgorithm = 'rsa-sha1'; - /** - * Canonisation method. - * - * @var string - */ - protected $canon = 'simple'; + /** + * Canonisation method. + * + * @var string + */ + protected $canon = 'simple'; - /** - * Headers not being signed. - * - * @var array - */ - protected $ignoredHeaders = []; + /** + * Headers not being signed. + * + * @var array + */ + protected $ignoredHeaders = []; - /** - * Signer identity. - * - * @var string - */ - protected $signerIdentity; + /** + * Signer identity. + * + * @var string + */ + protected $signerIdentity; - /** - * Must we embed signed headers? - * - * @var bool - */ - protected $debugHeaders = false; + /** + * Must we embed signed headers? + * + * @var bool + */ + protected $debugHeaders = false; - // work variables - /** - * Headers used to generate hash. - * - * @var array - */ - private $signedHeaders = []; + // work variables + /** + * Headers used to generate hash. + * + * @var array + */ + private $signedHeaders = []; - /** - * Stores the signature header. - * - * @var Swift_Mime_Headers_ParameterizedHeader - */ - protected $domainKeyHeader; + /** + * Stores the signature header. + * + * @var Swift_Mime_Headers_ParameterizedHeader + */ + protected $domainKeyHeader; - /** - * Hash Handler. - * - * @var resource|null - */ - private $hashHandler; + /** + * Hash Handler. + * + * @var resource|null + */ + private $hashHandler; - private $canonData = ''; + private $canonData = ''; - private $bodyCanonEmptyCounter = 0; + private $bodyCanonEmptyCounter = 0; - private $bodyCanonIgnoreStart = 2; + private $bodyCanonIgnoreStart = 2; - private $bodyCanonSpace = false; + private $bodyCanonSpace = false; - private $bodyCanonLastChar = null; + private $bodyCanonLastChar = null; - private $bodyCanonLine = ''; + private $bodyCanonLine = ''; - private $bound = []; + private $bound = []; - /** - * Constructor. - * - * @param string $privateKey - * @param string $domainName - * @param string $selector - */ - public function __construct($privateKey, $domainName, $selector) - { - $this->privateKey = $privateKey; - $this->domainName = $domainName; - $this->signerIdentity = '@'.$domainName; - $this->selector = $selector; - } + /** + * Constructor. + * + * @param string $privateKey + * @param string $domainName + * @param string $selector + */ + public function __construct($privateKey, $domainName, $selector) + { + $this->privateKey = $privateKey; + $this->domainName = $domainName; + $this->signerIdentity = '@'.$domainName; + $this->selector = $selector; + } - /** - * Resets internal states. - * - * @return $this - */ - public function reset() - { - $this->hashHandler = null; - $this->bodyCanonIgnoreStart = 2; - $this->bodyCanonEmptyCounter = 0; - $this->bodyCanonLastChar = null; - $this->bodyCanonSpace = false; + /** + * Resets internal states. + * + * @return $this + */ + public function reset() + { + $this->hashHandler = null; + $this->bodyCanonIgnoreStart = 2; + $this->bodyCanonEmptyCounter = 0; + $this->bodyCanonLastChar = null; + $this->bodyCanonSpace = false; - return $this; - } + return $this; + } - /** - * Writes $bytes to the end of the stream. - * - * Writing may not happen immediately if the stream chooses to buffer. If - * you want to write these bytes with immediate effect, call {@link commit()} - * after calling write(). - * - * This method returns the sequence ID of the write (i.e. 1 for first, 2 for - * second, etc etc). - * - * @param string $bytes - * - * @return int - * - * @throws Swift_IoException - * - * @return $this - */ - public function write($bytes) - { - $this->canonicalizeBody($bytes); - foreach ($this->bound as $is) { - $is->write($bytes); - } + /** + * Writes $bytes to the end of the stream. + * + * Writing may not happen immediately if the stream chooses to buffer. If + * you want to write these bytes with immediate effect, call {@link commit()} + * after calling write(). + * + * This method returns the sequence ID of the write (i.e. 1 for first, 2 for + * second, etc etc). + * + * @param string $bytes + * + * @return int + * + * @throws Swift_IoException + * + * @return $this + */ + public function write($bytes) + { + $this->canonicalizeBody($bytes); + foreach ($this->bound as $is) { + $is->write($bytes); + } - return $this; - } + return $this; + } - /** - * For any bytes that are currently buffered inside the stream, force them - * off the buffer. - * - * @throws Swift_IoException - * - * @return $this - */ - public function commit() - { - // Nothing to do - return $this; - } + /** + * For any bytes that are currently buffered inside the stream, force them + * off the buffer. + * + * @throws Swift_IoException + * + * @return $this + */ + public function commit() + { + // Nothing to do + return $this; + } - /** - * Attach $is to this stream. - * - * The stream acts as an observer, receiving all data that is written. - * All {@link write()} and {@link flushBuffers()} operations will be mirrored. - * - * @return $this - */ - public function bind(Swift_InputByteStream $is) - { - // Don't have to mirror anything - $this->bound[] = $is; + /** + * Attach $is to this stream. + * + * The stream acts as an observer, receiving all data that is written. + * All {@link write()} and {@link flushBuffers()} operations will be mirrored. + * + * @return $this + */ + public function bind(Swift_InputByteStream $is) + { + // Don't have to mirror anything + $this->bound[] = $is; - return $this; - } + return $this; + } - /** - * Remove an already bound stream. - * - * If $is is not bound, no errors will be raised. - * If the stream currently has any buffered data it will be written to $is - * before unbinding occurs. - * - * @return $this - */ - public function unbind(Swift_InputByteStream $is) - { - // Don't have to mirror anything - foreach ($this->bound as $k => $stream) { - if ($stream === $is) { - unset($this->bound[$k]); + /** + * Remove an already bound stream. + * + * If $is is not bound, no errors will be raised. + * If the stream currently has any buffered data it will be written to $is + * before unbinding occurs. + * + * @return $this + */ + public function unbind(Swift_InputByteStream $is) + { + // Don't have to mirror anything + foreach ($this->bound as $k => $stream) { + if ($stream === $is) { + unset($this->bound[$k]); - break; - } - } + break; + } + } - return $this; - } + return $this; + } - /** - * Flush the contents of the stream (empty it) and set the internal pointer - * to the beginning. - * - * @throws Swift_IoException - * - * @return $this - */ - public function flushBuffers() - { - $this->reset(); + /** + * Flush the contents of the stream (empty it) and set the internal pointer + * to the beginning. + * + * @throws Swift_IoException + * + * @return $this + */ + public function flushBuffers() + { + $this->reset(); - return $this; - } + return $this; + } - /** - * Set hash_algorithm, must be one of rsa-sha256 | rsa-sha1 defaults to rsa-sha256. - * - * @param string $hash - * - * @return $this - */ - public function setHashAlgorithm($hash) - { - $this->hashAlgorithm = 'rsa-sha1'; + /** + * Set hash_algorithm, must be one of rsa-sha256 | rsa-sha1 defaults to rsa-sha256. + * + * @param string $hash + * + * @return $this + */ + public function setHashAlgorithm($hash) + { + $this->hashAlgorithm = 'rsa-sha1'; - return $this; - } + return $this; + } - /** - * Set the canonicalization algorithm. - * - * @param string $canon simple | nofws defaults to simple - * - * @return $this - */ - public function setCanon($canon) - { - if ('nofws' == $canon) { - $this->canon = 'nofws'; - } else { - $this->canon = 'simple'; - } + /** + * Set the canonicalization algorithm. + * + * @param string $canon simple | nofws defaults to simple + * + * @return $this + */ + public function setCanon($canon) + { + if ('nofws' == $canon) { + $this->canon = 'nofws'; + } else { + $this->canon = 'simple'; + } - return $this; - } + return $this; + } - /** - * Set the signer identity. - * - * @param string $identity - * - * @return $this - */ - public function setSignerIdentity($identity) - { - $this->signerIdentity = $identity; + /** + * Set the signer identity. + * + * @param string $identity + * + * @return $this + */ + public function setSignerIdentity($identity) + { + $this->signerIdentity = $identity; - return $this; - } + return $this; + } - /** - * Enable / disable the DebugHeaders. - * - * @param bool $debug - * - * @return $this - */ - public function setDebugHeaders($debug) - { - $this->debugHeaders = (bool) $debug; + /** + * Enable / disable the DebugHeaders. + * + * @param bool $debug + * + * @return $this + */ + public function setDebugHeaders($debug) + { + $this->debugHeaders = (bool) $debug; - return $this; - } + return $this; + } - /** - * Start Body. - */ - public function startBody() - { - } + /** + * Start Body. + */ + public function startBody() + { + } - /** - * End Body. - */ - public function endBody() - { - $this->endOfBody(); - } + /** + * End Body. + */ + public function endBody() + { + $this->endOfBody(); + } - /** - * Returns the list of Headers Tampered by this plugin. - * - * @return array - */ - public function getAlteredHeaders() - { - if ($this->debugHeaders) { - return ['DomainKey-Signature', 'X-DebugHash']; - } + /** + * Returns the list of Headers Tampered by this plugin. + * + * @return array + */ + public function getAlteredHeaders() + { + if ($this->debugHeaders) { + return ['DomainKey-Signature', 'X-DebugHash']; + } - return ['DomainKey-Signature']; - } + return ['DomainKey-Signature']; + } - /** - * Adds an ignored Header. - * - * @param string $header_name - * - * @return $this - */ - public function ignoreHeader($header_name) - { - $this->ignoredHeaders[strtolower($header_name ?? '')] = true; + /** + * Adds an ignored Header. + * + * @param string $header_name + * + * @return $this + */ + public function ignoreHeader($header_name) + { + $this->ignoredHeaders[strtolower($header_name ?? '')] = true; - return $this; - } + return $this; + } - /** - * Set the headers to sign. - * - * @return $this - */ - public function setHeaders(Swift_Mime_SimpleHeaderSet $headers) - { - $this->startHash(); - $this->canonData = ''; - // Loop through Headers - $listHeaders = $headers->listAll(); - foreach ($listHeaders as $hName) { - // Check if we need to ignore Header - if (!isset($this->ignoredHeaders[strtolower($hName ?? '')])) { - if ($headers->has($hName)) { - $tmp = $headers->getAll($hName); - foreach ($tmp as $header) { - if ('' != $header->getFieldBody()) { - $this->addHeader($header->toString()); - $this->signedHeaders[] = $header->getFieldName(); - } - } - } - } - } - $this->endOfHeaders(); + /** + * Set the headers to sign. + * + * @return $this + */ + public function setHeaders(Swift_Mime_SimpleHeaderSet $headers) + { + $this->startHash(); + $this->canonData = ''; + // Loop through Headers + $listHeaders = $headers->listAll(); + foreach ($listHeaders as $hName) { + // Check if we need to ignore Header + if (!isset($this->ignoredHeaders[strtolower($hName ?? '')])) { + if ($headers->has($hName)) { + $tmp = $headers->getAll($hName); + foreach ($tmp as $header) { + if ('' != $header->getFieldBody()) { + $this->addHeader($header->toString()); + $this->signedHeaders[] = $header->getFieldName(); + } + } + } + } + } + $this->endOfHeaders(); - return $this; - } + return $this; + } - /** - * Add the signature to the given Headers. - * - * @return $this - */ - public function addSignature(Swift_Mime_SimpleHeaderSet $headers) - { - // Prepare the DomainKey-Signature Header - $params = ['a' => $this->hashAlgorithm, 'b' => chunk_split(base64_encode($this->getEncryptedHash() ?? ''), 73, ' '), 'c' => $this->canon, 'd' => $this->domainName, 'h' => implode(': ', $this->signedHeaders), 'q' => 'dns', 's' => $this->selector]; - $string = ''; - foreach ($params as $k => $v) { - $string .= $k.'='.$v.'; '; - } - $string = trim($string); - $headers->addTextHeader('DomainKey-Signature', $string); + /** + * Add the signature to the given Headers. + * + * @return $this + */ + public function addSignature(Swift_Mime_SimpleHeaderSet $headers) + { + // Prepare the DomainKey-Signature Header + $params = ['a' => $this->hashAlgorithm, 'b' => chunk_split(base64_encode($this->getEncryptedHash() ?? ''), 73, ' '), 'c' => $this->canon, 'd' => $this->domainName, 'h' => implode(': ', $this->signedHeaders), 'q' => 'dns', 's' => $this->selector]; + $string = ''; + foreach ($params as $k => $v) { + $string .= $k.'='.$v.'; '; + } + $string = trim($string); + $headers->addTextHeader('DomainKey-Signature', $string); - return $this; - } + return $this; + } - /* Private helpers */ + /* Private helpers */ - protected function addHeader($header) - { - switch ($this->canon) { - case 'nofws': - // Prepare Header and cascade - $exploded = explode(':', $header, 2); - $name = strtolower(trim($exploded[0])); - $value = str_replace("\r\n", '', $exploded[1]); - $value = preg_replace("/[ \t][ \t]+/", ' ', $value); - $header = $name.':'.trim($value)."\r\n"; - // no break - case 'simple': - // Nothing to do - } - $this->addToHash($header); - } + protected function addHeader($header) + { + switch ($this->canon) { + case 'nofws': + // Prepare Header and cascade + $exploded = explode(':', $header, 2); + $name = strtolower(trim($exploded[0])); + $value = str_replace("\r\n", '', $exploded[1]); + $value = preg_replace("/[ \t][ \t]+/", ' ', $value); + $header = $name.':'.trim($value)."\r\n"; + // no break + case 'simple': + // Nothing to do + } + $this->addToHash($header); + } - protected function endOfHeaders() - { - $this->bodyCanonEmptyCounter = 1; - } + protected function endOfHeaders() + { + $this->bodyCanonEmptyCounter = 1; + } - protected function canonicalizeBody($string) - { - $len = \strlen($string); - $canon = ''; - $nofws = ('nofws' == $this->canon); - for ($i = 0; $i < $len; ++$i) { - if ($this->bodyCanonIgnoreStart > 0) { - --$this->bodyCanonIgnoreStart; - continue; - } - switch ($string[$i]) { - case "\r": - $this->bodyCanonLastChar = "\r"; - break; - case "\n": - if ("\r" == $this->bodyCanonLastChar) { - if ($nofws) { - $this->bodyCanonSpace = false; - } - if ('' == $this->bodyCanonLine) { - ++$this->bodyCanonEmptyCounter; - } else { - $this->bodyCanonLine = ''; - $canon .= "\r\n"; - } - } else { - // Wooops Error - throw new Swift_SwiftException('Invalid new line sequence in mail found \n without preceding \r'); - } - break; - case ' ': - case "\t": - case "\x09": //HTAB - if ($nofws) { - $this->bodyCanonSpace = true; - break; - } - // no break - default: - if ($this->bodyCanonEmptyCounter > 0) { - $canon .= str_repeat("\r\n", $this->bodyCanonEmptyCounter); - $this->bodyCanonEmptyCounter = 0; - } - $this->bodyCanonLine .= $string[$i]; - $canon .= $string[$i]; - } - } - $this->addToHash($canon); - } + protected function canonicalizeBody($string) + { + $len = \strlen($string); + $canon = ''; + $nofws = ('nofws' == $this->canon); + for ($i = 0; $i < $len; ++$i) { + if ($this->bodyCanonIgnoreStart > 0) { + --$this->bodyCanonIgnoreStart; + continue; + } + switch ($string[$i]) { + case "\r": + $this->bodyCanonLastChar = "\r"; + break; + case "\n": + if ("\r" == $this->bodyCanonLastChar) { + if ($nofws) { + $this->bodyCanonSpace = false; + } + if ('' == $this->bodyCanonLine) { + ++$this->bodyCanonEmptyCounter; + } else { + $this->bodyCanonLine = ''; + $canon .= "\r\n"; + } + } else { + // Wooops Error + throw new Swift_SwiftException('Invalid new line sequence in mail found \n without preceding \r'); + } + break; + case ' ': + case "\t": + case "\x09": //HTAB + if ($nofws) { + $this->bodyCanonSpace = true; + break; + } + // no break + default: + if ($this->bodyCanonEmptyCounter > 0) { + $canon .= str_repeat("\r\n", $this->bodyCanonEmptyCounter); + $this->bodyCanonEmptyCounter = 0; + } + $this->bodyCanonLine .= $string[$i]; + $canon .= $string[$i]; + } + } + $this->addToHash($canon); + } - protected function endOfBody() - { - if (\strlen($this->bodyCanonLine) > 0) { - $this->addToHash("\r\n"); - } - } + protected function endOfBody() + { + if (\strlen($this->bodyCanonLine) > 0) { + $this->addToHash("\r\n"); + } + } - private function addToHash($string) - { - $this->canonData .= $string; - hash_update($this->hashHandler, $string); - } + private function addToHash($string) + { + $this->canonData .= $string; + hash_update($this->hashHandler, $string); + } - private function startHash() - { - // Init - switch ($this->hashAlgorithm) { - case 'rsa-sha1': - $this->hashHandler = hash_init('sha1'); - break; - } - $this->bodyCanonLine = ''; - } + private function startHash() + { + // Init + switch ($this->hashAlgorithm) { + case 'rsa-sha1': + $this->hashHandler = hash_init('sha1'); + break; + } + $this->bodyCanonLine = ''; + } - /** - * @throws Swift_SwiftException - * - * @return string - */ - private function getEncryptedHash() - { - $signature = ''; - $pkeyId = openssl_get_privatekey($this->privateKey); - if (!$pkeyId) { - throw new Swift_SwiftException('Unable to load DomainKey Private Key ['.openssl_error_string().']'); - } - if (openssl_sign($this->canonData, $signature, $pkeyId, OPENSSL_ALGO_SHA1)) { - return $signature; - } - throw new Swift_SwiftException('Unable to sign DomainKey Hash ['.openssl_error_string().']'); - } + /** + * @throws Swift_SwiftException + * + * @return string + */ + private function getEncryptedHash() + { + $signature = ''; + $pkeyId = openssl_get_privatekey($this->privateKey); + if (!$pkeyId) { + throw new Swift_SwiftException('Unable to load DomainKey Private Key ['.openssl_error_string().']'); + } + if (openssl_sign($this->canonData, $signature, $pkeyId, OPENSSL_ALGO_SHA1)) { + return $signature; + } + throw new Swift_SwiftException('Unable to sign DomainKey Hash ['.openssl_error_string().']'); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/HeaderSigner.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/HeaderSigner.php index 94136b94d85..6f5c20923dc 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/HeaderSigner.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/HeaderSigner.php @@ -15,47 +15,47 @@ */ interface Swift_Signers_HeaderSigner extends Swift_Signer, Swift_InputByteStream { - /** - * Exclude an header from the signed headers. - * - * @param string $header_name - * - * @return self - */ - public function ignoreHeader($header_name); + /** + * Exclude an header from the signed headers. + * + * @param string $header_name + * + * @return self + */ + public function ignoreHeader($header_name); - /** - * Prepare the Signer to get a new Body. - * - * @return self - */ - public function startBody(); + /** + * Prepare the Signer to get a new Body. + * + * @return self + */ + public function startBody(); - /** - * Give the signal that the body has finished streaming. - * - * @return self - */ - public function endBody(); + /** + * Give the signal that the body has finished streaming. + * + * @return self + */ + public function endBody(); - /** - * Give the headers already given. - * - * @return self - */ - public function setHeaders(Swift_Mime_SimpleHeaderSet $headers); + /** + * Give the headers already given. + * + * @return self + */ + public function setHeaders(Swift_Mime_SimpleHeaderSet $headers); - /** - * Add the header(s) to the headerSet. - * - * @return self - */ - public function addSignature(Swift_Mime_SimpleHeaderSet $headers); + /** + * Add the header(s) to the headerSet. + * + * @return self + */ + public function addSignature(Swift_Mime_SimpleHeaderSet $headers); - /** - * Return the list of header a signer might tamper. - * - * @return array - */ - public function getAlteredHeaders(); + /** + * Return the list of header a signer might tamper. + * + * @return array + */ + public function getAlteredHeaders(); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/OpenDKIMSigner.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/OpenDKIMSigner.php index fb0504dafa7..520bcc15e8b 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/OpenDKIMSigner.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/OpenDKIMSigner.php @@ -18,166 +18,166 @@ */ class Swift_Signers_OpenDKIMSigner extends Swift_Signers_DKIMSigner { - private $peclLoaded = false; + private $peclLoaded = false; - private $dkimHandler = null; + private $dkimHandler = null; - private $dropFirstLF = true; + private $dropFirstLF = true; - const CANON_RELAXED = 1; - const CANON_SIMPLE = 2; - const SIG_RSA_SHA1 = 3; - const SIG_RSA_SHA256 = 4; + const CANON_RELAXED = 1; + const CANON_SIMPLE = 2; + const SIG_RSA_SHA1 = 3; + const SIG_RSA_SHA256 = 4; - public function __construct($privateKey, $domainName, $selector) - { - if (!\extension_loaded('opendkim')) { - throw new Swift_SwiftException('php-opendkim extension not found'); - } + public function __construct($privateKey, $domainName, $selector) + { + if (!\extension_loaded('opendkim')) { + throw new Swift_SwiftException('php-opendkim extension not found'); + } - $this->peclLoaded = true; + $this->peclLoaded = true; - parent::__construct($privateKey, $domainName, $selector); - } + parent::__construct($privateKey, $domainName, $selector); + } - public function addSignature(Swift_Mime_SimpleHeaderSet $headers) - { - $header = new Swift_Mime_Headers_OpenDKIMHeader('DKIM-Signature'); - $headerVal = $this->dkimHandler->getSignatureHeader(); - if (false === $headerVal || \is_int($headerVal)) { - throw new Swift_SwiftException('OpenDKIM Error: '.$this->dkimHandler->getError()); - } - $header->setValue($headerVal); - $headers->set($header); + public function addSignature(Swift_Mime_SimpleHeaderSet $headers) + { + $header = new Swift_Mime_Headers_OpenDKIMHeader('DKIM-Signature'); + $headerVal = $this->dkimHandler->getSignatureHeader(); + if (false === $headerVal || \is_int($headerVal)) { + throw new Swift_SwiftException('OpenDKIM Error: '.$this->dkimHandler->getError()); + } + $header->setValue($headerVal); + $headers->set($header); - return $this; - } + return $this; + } - public function setHeaders(Swift_Mime_SimpleHeaderSet $headers) - { - $hash = 'rsa-sha1' == $this->hashAlgorithm ? OpenDKIMSign::ALG_RSASHA1 : OpenDKIMSign::ALG_RSASHA256; - $bodyCanon = 'simple' == $this->bodyCanon ? OpenDKIMSign::CANON_SIMPLE : OpenDKIMSign::CANON_RELAXED; - $headerCanon = 'simple' == $this->headerCanon ? OpenDKIMSign::CANON_SIMPLE : OpenDKIMSign::CANON_RELAXED; - $this->dkimHandler = new OpenDKIMSign($this->privateKey, $this->selector, $this->domainName, $headerCanon, $bodyCanon, $hash, -1); - // Hardcode signature Margin for now - $this->dkimHandler->setMargin(78); + public function setHeaders(Swift_Mime_SimpleHeaderSet $headers) + { + $hash = 'rsa-sha1' == $this->hashAlgorithm ? OpenDKIMSign::ALG_RSASHA1 : OpenDKIMSign::ALG_RSASHA256; + $bodyCanon = 'simple' == $this->bodyCanon ? OpenDKIMSign::CANON_SIMPLE : OpenDKIMSign::CANON_RELAXED; + $headerCanon = 'simple' == $this->headerCanon ? OpenDKIMSign::CANON_SIMPLE : OpenDKIMSign::CANON_RELAXED; + $this->dkimHandler = new OpenDKIMSign($this->privateKey, $this->selector, $this->domainName, $headerCanon, $bodyCanon, $hash, -1); + // Hardcode signature Margin for now + $this->dkimHandler->setMargin(78); - if (!is_numeric($this->signatureTimestamp)) { - OpenDKIM::setOption(OpenDKIM::OPTS_FIXEDTIME, time()); - } else { - if (!OpenDKIM::setOption(OpenDKIM::OPTS_FIXEDTIME, $this->signatureTimestamp)) { - throw new Swift_SwiftException('Unable to force signature timestamp ['.openssl_error_string().']'); - } - } - if (isset($this->signerIdentity)) { - $this->dkimHandler->setSigner($this->signerIdentity); - } - $listHeaders = $headers->listAll(); - foreach ($listHeaders as $hName) { - // Check if we need to ignore Header - if (!isset($this->ignoredHeaders[strtolower($hName ?? '')])) { - $tmp = $headers->getAll($hName); - if ($headers->has($hName)) { - foreach ($tmp as $header) { - if ('' != $header->getFieldBody()) { - $htosign = $header->toString(); - $this->dkimHandler->header($htosign); - $this->signedHeaders[] = $header->getFieldName(); - } - } - } - } - } + if (!is_numeric($this->signatureTimestamp)) { + OpenDKIM::setOption(OpenDKIM::OPTS_FIXEDTIME, time()); + } else { + if (!OpenDKIM::setOption(OpenDKIM::OPTS_FIXEDTIME, $this->signatureTimestamp)) { + throw new Swift_SwiftException('Unable to force signature timestamp ['.openssl_error_string().']'); + } + } + if (isset($this->signerIdentity)) { + $this->dkimHandler->setSigner($this->signerIdentity); + } + $listHeaders = $headers->listAll(); + foreach ($listHeaders as $hName) { + // Check if we need to ignore Header + if (!isset($this->ignoredHeaders[strtolower($hName ?? '')])) { + $tmp = $headers->getAll($hName); + if ($headers->has($hName)) { + foreach ($tmp as $header) { + if ('' != $header->getFieldBody()) { + $htosign = $header->toString(); + $this->dkimHandler->header($htosign); + $this->signedHeaders[] = $header->getFieldName(); + } + } + } + } + } - return $this; - } + return $this; + } - public function startBody() - { - if (!$this->peclLoaded) { - return parent::startBody(); - } - $this->dropFirstLF = true; - $this->dkimHandler->eoh(); + public function startBody() + { + if (!$this->peclLoaded) { + return parent::startBody(); + } + $this->dropFirstLF = true; + $this->dkimHandler->eoh(); - return $this; - } + return $this; + } - public function endBody() - { - if (!$this->peclLoaded) { - return parent::endBody(); - } - $this->dkimHandler->eom(); + public function endBody() + { + if (!$this->peclLoaded) { + return parent::endBody(); + } + $this->dkimHandler->eom(); - return $this; - } + return $this; + } - public function reset() - { - $this->dkimHandler = null; - parent::reset(); + public function reset() + { + $this->dkimHandler = null; + parent::reset(); - return $this; - } + return $this; + } - /** - * Set the signature timestamp. - * - * @param int $time - * - * @return $this - */ - public function setSignatureTimestamp($time) - { - $this->signatureTimestamp = $time; + /** + * Set the signature timestamp. + * + * @param int $time + * + * @return $this + */ + public function setSignatureTimestamp($time) + { + $this->signatureTimestamp = $time; - return $this; - } + return $this; + } - /** - * Set the signature expiration timestamp. - * - * @param int $time - * - * @return $this - */ - public function setSignatureExpiration($time) - { - $this->signatureExpiration = $time; + /** + * Set the signature expiration timestamp. + * + * @param int $time + * + * @return $this + */ + public function setSignatureExpiration($time) + { + $this->signatureExpiration = $time; - return $this; - } + return $this; + } - /** - * Enable / disable the DebugHeaders. - * - * @param bool $debug - * - * @return $this - */ - public function setDebugHeaders($debug) - { - $this->debugHeaders = (bool) $debug; + /** + * Enable / disable the DebugHeaders. + * + * @param bool $debug + * + * @return $this + */ + public function setDebugHeaders($debug) + { + $this->debugHeaders = (bool) $debug; - return $this; - } + return $this; + } - // Protected + // Protected - protected function canonicalizeBody($string) - { - if (!$this->peclLoaded) { - return parent::canonicalizeBody($string); - } - if (true === $this->dropFirstLF) { - if ("\r" == $string[0] && "\n" == $string[1]) { - $string = substr($string, 2); - } - } - $this->dropFirstLF = false; - if (\strlen($string)) { - $this->dkimHandler->body($string); - } - } + protected function canonicalizeBody($string) + { + if (!$this->peclLoaded) { + return parent::canonicalizeBody($string); + } + if (true === $this->dropFirstLF) { + if ("\r" == $string[0] && "\n" == $string[1]) { + $string = substr($string, 2); + } + } + $this->dropFirstLF = false; + if (\strlen($string)) { + $this->dkimHandler->body($string); + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/SMimeSigner.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/SMimeSigner.php index e3a489530af..3dd3cd05f04 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/SMimeSigner.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Signers/SMimeSigner.php @@ -17,526 +17,526 @@ */ class Swift_Signers_SMimeSigner implements Swift_Signers_BodySigner { - protected $signCertificate; - protected $signPrivateKey; - protected $encryptCert; - protected $signThenEncrypt = true; - protected $signLevel; - protected $encryptLevel; - protected $signOptions; - protected $encryptOptions; - protected $encryptCipher; - protected $extraCerts = null; - protected $wrapFullMessage = false; - - /** - * @var Swift_StreamFilters_StringReplacementFilterFactory - */ - protected $replacementFactory; - - /** - * @var Swift_Mime_SimpleHeaderFactory - */ - protected $headerFactory; - - /** - * Constructor. - * - * @param string|null $signCertificate - * @param string|null $signPrivateKey - * @param string|null $encryptCertificate - */ - public function __construct($signCertificate = null, $signPrivateKey = null, $encryptCertificate = null) - { - if (null !== $signPrivateKey) { - $this->setSignCertificate($signCertificate, $signPrivateKey); - } - - if (null !== $encryptCertificate) { - $this->setEncryptCertificate($encryptCertificate); - } - - $this->replacementFactory = Swift_DependencyContainer::getInstance() - ->lookup('transport.replacementfactory'); - - $this->signOptions = PKCS7_DETACHED; - $this->encryptCipher = OPENSSL_CIPHER_AES_128_CBC; - } - - /** - * Set the certificate location to use for signing. - * - * @see https://secure.php.net/manual/en/openssl.pkcs7.flags.php - * - * @param string $certificate - * @param string|array $privateKey If the key needs an passphrase use array('file-location', 'passphrase') instead - * @param int $signOptions Bitwise operator options for openssl_pkcs7_sign() - * @param string $extraCerts A file containing intermediate certificates needed by the signing certificate - * - * @return $this - */ - public function setSignCertificate($certificate, $privateKey = null, $signOptions = PKCS7_DETACHED, $extraCerts = null) - { - $this->signCertificate = 'file://'.str_replace('\\', '/', realpath($certificate)); - - if (null !== $privateKey) { - if (\is_array($privateKey)) { - $this->signPrivateKey = $privateKey; - $this->signPrivateKey[0] = 'file://'.str_replace('\\', '/', realpath($privateKey[0])); - } else { - $this->signPrivateKey = 'file://'.str_replace('\\', '/', realpath($privateKey)); - } - } - - $this->signOptions = $signOptions; - $this->extraCerts = $extraCerts ? realpath($extraCerts) : null; - - return $this; - } - - /** - * Set the certificate location to use for encryption. - * - * @see https://secure.php.net/manual/en/openssl.pkcs7.flags.php - * @see https://secure.php.net/manual/en/openssl.ciphers.php - * - * @param string|array $recipientCerts Either an single X.509 certificate, or an assoc array of X.509 certificates. - * @param int $cipher - * - * @return $this - */ - public function setEncryptCertificate($recipientCerts, $cipher = null) - { - if (\is_array($recipientCerts)) { - $this->encryptCert = []; - - foreach ($recipientCerts as $cert) { - $this->encryptCert[] = 'file://'.str_replace('\\', '/', realpath($cert)); - } - } else { - $this->encryptCert = 'file://'.str_replace('\\', '/', realpath($recipientCerts)); - } - - if (null !== $cipher) { - $this->encryptCipher = $cipher; - } - - return $this; - } - - /** - * @return string - */ - public function getSignCertificate() - { - return $this->signCertificate; - } - - /** - * @return string - */ - public function getSignPrivateKey() - { - return $this->signPrivateKey; - } - - /** - * Set perform signing before encryption. - * - * The default is to first sign the message and then encrypt. - * But some older mail clients, namely Microsoft Outlook 2000 will work when the message first encrypted. - * As this goes against the official specs, its recommended to only use 'encryption -> signing' when specifically targeting these 'broken' clients. - * - * @param bool $signThenEncrypt - * - * @return $this - */ - public function setSignThenEncrypt($signThenEncrypt = true) - { - $this->signThenEncrypt = $signThenEncrypt; - - return $this; - } - - /** - * @return bool - */ - public function isSignThenEncrypt() - { - return $this->signThenEncrypt; - } - - /** - * Resets internal states. - * - * @return $this - */ - public function reset() - { - return $this; - } - - /** - * Specify whether to wrap the entire MIME message in the S/MIME message. - * - * According to RFC5751 section 3.1: - * In order to protect outer, non-content-related message header fields - * (for instance, the "Subject", "To", "From", and "Cc" fields), the - * sending client MAY wrap a full MIME message in a message/rfc822 - * wrapper in order to apply S/MIME security services to these header - * fields. It is up to the receiving client to decide how to present - * this "inner" header along with the unprotected "outer" header. - * - * @param bool $wrap - * - * @return $this - */ - public function setWrapFullMessage($wrap) - { - $this->wrapFullMessage = $wrap; - } - - /** - * Change the Swift_Message to apply the signing. - * - * @return $this - */ - public function signMessage(Swift_Message $message) - { - if (null === $this->signCertificate && null === $this->encryptCert) { - return $this; - } - - if ($this->signThenEncrypt) { - $this->smimeSignMessage($message); - $this->smimeEncryptMessage($message); - } else { - $this->smimeEncryptMessage($message); - $this->smimeSignMessage($message); - } - } - - /** - * Return the list of header a signer might tamper. - * - * @return array - */ - public function getAlteredHeaders() - { - return ['Content-Type', 'Content-Transfer-Encoding', 'Content-Disposition']; - } - - /** - * Sign a Swift message. - */ - protected function smimeSignMessage(Swift_Message $message) - { - // If we don't have a certificate we can't sign the message - if (null === $this->signCertificate) { - return; - } - - // Work on a clone of the original message - $signMessage = clone $message; - $signMessage->clearSigners(); - - if ($this->wrapFullMessage) { - // The original message essentially becomes the body of the new - // wrapped message - $signMessage = $this->wrapMimeMessage($signMessage); - } else { - // Only keep header needed to parse the body correctly - $this->clearAllHeaders($signMessage); - $this->copyHeaders( - $message, - $signMessage, - [ - 'Content-Type', - 'Content-Transfer-Encoding', - 'Content-Disposition', - ] - ); - } - - // Copy the cloned message into a temporary file stream - $messageStream = new Swift_ByteStream_TemporaryFileByteStream(); - $signMessage->toByteStream($messageStream); - $messageStream->commit(); - $signedMessageStream = new Swift_ByteStream_TemporaryFileByteStream(); - - // Sign the message using openssl - if (!openssl_pkcs7_sign( - $messageStream->getPath(), - $signedMessageStream->getPath(), - $this->signCertificate, - $this->signPrivateKey, - [], - $this->signOptions, - $this->extraCerts - ) - ) { - throw new Swift_IoException(sprintf('Failed to sign S/Mime message. Error: "%s".', openssl_error_string())); - } - - // Parse the resulting signed message content back into the Swift message - // preserving the original headers - $this->parseSSLOutput($signedMessageStream, $message); - } - - /** - * Encrypt a Swift message. - */ - protected function smimeEncryptMessage(Swift_Message $message) - { - // If we don't have a certificate we can't encrypt the message - if (null === $this->encryptCert) { - return; - } - - // Work on a clone of the original message - $encryptMessage = clone $message; - $encryptMessage->clearSigners(); - - if ($this->wrapFullMessage) { - // The original message essentially becomes the body of the new - // wrapped message - $encryptMessage = $this->wrapMimeMessage($encryptMessage); - } else { - // Only keep header needed to parse the body correctly - $this->clearAllHeaders($encryptMessage); - $this->copyHeaders( - $message, - $encryptMessage, - [ - 'Content-Type', - 'Content-Transfer-Encoding', - 'Content-Disposition', - ] - ); - } - - // Convert the message content (including headers) to a string - // and place it in a temporary file - $messageStream = new Swift_ByteStream_TemporaryFileByteStream(); - $encryptMessage->toByteStream($messageStream); - $messageStream->commit(); - $encryptedMessageStream = new Swift_ByteStream_TemporaryFileByteStream(); - - // Encrypt the message - if (!openssl_pkcs7_encrypt( - $messageStream->getPath(), - $encryptedMessageStream->getPath(), - $this->encryptCert, - [], - 0, - $this->encryptCipher - ) - ) { - throw new Swift_IoException(sprintf('Failed to encrypt S/Mime message. Error: "%s".', openssl_error_string())); - } - - // Parse the resulting signed message content back into the Swift message - // preserving the original headers - $this->parseSSLOutput($encryptedMessageStream, $message); - } - - /** - * Copy named headers from one Swift message to another. - */ - protected function copyHeaders( - Swift_Message $fromMessage, - Swift_Message $toMessage, - array $headers = [] - ) { - foreach ($headers as $header) { - $this->copyHeader($fromMessage, $toMessage, $header); - } - } - - /** - * Copy a single header from one Swift message to another. - * - * @param string $headerName - */ - protected function copyHeader(Swift_Message $fromMessage, Swift_Message $toMessage, $headerName) - { - $header = $fromMessage->getHeaders()->get($headerName); - if (!$header) { - return; - } - $headers = $toMessage->getHeaders(); - switch ($header->getFieldType()) { - case Swift_Mime_Header::TYPE_TEXT: - $headers->addTextHeader($header->getFieldName(), $header->getValue()); - break; - case Swift_Mime_Header::TYPE_PARAMETERIZED: - $headers->addParameterizedHeader( - $header->getFieldName(), - $header->getValue(), - $header->getParameters() - ); - break; - } - } - - /** - * Remove all headers from a Swift message. - */ - protected function clearAllHeaders(Swift_Message $message) - { - $headers = $message->getHeaders(); - foreach ($headers->listAll() as $header) { - $headers->removeAll($header); - } - } - - /** - * Wraps a Swift_Message in a message/rfc822 MIME part. - * - * @return Swift_MimePart - */ - protected function wrapMimeMessage(Swift_Message $message) - { - // Start by copying the original message into a message stream - $messageStream = new Swift_ByteStream_TemporaryFileByteStream(); - $message->toByteStream($messageStream); - $messageStream->commit(); - - // Create a new MIME part that wraps the original stream - $wrappedMessage = new Swift_MimePart($messageStream, 'message/rfc822'); - $wrappedMessage->setEncoder(new Swift_Mime_ContentEncoder_PlainContentEncoder('7bit')); - - return $wrappedMessage; - } - - protected function parseSSLOutput(Swift_InputByteStream $inputStream, Swift_Message $message) - { - $messageStream = new Swift_ByteStream_TemporaryFileByteStream(); - $this->copyFromOpenSSLOutput($inputStream, $messageStream); - - $this->streamToMime($messageStream, $message); - } - - /** - * Merges an OutputByteStream from OpenSSL to a Swift_Message. - */ - protected function streamToMime(Swift_OutputByteStream $fromStream, Swift_Message $message) - { - // Parse the stream into headers and body - list($headers, $messageStream) = $this->parseStream($fromStream); - - // Get the original message headers - $messageHeaders = $message->getHeaders(); - - // Let the stream determine the headers describing the body content, - // since the body of the original message is overwritten by the body - // coming from the stream. - // These are all content-* headers. - - // Default transfer encoding is 7bit if not set - $encoding = ''; - // Remove all existing transfer encoding headers - $messageHeaders->removeAll('Content-Transfer-Encoding'); - // See whether the stream sets the transfer encoding - if (isset($headers['content-transfer-encoding'])) { - $encoding = $headers['content-transfer-encoding']; - } - - // We use the null content encoder, since the body is already encoded - // according to the transfer encoding specified in the stream - $message->setEncoder(new Swift_Mime_ContentEncoder_NullContentEncoder($encoding)); - - // Set the disposition, if present - if (isset($headers['content-disposition'])) { - $messageHeaders->addTextHeader('Content-Disposition', $headers['content-disposition']); - } - - // Copy over the body from the stream using the content type dictated - // by the stream content - $message->setChildren([]); - $message->setBody($messageStream, $headers['content-type']); - } - - /** - * This message will parse the headers of a MIME email byte stream - * and return an array that contains the headers as an associative - * array and the email body as a string. - * - * @return array - */ - protected function parseStream(Swift_OutputByteStream $emailStream) - { - $bufferLength = 78; - $headerData = ''; - $headerBodySeparator = "\r\n\r\n"; - - $emailStream->setReadPointer(0); - - // Read out the headers section from the stream to a string - while (false !== ($buffer = $emailStream->read($bufferLength))) { - $headerData .= $buffer; - - $headersPosEnd = strpos($headerData, $headerBodySeparator); - - // Stop reading if we found the end of the headers - if (false !== $headersPosEnd) { - break; - } - } - - // Split the header data into lines - $headerData = trim(substr($headerData, 0, $headersPosEnd)); - $headerLines = explode("\r\n", $headerData); - unset($headerData); - - $headers = []; - $currentHeaderName = ''; - - // Transform header lines into an associative array - foreach ($headerLines as $headerLine) { - // Handle headers that span multiple lines - if (false === strpos($headerLine, ':')) { - $headers[$currentHeaderName] .= ' '.trim($headerLine ?? ''); - continue; - } - - $header = explode(':', $headerLine, 2); - $currentHeaderName = strtolower($header[0] ?? ''); - $headers[$currentHeaderName] = trim($header[1] ?? ''); - } - - // Read the entire email body into a byte stream - $bodyStream = new Swift_ByteStream_TemporaryFileByteStream(); - - // Skip the header and separator and point to the body - $emailStream->setReadPointer($headersPosEnd + \strlen($headerBodySeparator)); - - while (false !== ($buffer = $emailStream->read($bufferLength))) { - $bodyStream->write($buffer); - } - - $bodyStream->commit(); - - return [$headers, $bodyStream]; - } - - protected function copyFromOpenSSLOutput(Swift_OutputByteStream $fromStream, Swift_InputByteStream $toStream) - { - $bufferLength = 4096; - $filteredStream = new Swift_ByteStream_TemporaryFileByteStream(); - $filteredStream->addFilter($this->replacementFactory->createFilter("\r\n", "\n"), 'CRLF to LF'); - $filteredStream->addFilter($this->replacementFactory->createFilter("\n", "\r\n"), 'LF to CRLF'); - - while (false !== ($buffer = $fromStream->read($bufferLength))) { - $filteredStream->write($buffer); - } - - $filteredStream->flushBuffers(); - - while (false !== ($buffer = $filteredStream->read($bufferLength))) { - $toStream->write($buffer); - } - - $toStream->commit(); - } + protected $signCertificate; + protected $signPrivateKey; + protected $encryptCert; + protected $signThenEncrypt = true; + protected $signLevel; + protected $encryptLevel; + protected $signOptions; + protected $encryptOptions; + protected $encryptCipher; + protected $extraCerts = null; + protected $wrapFullMessage = false; + + /** + * @var Swift_StreamFilters_StringReplacementFilterFactory + */ + protected $replacementFactory; + + /** + * @var Swift_Mime_SimpleHeaderFactory + */ + protected $headerFactory; + + /** + * Constructor. + * + * @param string|null $signCertificate + * @param string|null $signPrivateKey + * @param string|null $encryptCertificate + */ + public function __construct($signCertificate = null, $signPrivateKey = null, $encryptCertificate = null) + { + if (null !== $signPrivateKey) { + $this->setSignCertificate($signCertificate, $signPrivateKey); + } + + if (null !== $encryptCertificate) { + $this->setEncryptCertificate($encryptCertificate); + } + + $this->replacementFactory = Swift_DependencyContainer::getInstance() + ->lookup('transport.replacementfactory'); + + $this->signOptions = PKCS7_DETACHED; + $this->encryptCipher = OPENSSL_CIPHER_AES_128_CBC; + } + + /** + * Set the certificate location to use for signing. + * + * @see https://secure.php.net/manual/en/openssl.pkcs7.flags.php + * + * @param string $certificate + * @param string|array $privateKey If the key needs an passphrase use array('file-location', 'passphrase') instead + * @param int $signOptions Bitwise operator options for openssl_pkcs7_sign() + * @param string $extraCerts A file containing intermediate certificates needed by the signing certificate + * + * @return $this + */ + public function setSignCertificate($certificate, $privateKey = null, $signOptions = PKCS7_DETACHED, $extraCerts = null) + { + $this->signCertificate = 'file://'.str_replace('\\', '/', realpath($certificate)); + + if (null !== $privateKey) { + if (\is_array($privateKey)) { + $this->signPrivateKey = $privateKey; + $this->signPrivateKey[0] = 'file://'.str_replace('\\', '/', realpath($privateKey[0])); + } else { + $this->signPrivateKey = 'file://'.str_replace('\\', '/', realpath($privateKey)); + } + } + + $this->signOptions = $signOptions; + $this->extraCerts = $extraCerts ? realpath($extraCerts) : null; + + return $this; + } + + /** + * Set the certificate location to use for encryption. + * + * @see https://secure.php.net/manual/en/openssl.pkcs7.flags.php + * @see https://secure.php.net/manual/en/openssl.ciphers.php + * + * @param string|array $recipientCerts Either an single X.509 certificate, or an assoc array of X.509 certificates. + * @param int $cipher + * + * @return $this + */ + public function setEncryptCertificate($recipientCerts, $cipher = null) + { + if (\is_array($recipientCerts)) { + $this->encryptCert = []; + + foreach ($recipientCerts as $cert) { + $this->encryptCert[] = 'file://'.str_replace('\\', '/', realpath($cert)); + } + } else { + $this->encryptCert = 'file://'.str_replace('\\', '/', realpath($recipientCerts)); + } + + if (null !== $cipher) { + $this->encryptCipher = $cipher; + } + + return $this; + } + + /** + * @return string + */ + public function getSignCertificate() + { + return $this->signCertificate; + } + + /** + * @return string + */ + public function getSignPrivateKey() + { + return $this->signPrivateKey; + } + + /** + * Set perform signing before encryption. + * + * The default is to first sign the message and then encrypt. + * But some older mail clients, namely Microsoft Outlook 2000 will work when the message first encrypted. + * As this goes against the official specs, its recommended to only use 'encryption -> signing' when specifically targeting these 'broken' clients. + * + * @param bool $signThenEncrypt + * + * @return $this + */ + public function setSignThenEncrypt($signThenEncrypt = true) + { + $this->signThenEncrypt = $signThenEncrypt; + + return $this; + } + + /** + * @return bool + */ + public function isSignThenEncrypt() + { + return $this->signThenEncrypt; + } + + /** + * Resets internal states. + * + * @return $this + */ + public function reset() + { + return $this; + } + + /** + * Specify whether to wrap the entire MIME message in the S/MIME message. + * + * According to RFC5751 section 3.1: + * In order to protect outer, non-content-related message header fields + * (for instance, the "Subject", "To", "From", and "Cc" fields), the + * sending client MAY wrap a full MIME message in a message/rfc822 + * wrapper in order to apply S/MIME security services to these header + * fields. It is up to the receiving client to decide how to present + * this "inner" header along with the unprotected "outer" header. + * + * @param bool $wrap + * + * @return $this + */ + public function setWrapFullMessage($wrap) + { + $this->wrapFullMessage = $wrap; + } + + /** + * Change the Swift_Message to apply the signing. + * + * @return $this + */ + public function signMessage(Swift_Message $message) + { + if (null === $this->signCertificate && null === $this->encryptCert) { + return $this; + } + + if ($this->signThenEncrypt) { + $this->smimeSignMessage($message); + $this->smimeEncryptMessage($message); + } else { + $this->smimeEncryptMessage($message); + $this->smimeSignMessage($message); + } + } + + /** + * Return the list of header a signer might tamper. + * + * @return array + */ + public function getAlteredHeaders() + { + return ['Content-Type', 'Content-Transfer-Encoding', 'Content-Disposition']; + } + + /** + * Sign a Swift message. + */ + protected function smimeSignMessage(Swift_Message $message) + { + // If we don't have a certificate we can't sign the message + if (null === $this->signCertificate) { + return; + } + + // Work on a clone of the original message + $signMessage = clone $message; + $signMessage->clearSigners(); + + if ($this->wrapFullMessage) { + // The original message essentially becomes the body of the new + // wrapped message + $signMessage = $this->wrapMimeMessage($signMessage); + } else { + // Only keep header needed to parse the body correctly + $this->clearAllHeaders($signMessage); + $this->copyHeaders( + $message, + $signMessage, + [ + 'Content-Type', + 'Content-Transfer-Encoding', + 'Content-Disposition', + ] + ); + } + + // Copy the cloned message into a temporary file stream + $messageStream = new Swift_ByteStream_TemporaryFileByteStream(); + $signMessage->toByteStream($messageStream); + $messageStream->commit(); + $signedMessageStream = new Swift_ByteStream_TemporaryFileByteStream(); + + // Sign the message using openssl + if (!openssl_pkcs7_sign( + $messageStream->getPath(), + $signedMessageStream->getPath(), + $this->signCertificate, + $this->signPrivateKey, + [], + $this->signOptions, + $this->extraCerts + ) + ) { + throw new Swift_IoException(sprintf('Failed to sign S/Mime message. Error: "%s".', openssl_error_string())); + } + + // Parse the resulting signed message content back into the Swift message + // preserving the original headers + $this->parseSSLOutput($signedMessageStream, $message); + } + + /** + * Encrypt a Swift message. + */ + protected function smimeEncryptMessage(Swift_Message $message) + { + // If we don't have a certificate we can't encrypt the message + if (null === $this->encryptCert) { + return; + } + + // Work on a clone of the original message + $encryptMessage = clone $message; + $encryptMessage->clearSigners(); + + if ($this->wrapFullMessage) { + // The original message essentially becomes the body of the new + // wrapped message + $encryptMessage = $this->wrapMimeMessage($encryptMessage); + } else { + // Only keep header needed to parse the body correctly + $this->clearAllHeaders($encryptMessage); + $this->copyHeaders( + $message, + $encryptMessage, + [ + 'Content-Type', + 'Content-Transfer-Encoding', + 'Content-Disposition', + ] + ); + } + + // Convert the message content (including headers) to a string + // and place it in a temporary file + $messageStream = new Swift_ByteStream_TemporaryFileByteStream(); + $encryptMessage->toByteStream($messageStream); + $messageStream->commit(); + $encryptedMessageStream = new Swift_ByteStream_TemporaryFileByteStream(); + + // Encrypt the message + if (!openssl_pkcs7_encrypt( + $messageStream->getPath(), + $encryptedMessageStream->getPath(), + $this->encryptCert, + [], + 0, + $this->encryptCipher + ) + ) { + throw new Swift_IoException(sprintf('Failed to encrypt S/Mime message. Error: "%s".', openssl_error_string())); + } + + // Parse the resulting signed message content back into the Swift message + // preserving the original headers + $this->parseSSLOutput($encryptedMessageStream, $message); + } + + /** + * Copy named headers from one Swift message to another. + */ + protected function copyHeaders( + Swift_Message $fromMessage, + Swift_Message $toMessage, + array $headers = [] + ) { + foreach ($headers as $header) { + $this->copyHeader($fromMessage, $toMessage, $header); + } + } + + /** + * Copy a single header from one Swift message to another. + * + * @param string $headerName + */ + protected function copyHeader(Swift_Message $fromMessage, Swift_Message $toMessage, $headerName) + { + $header = $fromMessage->getHeaders()->get($headerName); + if (!$header) { + return; + } + $headers = $toMessage->getHeaders(); + switch ($header->getFieldType()) { + case Swift_Mime_Header::TYPE_TEXT: + $headers->addTextHeader($header->getFieldName(), $header->getValue()); + break; + case Swift_Mime_Header::TYPE_PARAMETERIZED: + $headers->addParameterizedHeader( + $header->getFieldName(), + $header->getValue(), + $header->getParameters() + ); + break; + } + } + + /** + * Remove all headers from a Swift message. + */ + protected function clearAllHeaders(Swift_Message $message) + { + $headers = $message->getHeaders(); + foreach ($headers->listAll() as $header) { + $headers->removeAll($header); + } + } + + /** + * Wraps a Swift_Message in a message/rfc822 MIME part. + * + * @return Swift_MimePart + */ + protected function wrapMimeMessage(Swift_Message $message) + { + // Start by copying the original message into a message stream + $messageStream = new Swift_ByteStream_TemporaryFileByteStream(); + $message->toByteStream($messageStream); + $messageStream->commit(); + + // Create a new MIME part that wraps the original stream + $wrappedMessage = new Swift_MimePart($messageStream, 'message/rfc822'); + $wrappedMessage->setEncoder(new Swift_Mime_ContentEncoder_PlainContentEncoder('7bit')); + + return $wrappedMessage; + } + + protected function parseSSLOutput(Swift_InputByteStream $inputStream, Swift_Message $message) + { + $messageStream = new Swift_ByteStream_TemporaryFileByteStream(); + $this->copyFromOpenSSLOutput($inputStream, $messageStream); + + $this->streamToMime($messageStream, $message); + } + + /** + * Merges an OutputByteStream from OpenSSL to a Swift_Message. + */ + protected function streamToMime(Swift_OutputByteStream $fromStream, Swift_Message $message) + { + // Parse the stream into headers and body + list($headers, $messageStream) = $this->parseStream($fromStream); + + // Get the original message headers + $messageHeaders = $message->getHeaders(); + + // Let the stream determine the headers describing the body content, + // since the body of the original message is overwritten by the body + // coming from the stream. + // These are all content-* headers. + + // Default transfer encoding is 7bit if not set + $encoding = ''; + // Remove all existing transfer encoding headers + $messageHeaders->removeAll('Content-Transfer-Encoding'); + // See whether the stream sets the transfer encoding + if (isset($headers['content-transfer-encoding'])) { + $encoding = $headers['content-transfer-encoding']; + } + + // We use the null content encoder, since the body is already encoded + // according to the transfer encoding specified in the stream + $message->setEncoder(new Swift_Mime_ContentEncoder_NullContentEncoder($encoding)); + + // Set the disposition, if present + if (isset($headers['content-disposition'])) { + $messageHeaders->addTextHeader('Content-Disposition', $headers['content-disposition']); + } + + // Copy over the body from the stream using the content type dictated + // by the stream content + $message->setChildren([]); + $message->setBody($messageStream, $headers['content-type']); + } + + /** + * This message will parse the headers of a MIME email byte stream + * and return an array that contains the headers as an associative + * array and the email body as a string. + * + * @return array + */ + protected function parseStream(Swift_OutputByteStream $emailStream) + { + $bufferLength = 78; + $headerData = ''; + $headerBodySeparator = "\r\n\r\n"; + + $emailStream->setReadPointer(0); + + // Read out the headers section from the stream to a string + while (false !== ($buffer = $emailStream->read($bufferLength))) { + $headerData .= $buffer; + + $headersPosEnd = strpos($headerData, $headerBodySeparator); + + // Stop reading if we found the end of the headers + if (false !== $headersPosEnd) { + break; + } + } + + // Split the header data into lines + $headerData = trim(substr($headerData, 0, $headersPosEnd)); + $headerLines = explode("\r\n", $headerData); + unset($headerData); + + $headers = []; + $currentHeaderName = ''; + + // Transform header lines into an associative array + foreach ($headerLines as $headerLine) { + // Handle headers that span multiple lines + if (false === strpos($headerLine, ':')) { + $headers[$currentHeaderName] .= ' '.trim($headerLine ?? ''); + continue; + } + + $header = explode(':', $headerLine, 2); + $currentHeaderName = strtolower($header[0] ?? ''); + $headers[$currentHeaderName] = trim($header[1] ?? ''); + } + + // Read the entire email body into a byte stream + $bodyStream = new Swift_ByteStream_TemporaryFileByteStream(); + + // Skip the header and separator and point to the body + $emailStream->setReadPointer($headersPosEnd + \strlen($headerBodySeparator)); + + while (false !== ($buffer = $emailStream->read($bufferLength))) { + $bodyStream->write($buffer); + } + + $bodyStream->commit(); + + return [$headers, $bodyStream]; + } + + protected function copyFromOpenSSLOutput(Swift_OutputByteStream $fromStream, Swift_InputByteStream $toStream) + { + $bufferLength = 4096; + $filteredStream = new Swift_ByteStream_TemporaryFileByteStream(); + $filteredStream->addFilter($this->replacementFactory->createFilter("\r\n", "\n"), 'CRLF to LF'); + $filteredStream->addFilter($this->replacementFactory->createFilter("\n", "\r\n"), 'LF to CRLF'); + + while (false !== ($buffer = $fromStream->read($bufferLength))) { + $filteredStream->write($buffer); + } + + $filteredStream->flushBuffers(); + + while (false !== ($buffer = $filteredStream->read($bufferLength))) { + $toStream->write($buffer); + } + + $toStream->commit(); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/SmtpTransport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/SmtpTransport.php index 625a470e09c..56b62323ad7 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/SmtpTransport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/SmtpTransport.php @@ -22,24 +22,24 @@ */ class Swift_SmtpTransport extends Swift_Transport_EsmtpTransport { - /** - * @param string $host - * @param int $port - * @param string|null $encryption SMTP encryption mode: - * - null for plain SMTP (no encryption), - * - 'tls' for SMTP with STARTTLS (best effort encryption), - * - 'ssl' for SMTPS = SMTP over TLS (always encrypted). - */ - public function __construct($host = 'localhost', $port = 25, $encryption = null) - { - \call_user_func_array( - [$this, 'Swift_Transport_EsmtpTransport::__construct'], - Swift_DependencyContainer::getInstance() - ->createDependenciesFor('transport.smtp') - ); + /** + * @param string $host + * @param int $port + * @param string|null $encryption SMTP encryption mode: + * - null for plain SMTP (no encryption), + * - 'tls' for SMTP with STARTTLS (best effort encryption), + * - 'ssl' for SMTPS = SMTP over TLS (always encrypted). + */ + public function __construct($host = 'localhost', $port = 25, $encryption = null) + { + \call_user_func_array( + [$this, 'Swift_Transport_EsmtpTransport::__construct'], + Swift_DependencyContainer::getInstance() + ->createDependenciesFor('transport.smtp') + ); - $this->setHost($host); - $this->setPort($port); - $this->setEncryption($encryption); - } + $this->setHost($host); + $this->setPort($port); + $this->setEncryption($encryption); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/SpoolTransport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/SpoolTransport.php index ac30065048a..c08e0fb17d5 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/SpoolTransport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/SpoolTransport.php @@ -15,19 +15,19 @@ */ class Swift_SpoolTransport extends Swift_Transport_SpoolTransport { - /** - * Create a new SpoolTransport. - */ - public function __construct(Swift_Spool $spool) - { - $arguments = Swift_DependencyContainer::getInstance() - ->createDependenciesFor('transport.spool'); + /** + * Create a new SpoolTransport. + */ + public function __construct(Swift_Spool $spool) + { + $arguments = Swift_DependencyContainer::getInstance() + ->createDependenciesFor('transport.spool'); - $arguments[] = $spool; + $arguments[] = $spool; - \call_user_func_array( - [$this, 'Swift_Transport_SpoolTransport::__construct'], - $arguments - ); - } + \call_user_func_array( + [$this, 'Swift_Transport_SpoolTransport::__construct'], + $arguments + ); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/StreamFilters/ByteArrayReplacementFilter.php b/htdocs/includes/swiftmailer/lib/classes/Swift/StreamFilters/ByteArrayReplacementFilter.php index 2e68f95e3e7..7e5ddf1b7da 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/StreamFilters/ByteArrayReplacementFilter.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/StreamFilters/ByteArrayReplacementFilter.php @@ -17,150 +17,150 @@ */ class Swift_StreamFilters_ByteArrayReplacementFilter implements Swift_StreamFilter { - /** The replacement(s) to make */ - private $replace; + /** The replacement(s) to make */ + private $replace; - /** The Index for searching */ - private $index; + /** The Index for searching */ + private $index; - /** The Search Tree */ - private $tree = []; + /** The Search Tree */ + private $tree = []; - /** Gives the size of the largest search */ - private $treeMaxLen = 0; + /** Gives the size of the largest search */ + private $treeMaxLen = 0; - private $repSize; + private $repSize; - /** - * Create a new ByteArrayReplacementFilter with $search and $replace. - * - * @param array $search - * @param array $replace - */ - public function __construct($search, $replace) - { - $this->index = []; - $this->tree = []; - $this->replace = []; - $this->repSize = []; + /** + * Create a new ByteArrayReplacementFilter with $search and $replace. + * + * @param array $search + * @param array $replace + */ + public function __construct($search, $replace) + { + $this->index = []; + $this->tree = []; + $this->replace = []; + $this->repSize = []; - $tree = null; - $i = null; - $last_size = $size = 0; - foreach ($search as $i => $search_element) { - if (null !== $tree) { - $tree[-1] = min(\count($replace) - 1, $i - 1); - $tree[-2] = $last_size; - } - $tree = &$this->tree; - if (\is_array($search_element)) { - foreach ($search_element as $k => $char) { - $this->index[$char] = true; - if (!isset($tree[$char])) { - $tree[$char] = []; - } - $tree = &$tree[$char]; - } - $last_size = $k + 1; - $size = max($size, $last_size); - } else { - $last_size = 1; - if (!isset($tree[$search_element])) { - $tree[$search_element] = []; - } - $tree = &$tree[$search_element]; - $size = max($last_size, $size); - $this->index[$search_element] = true; - } - } - if (null !== $i) { - $tree[-1] = min(\count($replace) - 1, $i); - $tree[-2] = $last_size; - $this->treeMaxLen = $size; - } - foreach ($replace as $rep) { - if (!\is_array($rep)) { - $rep = [$rep]; - } - $this->replace[] = $rep; - } - for ($i = \count($this->replace) - 1; $i >= 0; --$i) { - $this->replace[$i] = $rep = $this->filter($this->replace[$i], $i); - $this->repSize[$i] = \count($rep); - } - } + $tree = null; + $i = null; + $last_size = $size = 0; + foreach ($search as $i => $search_element) { + if (null !== $tree) { + $tree[-1] = min(\count($replace) - 1, $i - 1); + $tree[-2] = $last_size; + } + $tree = &$this->tree; + if (\is_array($search_element)) { + foreach ($search_element as $k => $char) { + $this->index[$char] = true; + if (!isset($tree[$char])) { + $tree[$char] = []; + } + $tree = &$tree[$char]; + } + $last_size = $k + 1; + $size = max($size, $last_size); + } else { + $last_size = 1; + if (!isset($tree[$search_element])) { + $tree[$search_element] = []; + } + $tree = &$tree[$search_element]; + $size = max($last_size, $size); + $this->index[$search_element] = true; + } + } + if (null !== $i) { + $tree[-1] = min(\count($replace) - 1, $i); + $tree[-2] = $last_size; + $this->treeMaxLen = $size; + } + foreach ($replace as $rep) { + if (!\is_array($rep)) { + $rep = [$rep]; + } + $this->replace[] = $rep; + } + for ($i = \count($this->replace) - 1; $i >= 0; --$i) { + $this->replace[$i] = $rep = $this->filter($this->replace[$i], $i); + $this->repSize[$i] = \count($rep); + } + } - /** - * Returns true if based on the buffer passed more bytes should be buffered. - * - * @param array $buffer - * - * @return bool - */ - public function shouldBuffer($buffer) - { - $endOfBuffer = end($buffer); + /** + * Returns true if based on the buffer passed more bytes should be buffered. + * + * @param array $buffer + * + * @return bool + */ + public function shouldBuffer($buffer) + { + $endOfBuffer = end($buffer); - return isset($this->index[$endOfBuffer]); - } + return isset($this->index[$endOfBuffer]); + } - /** - * Perform the actual replacements on $buffer and return the result. - * - * @param array $buffer - * @param int $minReplaces - * - * @return array - */ - public function filter($buffer, $minReplaces = -1) - { - if (0 == $this->treeMaxLen) { - return $buffer; - } + /** + * Perform the actual replacements on $buffer and return the result. + * + * @param array $buffer + * @param int $minReplaces + * + * @return array + */ + public function filter($buffer, $minReplaces = -1) + { + if (0 == $this->treeMaxLen) { + return $buffer; + } - $newBuffer = []; - $buf_size = \count($buffer); - $last_size = 0; - for ($i = 0; $i < $buf_size; ++$i) { - $search_pos = $this->tree; - $last_found = PHP_INT_MAX; - // We try to find if the next byte is part of a search pattern - for ($j = 0; $j <= $this->treeMaxLen; ++$j) { - // We have a new byte for a search pattern - if (isset($buffer[$p = $i + $j]) && isset($search_pos[$buffer[$p]])) { - $search_pos = $search_pos[$buffer[$p]]; - // We have a complete pattern, save, in case we don't find a better match later - if (isset($search_pos[-1]) && $search_pos[-1] < $last_found - && $search_pos[-1] > $minReplaces) { - $last_found = $search_pos[-1]; - $last_size = $search_pos[-2]; - } - } - // We got a complete pattern - elseif (PHP_INT_MAX !== $last_found) { - // Adding replacement datas to output buffer - $rep_size = $this->repSize[$last_found]; - for ($j = 0; $j < $rep_size; ++$j) { - $newBuffer[] = $this->replace[$last_found][$j]; - } - // We Move cursor forward - $i += $last_size - 1; - // Edge Case, last position in buffer - if ($i >= $buf_size) { - $newBuffer[] = $buffer[$i]; - } + $newBuffer = []; + $buf_size = \count($buffer); + $last_size = 0; + for ($i = 0; $i < $buf_size; ++$i) { + $search_pos = $this->tree; + $last_found = PHP_INT_MAX; + // We try to find if the next byte is part of a search pattern + for ($j = 0; $j <= $this->treeMaxLen; ++$j) { + // We have a new byte for a search pattern + if (isset($buffer[$p = $i + $j]) && isset($search_pos[$buffer[$p]])) { + $search_pos = $search_pos[$buffer[$p]]; + // We have a complete pattern, save, in case we don't find a better match later + if (isset($search_pos[-1]) && $search_pos[-1] < $last_found + && $search_pos[-1] > $minReplaces) { + $last_found = $search_pos[-1]; + $last_size = $search_pos[-2]; + } + } + // We got a complete pattern + elseif (PHP_INT_MAX !== $last_found) { + // Adding replacement datas to output buffer + $rep_size = $this->repSize[$last_found]; + for ($j = 0; $j < $rep_size; ++$j) { + $newBuffer[] = $this->replace[$last_found][$j]; + } + // We Move cursor forward + $i += $last_size - 1; + // Edge Case, last position in buffer + if ($i >= $buf_size) { + $newBuffer[] = $buffer[$i]; + } - // We start the next loop - continue 2; - } else { - // this byte is not in a pattern and we haven't found another pattern - break; - } - } - // Normal byte, move it to output buffer - $newBuffer[] = $buffer[$i]; - } + // We start the next loop + continue 2; + } else { + // this byte is not in a pattern and we haven't found another pattern + break; + } + } + // Normal byte, move it to output buffer + $newBuffer[] = $buffer[$i]; + } - return $newBuffer; - } + return $newBuffer; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/StreamFilters/StringReplacementFilterFactory.php b/htdocs/includes/swiftmailer/lib/classes/Swift/StreamFilters/StringReplacementFilterFactory.php index 965e9f69cda..783b8896dd7 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/StreamFilters/StringReplacementFilterFactory.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/StreamFilters/StringReplacementFilterFactory.php @@ -15,31 +15,31 @@ */ class Swift_StreamFilters_StringReplacementFilterFactory implements Swift_ReplacementFilterFactory { - /** Lazy-loaded filters */ - private $filters = []; + /** Lazy-loaded filters */ + private $filters = []; - /** - * Create a new StreamFilter to replace $search with $replace in a string. - * - * @param string $search - * @param string $replace - * - * @return Swift_StreamFilter - */ - public function createFilter($search, $replace) - { - if (!isset($this->filters[$search][$replace])) { - if (!isset($this->filters[$search])) { - $this->filters[$search] = []; - } + /** + * Create a new StreamFilter to replace $search with $replace in a string. + * + * @param string $search + * @param string $replace + * + * @return Swift_StreamFilter + */ + public function createFilter($search, $replace) + { + if (!isset($this->filters[$search][$replace])) { + if (!isset($this->filters[$search])) { + $this->filters[$search] = []; + } - if (!isset($this->filters[$search][$replace])) { - $this->filters[$search][$replace] = []; - } + if (!isset($this->filters[$search][$replace])) { + $this->filters[$search][$replace] = []; + } - $this->filters[$search][$replace] = new Swift_StreamFilters_StringReplacementFilter($search, $replace); - } + $this->filters[$search][$replace] = new Swift_StreamFilters_StringReplacementFilter($search, $replace); + } - return $this->filters[$search][$replace]; - } + return $this->filters[$search][$replace]; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/SwiftException.php b/htdocs/includes/swiftmailer/lib/classes/Swift/SwiftException.php index 44cbfc779e5..15e68b18e79 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/SwiftException.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/SwiftException.php @@ -15,14 +15,14 @@ */ class Swift_SwiftException extends Exception { - /** - * Create a new SwiftException with $message. - * - * @param string $message - * @param int $code - */ - public function __construct($message, $code = 0, Exception $previous = null) - { - parent::__construct($message, $code, $previous); - } + /** + * Create a new SwiftException with $message. + * + * @param string $message + * @param int $code + */ + public function __construct($message, $code = 0, Exception $previous = null) + { + parent::__construct($message, $code, $previous); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport.php index f3d4c4fe31e..bc324e8685a 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport.php @@ -15,62 +15,62 @@ */ interface Swift_Transport { - /** - * Test if this Transport mechanism has started. - * - * @return bool - */ - public function isStarted(); + /** + * Test if this Transport mechanism has started. + * + * @return bool + */ + public function isStarted(); - /** - * Start this Transport mechanism. - */ - public function start(); + /** + * Start this Transport mechanism. + */ + public function start(); - /** - * Stop this Transport mechanism. - */ - public function stop(); + /** + * Stop this Transport mechanism. + */ + public function stop(); - /** - * Check if this Transport mechanism is alive. - * - * If a Transport mechanism session is no longer functional, the method - * returns FALSE. It is the responsibility of the developer to handle this - * case and restart the Transport mechanism manually. - * - * @example - * - * if (!$transport->ping()) { - * $transport->stop(); - * $transport->start(); - * } - * - * The Transport mechanism will be started, if it is not already. - * - * It is undefined if the Transport mechanism attempts to restart as long as - * the return value reflects whether the mechanism is now functional. - * - * @return bool TRUE if the transport is alive - */ - public function ping(); + /** + * Check if this Transport mechanism is alive. + * + * If a Transport mechanism session is no longer functional, the method + * returns FALSE. It is the responsibility of the developer to handle this + * case and restart the Transport mechanism manually. + * + * @example + * + * if (!$transport->ping()) { + * $transport->stop(); + * $transport->start(); + * } + * + * The Transport mechanism will be started, if it is not already. + * + * It is undefined if the Transport mechanism attempts to restart as long as + * the return value reflects whether the mechanism is now functional. + * + * @return bool TRUE if the transport is alive + */ + public function ping(); - /** - * Send the given Message. - * - * Recipient/sender data will be retrieved from the Message API. - * The return value is the number of recipients who were accepted for delivery. - * - * This is the responsibility of the send method to start the transport if needed. - * - * @param string[] $failedRecipients An array of failures by-reference - * - * @return int - */ - public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null); + /** + * Send the given Message. + * + * Recipient/sender data will be retrieved from the Message API. + * The return value is the number of recipients who were accepted for delivery. + * + * This is the responsibility of the send method to start the transport if needed. + * + * @param string[] $failedRecipients An array of failures by-reference + * + * @return int + */ + public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null); - /** - * Register a plugin in the Transport. - */ - public function registerPlugin(Swift_Events_EventListener $plugin); + /** + * Register a plugin in the Transport. + */ + public function registerPlugin(Swift_Events_EventListener $plugin); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/AbstractSmtpTransport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/AbstractSmtpTransport.php index d761677db7e..d2dbd7a66a0 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/AbstractSmtpTransport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/AbstractSmtpTransport.php @@ -15,527 +15,527 @@ */ abstract class Swift_Transport_AbstractSmtpTransport implements Swift_Transport { - /** Input-Output buffer for sending/receiving SMTP commands and responses */ - protected $buffer; - - /** Connection status */ - protected $started = false; - - /** The domain name to use in HELO command */ - protected $domain = '[127.0.0.1]'; - - /** The event dispatching layer */ - protected $eventDispatcher; - - protected $addressEncoder; - - /** Whether the PIPELINING SMTP extension is enabled (RFC 2920) */ - protected $pipelining = null; - - /** The pipelined commands waiting for response */ - protected $pipeline = []; - - /** Source Ip */ - protected $sourceIp; - - /** Return an array of params for the Buffer */ - abstract protected function getBufferParams(); - - /** - * Creates a new EsmtpTransport using the given I/O buffer. - * - * @param string $localDomain - */ - public function __construct(Swift_Transport_IoBuffer $buf, Swift_Events_EventDispatcher $dispatcher, $localDomain = '127.0.0.1', Swift_AddressEncoder $addressEncoder = null) - { - $this->buffer = $buf; - $this->eventDispatcher = $dispatcher; - $this->addressEncoder = $addressEncoder ?? new Swift_AddressEncoder_IdnAddressEncoder(); - $this->setLocalDomain($localDomain); - } - - /** - * Set the name of the local domain which Swift will identify itself as. - * - * This should be a fully-qualified domain name and should be truly the domain - * you're using. - * - * If your server does not have a domain name, use the IP address. This will - * automatically be wrapped in square brackets as described in RFC 5321, - * section 4.1.3. - * - * @param string $domain - * - * @return $this - */ - public function setLocalDomain($domain) - { - if ('[' !== substr($domain, 0, 1)) { - if (filter_var($domain, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { - $domain = '['.$domain.']'; - } elseif (filter_var($domain, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { - $domain = '[IPv6:'.$domain.']'; - } - } - - $this->domain = $domain; - - return $this; - } - - /** - * Get the name of the domain Swift will identify as. - * - * If an IP address was specified, this will be returned wrapped in square - * brackets as described in RFC 5321, section 4.1.3. - * - * @return string - */ - public function getLocalDomain() - { - return $this->domain; - } - - /** - * Sets the source IP. - * - * @param string $source - */ - public function setSourceIp($source) - { - $this->sourceIp = $source; - } - - /** - * Returns the IP used to connect to the destination. - * - * @return string - */ - public function getSourceIp() - { - return $this->sourceIp; - } - - public function setAddressEncoder(Swift_AddressEncoder $addressEncoder) - { - $this->addressEncoder = $addressEncoder; - } - - public function getAddressEncoder() - { - return $this->addressEncoder; - } - - /** - * Start the SMTP connection. - */ - public function start() - { - if (!$this->started) { - if ($evt = $this->eventDispatcher->createTransportChangeEvent($this)) { - $this->eventDispatcher->dispatchEvent($evt, 'beforeTransportStarted'); - if ($evt->bubbleCancelled()) { - return; - } - } - - try { - $this->buffer->initialize($this->getBufferParams()); - } catch (Swift_TransportException $e) { - $this->throwException($e); - } - $this->readGreeting(); - $this->doHeloCommand(); - - if ($evt) { - $this->eventDispatcher->dispatchEvent($evt, 'transportStarted'); - } - - $this->started = true; - } - } - - /** - * Test if an SMTP connection has been established. - * - * @return bool - */ - public function isStarted() - { - return $this->started; - } - - /** - * Send the given Message. - * - * Recipient/sender data will be retrieved from the Message API. - * The return value is the number of recipients who were accepted for delivery. - * - * @param string[] $failedRecipients An array of failures by-reference - * - * @return int - */ - public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) - { - if (!$this->isStarted()) { - $this->start(); - } - - $sent = 0; - $failedRecipients = (array) $failedRecipients; - - if ($evt = $this->eventDispatcher->createSendEvent($this, $message)) { - $this->eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed'); - if ($evt->bubbleCancelled()) { - return 0; - } - } - - if (!$reversePath = $this->getReversePath($message)) { - $this->throwException(new Swift_TransportException('Cannot send message without a sender address')); - } - - $to = (array) $message->getTo(); - $cc = (array) $message->getCc(); - $bcc = (array) $message->getBcc(); - $tos = array_merge($to, $cc, $bcc); - - $message->setBcc([]); - - try { - $sent += $this->sendTo($message, $reversePath, $tos, $failedRecipients); - } finally { - $message->setBcc($bcc); - } - - if ($evt) { - if ($sent == \count($to) + \count($cc) + \count($bcc)) { - $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS); - } elseif ($sent > 0) { - $evt->setResult(Swift_Events_SendEvent::RESULT_TENTATIVE); - } else { - $evt->setResult(Swift_Events_SendEvent::RESULT_FAILED); - } - $evt->setFailedRecipients($failedRecipients); - $this->eventDispatcher->dispatchEvent($evt, 'sendPerformed'); - } - - $message->generateId(); //Make sure a new Message ID is used - - return $sent; - } - - /** - * Stop the SMTP connection. - */ - public function stop() - { - if ($this->started) { - if ($evt = $this->eventDispatcher->createTransportChangeEvent($this)) { - $this->eventDispatcher->dispatchEvent($evt, 'beforeTransportStopped'); - if ($evt->bubbleCancelled()) { - return; - } - } - - try { - $this->executeCommand("QUIT\r\n", [221]); - } catch (Swift_TransportException $e) { - } - - try { - $this->buffer->terminate(); - - if ($evt) { - $this->eventDispatcher->dispatchEvent($evt, 'transportStopped'); - } - } catch (Swift_TransportException $e) { - $this->throwException($e); - } - } - $this->started = false; - } - - /** - * {@inheritdoc} - */ - public function ping() - { - try { - if (!$this->isStarted()) { - $this->start(); - } - - $this->executeCommand("NOOP\r\n", [250]); - } catch (Swift_TransportException $e) { - try { - $this->stop(); - } catch (Swift_TransportException $e) { - } - - return false; - } - - return true; - } - - /** - * Register a plugin. - */ - public function registerPlugin(Swift_Events_EventListener $plugin) - { - $this->eventDispatcher->bindEventListener($plugin); - } - - /** - * Reset the current mail transaction. - */ - public function reset() - { - $this->executeCommand("RSET\r\n", [250], $failures, true); - } - - /** - * Get the IoBuffer where read/writes are occurring. - * - * @return Swift_Transport_IoBuffer - */ - public function getBuffer() - { - return $this->buffer; - } - - /** - * Run a command against the buffer, expecting the given response codes. - * - * If no response codes are given, the response will not be validated. - * If codes are given, an exception will be thrown on an invalid response. - * If the command is RCPT TO, and the pipeline is non-empty, no exception - * will be thrown; instead the failing address is added to $failures. - * - * @param string $command - * @param int[] $codes - * @param string[] $failures An array of failures by-reference - * @param bool $pipeline Do not wait for response - * @param string $address the address, if command is RCPT TO - * - * @return string|null The server response, or null if pipelining is enabled - */ - public function executeCommand($command, $codes = [], &$failures = null, $pipeline = false, $address = null) - { - $failures = (array) $failures; - $seq = $this->buffer->write($command); - if ($evt = $this->eventDispatcher->createCommandEvent($this, $command, $codes)) { - $this->eventDispatcher->dispatchEvent($evt, 'commandSent'); - } - - $this->pipeline[] = [$command, $seq, $codes, $address]; - - if ($pipeline && $this->pipelining) { - return null; - } - - $response = null; - - while ($this->pipeline) { - list($command, $seq, $codes, $address) = array_shift($this->pipeline); - $response = $this->getFullResponse($seq); - try { - $this->assertResponseCode($response, $codes); - } catch (Swift_TransportException $e) { - if ($this->pipeline && $address) { - $failures[] = $address; - } else { - $this->throwException($e); - } - } - } - - return $response; - } - - /** Read the opening SMTP greeting */ - protected function readGreeting() - { - $this->assertResponseCode($this->getFullResponse(0), [220]); - } - - /** Send the HELO welcome */ - protected function doHeloCommand() - { - $this->executeCommand( - sprintf("HELO %s\r\n", $this->domain), [250] - ); - } - - /** Send the MAIL FROM command */ - protected function doMailFromCommand($address) - { - $address = $this->addressEncoder->encodeString($address); - $this->executeCommand( - sprintf("MAIL FROM:<%s>\r\n", $address), [250], $failures, true - ); - } - - /** Send the RCPT TO command */ - protected function doRcptToCommand($address) - { - $address = $this->addressEncoder->encodeString($address); - $this->executeCommand( - sprintf("RCPT TO:<%s>\r\n", $address), [250, 251, 252], $failures, true, $address - ); - } - - /** Send the DATA command */ - protected function doDataCommand(&$failedRecipients) - { - $this->executeCommand("DATA\r\n", [354], $failedRecipients); - } - - /** Stream the contents of the message over the buffer */ - protected function streamMessage(Swift_Mime_SimpleMessage $message) - { - $this->buffer->setWriteTranslations(["\r\n." => "\r\n.."]); - try { - $message->toByteStream($this->buffer); - $this->buffer->flushBuffers(); - } catch (Swift_TransportException $e) { - $this->throwException($e); - } - $this->buffer->setWriteTranslations([]); - $this->executeCommand("\r\n.\r\n", [250]); - } - - /** Determine the best-use reverse path for this message */ - protected function getReversePath(Swift_Mime_SimpleMessage $message) - { - $return = $message->getReturnPath(); - $sender = $message->getSender(); - $from = $message->getFrom(); - $path = null; - if (!empty($return)) { - $path = $return; - } elseif (!empty($sender)) { - // Don't use array_keys - reset($sender); // Reset Pointer to first pos - $path = key($sender); // Get key - } elseif (!empty($from)) { - reset($from); // Reset Pointer to first pos - $path = key($from); // Get key - } - - return $path; - } - - /** Throw a TransportException, first sending it to any listeners */ - protected function throwException(Swift_TransportException $e) - { - if ($evt = $this->eventDispatcher->createTransportExceptionEvent($this, $e)) { - $this->eventDispatcher->dispatchEvent($evt, 'exceptionThrown'); - if (!$evt->bubbleCancelled()) { - throw $e; - } - } else { - throw $e; - } - } - - /** Throws an Exception if a response code is incorrect */ - protected function assertResponseCode($response, $wanted) - { - if (!$response) { - $this->throwException(new Swift_TransportException('Expected response code '.implode('/', $wanted).' but got an empty response')); - } - - list($code) = sscanf($response, '%3d'); - $valid = (empty($wanted) || \in_array($code, $wanted)); - - if ($evt = $this->eventDispatcher->createResponseEvent($this, $response, - $valid)) { - $this->eventDispatcher->dispatchEvent($evt, 'responseReceived'); - } - - if (!$valid) { - $this->throwException(new Swift_TransportException('Expected response code '.implode('/', $wanted).' but got code "'.$code.'", with message "'.$response.'"', $code)); - } - } - - /** Get an entire multi-line response using its sequence number */ - protected function getFullResponse($seq) - { - $response = ''; - try { - do { - $line = $this->buffer->readLine($seq); - $response .= $line; - } while (null !== $line && false !== $line && ' ' != $line[3]); - } catch (Swift_TransportException $e) { - $this->throwException($e); - } catch (Swift_IoException $e) { - $this->throwException(new Swift_TransportException($e->getMessage(), 0, $e)); - } - - return $response; - } - - /** Send an email to the given recipients from the given reverse path */ - private function doMailTransaction($message, $reversePath, array $recipients, array &$failedRecipients) - { - $sent = 0; - $this->doMailFromCommand($reversePath); - foreach ($recipients as $forwardPath) { - try { - $this->doRcptToCommand($forwardPath); - ++$sent; - } catch (Swift_TransportException $e) { - $failedRecipients[] = $forwardPath; - } catch (Swift_AddressEncoderException $e) { - $failedRecipients[] = $forwardPath; - } - } - - if (0 != $sent) { - $sent += \count($failedRecipients); - $this->doDataCommand($failedRecipients); - $sent -= \count($failedRecipients); - - $this->streamMessage($message); - } else { - $this->reset(); - } - - return $sent; - } - - /** Send a message to the given To: recipients */ - private function sendTo(Swift_Mime_SimpleMessage $message, $reversePath, array $to, array &$failedRecipients) - { - if (empty($to)) { - return 0; - } - - return $this->doMailTransaction($message, $reversePath, array_keys($to), - $failedRecipients); - } - - /** - * Destructor. - */ - public function __destruct() - { - try { - $this->stop(); - } catch (Exception $e) { - } - } - - public function __sleep() - { - throw new \BadMethodCallException('Cannot serialize '.__CLASS__); - } - - public function __wakeup() - { - throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); - } + /** Input-Output buffer for sending/receiving SMTP commands and responses */ + protected $buffer; + + /** Connection status */ + protected $started = false; + + /** The domain name to use in HELO command */ + protected $domain = '[127.0.0.1]'; + + /** The event dispatching layer */ + protected $eventDispatcher; + + protected $addressEncoder; + + /** Whether the PIPELINING SMTP extension is enabled (RFC 2920) */ + protected $pipelining = null; + + /** The pipelined commands waiting for response */ + protected $pipeline = []; + + /** Source Ip */ + protected $sourceIp; + + /** Return an array of params for the Buffer */ + abstract protected function getBufferParams(); + + /** + * Creates a new EsmtpTransport using the given I/O buffer. + * + * @param string $localDomain + */ + public function __construct(Swift_Transport_IoBuffer $buf, Swift_Events_EventDispatcher $dispatcher, $localDomain = '127.0.0.1', Swift_AddressEncoder $addressEncoder = null) + { + $this->buffer = $buf; + $this->eventDispatcher = $dispatcher; + $this->addressEncoder = $addressEncoder ?? new Swift_AddressEncoder_IdnAddressEncoder(); + $this->setLocalDomain($localDomain); + } + + /** + * Set the name of the local domain which Swift will identify itself as. + * + * This should be a fully-qualified domain name and should be truly the domain + * you're using. + * + * If your server does not have a domain name, use the IP address. This will + * automatically be wrapped in square brackets as described in RFC 5321, + * section 4.1.3. + * + * @param string $domain + * + * @return $this + */ + public function setLocalDomain($domain) + { + if ('[' !== substr($domain, 0, 1)) { + if (filter_var($domain, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { + $domain = '['.$domain.']'; + } elseif (filter_var($domain, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { + $domain = '[IPv6:'.$domain.']'; + } + } + + $this->domain = $domain; + + return $this; + } + + /** + * Get the name of the domain Swift will identify as. + * + * If an IP address was specified, this will be returned wrapped in square + * brackets as described in RFC 5321, section 4.1.3. + * + * @return string + */ + public function getLocalDomain() + { + return $this->domain; + } + + /** + * Sets the source IP. + * + * @param string $source + */ + public function setSourceIp($source) + { + $this->sourceIp = $source; + } + + /** + * Returns the IP used to connect to the destination. + * + * @return string + */ + public function getSourceIp() + { + return $this->sourceIp; + } + + public function setAddressEncoder(Swift_AddressEncoder $addressEncoder) + { + $this->addressEncoder = $addressEncoder; + } + + public function getAddressEncoder() + { + return $this->addressEncoder; + } + + /** + * Start the SMTP connection. + */ + public function start() + { + if (!$this->started) { + if ($evt = $this->eventDispatcher->createTransportChangeEvent($this)) { + $this->eventDispatcher->dispatchEvent($evt, 'beforeTransportStarted'); + if ($evt->bubbleCancelled()) { + return; + } + } + + try { + $this->buffer->initialize($this->getBufferParams()); + } catch (Swift_TransportException $e) { + $this->throwException($e); + } + $this->readGreeting(); + $this->doHeloCommand(); + + if ($evt) { + $this->eventDispatcher->dispatchEvent($evt, 'transportStarted'); + } + + $this->started = true; + } + } + + /** + * Test if an SMTP connection has been established. + * + * @return bool + */ + public function isStarted() + { + return $this->started; + } + + /** + * Send the given Message. + * + * Recipient/sender data will be retrieved from the Message API. + * The return value is the number of recipients who were accepted for delivery. + * + * @param string[] $failedRecipients An array of failures by-reference + * + * @return int + */ + public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) + { + if (!$this->isStarted()) { + $this->start(); + } + + $sent = 0; + $failedRecipients = (array) $failedRecipients; + + if ($evt = $this->eventDispatcher->createSendEvent($this, $message)) { + $this->eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed'); + if ($evt->bubbleCancelled()) { + return 0; + } + } + + if (!$reversePath = $this->getReversePath($message)) { + $this->throwException(new Swift_TransportException('Cannot send message without a sender address')); + } + + $to = (array) $message->getTo(); + $cc = (array) $message->getCc(); + $bcc = (array) $message->getBcc(); + $tos = array_merge($to, $cc, $bcc); + + $message->setBcc([]); + + try { + $sent += $this->sendTo($message, $reversePath, $tos, $failedRecipients); + } finally { + $message->setBcc($bcc); + } + + if ($evt) { + if ($sent == \count($to) + \count($cc) + \count($bcc)) { + $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS); + } elseif ($sent > 0) { + $evt->setResult(Swift_Events_SendEvent::RESULT_TENTATIVE); + } else { + $evt->setResult(Swift_Events_SendEvent::RESULT_FAILED); + } + $evt->setFailedRecipients($failedRecipients); + $this->eventDispatcher->dispatchEvent($evt, 'sendPerformed'); + } + + $message->generateId(); //Make sure a new Message ID is used + + return $sent; + } + + /** + * Stop the SMTP connection. + */ + public function stop() + { + if ($this->started) { + if ($evt = $this->eventDispatcher->createTransportChangeEvent($this)) { + $this->eventDispatcher->dispatchEvent($evt, 'beforeTransportStopped'); + if ($evt->bubbleCancelled()) { + return; + } + } + + try { + $this->executeCommand("QUIT\r\n", [221]); + } catch (Swift_TransportException $e) { + } + + try { + $this->buffer->terminate(); + + if ($evt) { + $this->eventDispatcher->dispatchEvent($evt, 'transportStopped'); + } + } catch (Swift_TransportException $e) { + $this->throwException($e); + } + } + $this->started = false; + } + + /** + * {@inheritdoc} + */ + public function ping() + { + try { + if (!$this->isStarted()) { + $this->start(); + } + + $this->executeCommand("NOOP\r\n", [250]); + } catch (Swift_TransportException $e) { + try { + $this->stop(); + } catch (Swift_TransportException $e) { + } + + return false; + } + + return true; + } + + /** + * Register a plugin. + */ + public function registerPlugin(Swift_Events_EventListener $plugin) + { + $this->eventDispatcher->bindEventListener($plugin); + } + + /** + * Reset the current mail transaction. + */ + public function reset() + { + $this->executeCommand("RSET\r\n", [250], $failures, true); + } + + /** + * Get the IoBuffer where read/writes are occurring. + * + * @return Swift_Transport_IoBuffer + */ + public function getBuffer() + { + return $this->buffer; + } + + /** + * Run a command against the buffer, expecting the given response codes. + * + * If no response codes are given, the response will not be validated. + * If codes are given, an exception will be thrown on an invalid response. + * If the command is RCPT TO, and the pipeline is non-empty, no exception + * will be thrown; instead the failing address is added to $failures. + * + * @param string $command + * @param int[] $codes + * @param string[] $failures An array of failures by-reference + * @param bool $pipeline Do not wait for response + * @param string $address the address, if command is RCPT TO + * + * @return string|null The server response, or null if pipelining is enabled + */ + public function executeCommand($command, $codes = [], &$failures = null, $pipeline = false, $address = null) + { + $failures = (array) $failures; + $seq = $this->buffer->write($command); + if ($evt = $this->eventDispatcher->createCommandEvent($this, $command, $codes)) { + $this->eventDispatcher->dispatchEvent($evt, 'commandSent'); + } + + $this->pipeline[] = [$command, $seq, $codes, $address]; + + if ($pipeline && $this->pipelining) { + return null; + } + + $response = null; + + while ($this->pipeline) { + list($command, $seq, $codes, $address) = array_shift($this->pipeline); + $response = $this->getFullResponse($seq); + try { + $this->assertResponseCode($response, $codes); + } catch (Swift_TransportException $e) { + if ($this->pipeline && $address) { + $failures[] = $address; + } else { + $this->throwException($e); + } + } + } + + return $response; + } + + /** Read the opening SMTP greeting */ + protected function readGreeting() + { + $this->assertResponseCode($this->getFullResponse(0), [220]); + } + + /** Send the HELO welcome */ + protected function doHeloCommand() + { + $this->executeCommand( + sprintf("HELO %s\r\n", $this->domain), [250] + ); + } + + /** Send the MAIL FROM command */ + protected function doMailFromCommand($address) + { + $address = $this->addressEncoder->encodeString($address); + $this->executeCommand( + sprintf("MAIL FROM:<%s>\r\n", $address), [250], $failures, true + ); + } + + /** Send the RCPT TO command */ + protected function doRcptToCommand($address) + { + $address = $this->addressEncoder->encodeString($address); + $this->executeCommand( + sprintf("RCPT TO:<%s>\r\n", $address), [250, 251, 252], $failures, true, $address + ); + } + + /** Send the DATA command */ + protected function doDataCommand(&$failedRecipients) + { + $this->executeCommand("DATA\r\n", [354], $failedRecipients); + } + + /** Stream the contents of the message over the buffer */ + protected function streamMessage(Swift_Mime_SimpleMessage $message) + { + $this->buffer->setWriteTranslations(["\r\n." => "\r\n.."]); + try { + $message->toByteStream($this->buffer); + $this->buffer->flushBuffers(); + } catch (Swift_TransportException $e) { + $this->throwException($e); + } + $this->buffer->setWriteTranslations([]); + $this->executeCommand("\r\n.\r\n", [250]); + } + + /** Determine the best-use reverse path for this message */ + protected function getReversePath(Swift_Mime_SimpleMessage $message) + { + $return = $message->getReturnPath(); + $sender = $message->getSender(); + $from = $message->getFrom(); + $path = null; + if (!empty($return)) { + $path = $return; + } elseif (!empty($sender)) { + // Don't use array_keys + reset($sender); // Reset Pointer to first pos + $path = key($sender); // Get key + } elseif (!empty($from)) { + reset($from); // Reset Pointer to first pos + $path = key($from); // Get key + } + + return $path; + } + + /** Throw a TransportException, first sending it to any listeners */ + protected function throwException(Swift_TransportException $e) + { + if ($evt = $this->eventDispatcher->createTransportExceptionEvent($this, $e)) { + $this->eventDispatcher->dispatchEvent($evt, 'exceptionThrown'); + if (!$evt->bubbleCancelled()) { + throw $e; + } + } else { + throw $e; + } + } + + /** Throws an Exception if a response code is incorrect */ + protected function assertResponseCode($response, $wanted) + { + if (!$response) { + $this->throwException(new Swift_TransportException('Expected response code '.implode('/', $wanted).' but got an empty response')); + } + + list($code) = sscanf($response, '%3d'); + $valid = (empty($wanted) || \in_array($code, $wanted)); + + if ($evt = $this->eventDispatcher->createResponseEvent($this, $response, + $valid)) { + $this->eventDispatcher->dispatchEvent($evt, 'responseReceived'); + } + + if (!$valid) { + $this->throwException(new Swift_TransportException('Expected response code '.implode('/', $wanted).' but got code "'.$code.'", with message "'.$response.'"', $code)); + } + } + + /** Get an entire multi-line response using its sequence number */ + protected function getFullResponse($seq) + { + $response = ''; + try { + do { + $line = $this->buffer->readLine($seq); + $response .= $line; + } while (null !== $line && false !== $line && ' ' != $line[3]); + } catch (Swift_TransportException $e) { + $this->throwException($e); + } catch (Swift_IoException $e) { + $this->throwException(new Swift_TransportException($e->getMessage(), 0, $e)); + } + + return $response; + } + + /** Send an email to the given recipients from the given reverse path */ + private function doMailTransaction($message, $reversePath, array $recipients, array &$failedRecipients) + { + $sent = 0; + $this->doMailFromCommand($reversePath); + foreach ($recipients as $forwardPath) { + try { + $this->doRcptToCommand($forwardPath); + ++$sent; + } catch (Swift_TransportException $e) { + $failedRecipients[] = $forwardPath; + } catch (Swift_AddressEncoderException $e) { + $failedRecipients[] = $forwardPath; + } + } + + if (0 != $sent) { + $sent += \count($failedRecipients); + $this->doDataCommand($failedRecipients); + $sent -= \count($failedRecipients); + + $this->streamMessage($message); + } else { + $this->reset(); + } + + return $sent; + } + + /** Send a message to the given To: recipients */ + private function sendTo(Swift_Mime_SimpleMessage $message, $reversePath, array $to, array &$failedRecipients) + { + if (empty($to)) { + return 0; + } + + return $this->doMailTransaction($message, $reversePath, array_keys($to), + $failedRecipients); + } + + /** + * Destructor. + */ + public function __destruct() + { + try { + $this->stop(); + } catch (Exception $e) { + } + } + + public function __sleep() + { + throw new \BadMethodCallException('Cannot serialize '.__CLASS__); + } + + public function __wakeup() + { + throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/CramMd5Authenticator.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/CramMd5Authenticator.php index 1c577324ced..bb3a1615096 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/CramMd5Authenticator.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/CramMd5Authenticator.php @@ -15,61 +15,61 @@ */ class Swift_Transport_Esmtp_Auth_CramMd5Authenticator implements Swift_Transport_Esmtp_Authenticator { - /** - * Get the name of the AUTH mechanism this Authenticator handles. - * - * @return string - */ - public function getAuthKeyword() - { - return 'CRAM-MD5'; - } + /** + * Get the name of the AUTH mechanism this Authenticator handles. + * + * @return string + */ + public function getAuthKeyword() + { + return 'CRAM-MD5'; + } - /** - * {@inheritdoc} - */ - public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password) - { - try { - $challenge = $agent->executeCommand("AUTH CRAM-MD5\r\n", [334]); - $challenge = base64_decode(substr($challenge, 4)); - $message = base64_encode( - $username.' '.$this->getResponse($password, $challenge) - ); - $agent->executeCommand(sprintf("%s\r\n", $message), [235]); + /** + * {@inheritdoc} + */ + public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password) + { + try { + $challenge = $agent->executeCommand("AUTH CRAM-MD5\r\n", [334]); + $challenge = base64_decode(substr($challenge, 4)); + $message = base64_encode( + $username.' '.$this->getResponse($password, $challenge) + ); + $agent->executeCommand(sprintf("%s\r\n", $message), [235]); - return true; - } catch (Swift_TransportException $e) { - $agent->executeCommand("RSET\r\n", [250]); + return true; + } catch (Swift_TransportException $e) { + $agent->executeCommand("RSET\r\n", [250]); - throw $e; - } - } + throw $e; + } + } - /** - * Generate a CRAM-MD5 response from a server challenge. - * - * @param string $secret - * @param string $challenge - * - * @return string - */ - private function getResponse($secret, $challenge) - { - if (\strlen($secret) > 64) { - $secret = pack('H32', md5($secret)); - } + /** + * Generate a CRAM-MD5 response from a server challenge. + * + * @param string $secret + * @param string $challenge + * + * @return string + */ + private function getResponse($secret, $challenge) + { + if (\strlen($secret) > 64) { + $secret = pack('H32', md5($secret)); + } - if (\strlen($secret) < 64) { - $secret = str_pad($secret, 64, \chr(0)); - } + if (\strlen($secret) < 64) { + $secret = str_pad($secret, 64, \chr(0)); + } - $k_ipad = substr($secret, 0, 64) ^ str_repeat(\chr(0x36), 64); - $k_opad = substr($secret, 0, 64) ^ str_repeat(\chr(0x5C), 64); + $k_ipad = substr($secret, 0, 64) ^ str_repeat(\chr(0x36), 64); + $k_opad = substr($secret, 0, 64) ^ str_repeat(\chr(0x5C), 64); - $inner = pack('H32', md5($k_ipad.$challenge)); - $digest = md5($k_opad.$inner); + $inner = pack('H32', md5($k_ipad.$challenge)); + $digest = md5($k_opad.$inner); - return $digest; - } + return $digest; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/LoginAuthenticator.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/LoginAuthenticator.php index 22e9ac723fd..0b9d81b8ad6 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/LoginAuthenticator.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/LoginAuthenticator.php @@ -15,31 +15,31 @@ */ class Swift_Transport_Esmtp_Auth_LoginAuthenticator implements Swift_Transport_Esmtp_Authenticator { - /** - * Get the name of the AUTH mechanism this Authenticator handles. - * - * @return string - */ - public function getAuthKeyword() - { - return 'LOGIN'; - } + /** + * Get the name of the AUTH mechanism this Authenticator handles. + * + * @return string + */ + public function getAuthKeyword() + { + return 'LOGIN'; + } - /** - * {@inheritdoc} - */ - public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password) - { - try { - $agent->executeCommand("AUTH LOGIN\r\n", [334]); - $agent->executeCommand(sprintf("%s\r\n", base64_encode($username ?? '')), [334]); - $agent->executeCommand(sprintf("%s\r\n", base64_encode($password ?? '')), [235]); + /** + * {@inheritdoc} + */ + public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password) + { + try { + $agent->executeCommand("AUTH LOGIN\r\n", [334]); + $agent->executeCommand(sprintf("%s\r\n", base64_encode($username ?? '')), [334]); + $agent->executeCommand(sprintf("%s\r\n", base64_encode($password ?? '')), [235]); - return true; - } catch (Swift_TransportException $e) { - $agent->executeCommand("RSET\r\n", [250]); + return true; + } catch (Swift_TransportException $e) { + $agent->executeCommand("RSET\r\n", [250]); - throw $e; - } - } + throw $e; + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/NTLMAuthenticator.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/NTLMAuthenticator.php index dfccdecf200..41931fdd226 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/NTLMAuthenticator.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/NTLMAuthenticator.php @@ -17,665 +17,665 @@ */ class Swift_Transport_Esmtp_Auth_NTLMAuthenticator implements Swift_Transport_Esmtp_Authenticator { - const NTLMSIG = "NTLMSSP\x00"; - const DESCONST = 'KGS!@#$%'; - - /** - * Get the name of the AUTH mechanism this Authenticator handles. - * - * @return string - */ - public function getAuthKeyword() - { - return 'NTLM'; - } - - /** - * {@inheritdoc} - * - * @throws \LogicException - */ - public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password) - { - if (!\function_exists('openssl_encrypt')) { - throw new LogicException('The OpenSSL extension must be enabled to use the NTLM authenticator.'); - } - - if (!\function_exists('bcmul')) { - throw new LogicException('The BCMath functions must be enabled to use the NTLM authenticator.'); - } - - try { - // execute AUTH command and filter out the code at the beginning - // AUTH NTLM xxxx - $response = base64_decode(substr(trim($this->sendMessage1($agent) ?? ''), 4)); - - // extra parameters for our unit cases - $timestamp = \func_num_args() > 3 ? func_get_arg(3) : $this->getCorrectTimestamp(bcmul(microtime(true), '1000')); - $client = \func_num_args() > 4 ? func_get_arg(4) : random_bytes(8); - - // Message 3 response - $this->sendMessage3($response, $username, $password, $timestamp, $client, $agent); - - return true; - } catch (Swift_TransportException $e) { - $agent->executeCommand("RSET\r\n", [250]); - - throw $e; - } - } - - protected function si2bin($si, $bits = 32) - { - $bin = null; - if ($si >= -2 ** ($bits - 1) && ($si <= 2 ** ($bits - 1))) { - // positive or zero - if ($si >= 0) { - $bin = base_convert($si, 10, 2); - // pad to $bits bit - $bin_length = \strlen($bin); - if ($bin_length < $bits) { - $bin = str_repeat('0', $bits - $bin_length).$bin; - } - } else { - // negative - $si = -$si - 2 ** $bits; - $bin = base_convert($si, 10, 2); - $bin_length = \strlen($bin); - if ($bin_length > $bits) { - $bin = str_repeat('1', $bits - $bin_length).$bin; - } - } - } - - return $bin; - } - - /** - * Send our auth message and returns the response. - * - * @return string SMTP Response - */ - protected function sendMessage1(Swift_Transport_SmtpAgent $agent) - { - $message = $this->createMessage1(); - - return $agent->executeCommand(sprintf("AUTH %s %s\r\n", $this->getAuthKeyword(), base64_encode($message)), [334]); - } - - /** - * Fetch all details of our response (message 2). - * - * @param string $response - * - * @return array our response parsed - */ - protected function parseMessage2($response) - { - $responseHex = bin2hex($response); - $length = floor(hexdec(substr($responseHex, 28, 4)) / 256) * 2; - $offset = floor(hexdec(substr($responseHex, 32, 4)) / 256) * 2; - $challenge = hex2bin(substr($responseHex, 48, 16)); - $context = hex2bin(substr($responseHex, 64, 16)); - $targetInfoH = hex2bin(substr($responseHex, 80, 16)); - $targetName = hex2bin(substr($responseHex, $offset, $length)); - $offset = floor(hexdec(substr($responseHex, 88, 4)) / 256) * 2; - $targetInfoBlock = substr($responseHex, $offset); - list($domainName, $serverName, $DNSDomainName, $DNSServerName, $terminatorByte) = $this->readSubBlock($targetInfoBlock); - - return [ - $challenge, - $context, - $targetInfoH, - $targetName, - $domainName, - $serverName, - $DNSDomainName, - $DNSServerName, - hex2bin($targetInfoBlock), - $terminatorByte, - ]; - } - - /** - * Read the blob information in from message2. - * - * @return array - */ - protected function readSubBlock($block) - { - // remove terminatorByte cause it's always the same - $block = substr($block, 0, -8); - - $length = \strlen($block); - $offset = 0; - $data = []; - while ($offset < $length) { - $blockLength = hexdec(substr(substr($block, $offset, 8), -4)) / 256; - $offset += 8; - $data[] = hex2bin(substr($block, $offset, $blockLength * 2)); - $offset += $blockLength * 2; - } - - if (3 == \count($data)) { - $data[] = $data[2]; - $data[2] = ''; - } - - $data[] = $this->createByte('00'); - - return $data; - } - - /** - * Send our final message with all our data. - * - * @param string $response Message 1 response (message 2) - * @param string $username - * @param string $password - * @param string $timestamp - * @param string $client - * @param bool $v2 Use version2 of the protocol - * - * @return string - */ - protected function sendMessage3($response, $username, $password, $timestamp, $client, Swift_Transport_SmtpAgent $agent, $v2 = true) - { - list($domain, $username) = $this->getDomainAndUsername($username); - //$challenge, $context, $targetInfoH, $targetName, $domainName, $workstation, $DNSDomainName, $DNSServerName, $blob, $ter - list($challenge, , , , , $workstation, , , $blob) = $this->parseMessage2($response); - - if (!$v2) { - // LMv1 - $lmResponse = $this->createLMPassword($password, $challenge); - // NTLMv1 - $ntlmResponse = $this->createNTLMPassword($password, $challenge); - } else { - // LMv2 - $lmResponse = $this->createLMv2Password($password, $username, $domain, $challenge, $client); - // NTLMv2 - $ntlmResponse = $this->createNTLMv2Hash($password, $username, $domain, $challenge, $blob, $timestamp, $client); - } - - $message = $this->createMessage3($domain, $username, $workstation, $lmResponse, $ntlmResponse); - - return $agent->executeCommand(sprintf("%s\r\n", base64_encode($message)), [235]); - } - - /** - * Create our message 1. - * - * @return string - */ - protected function createMessage1() - { - return self::NTLMSIG - .$this->createByte('01') // Message 1 - .$this->createByte('0702'); // Flags - } - - /** - * Create our message 3. - * - * @param string $domain - * @param string $username - * @param string $workstation - * @param string $lmResponse - * @param string $ntlmResponse - * - * @return string - */ - protected function createMessage3($domain, $username, $workstation, $lmResponse, $ntlmResponse) - { - // Create security buffers - $domainSec = $this->createSecurityBuffer($domain, 64); - $domainInfo = $this->readSecurityBuffer(bin2hex($domainSec)); - $userSec = $this->createSecurityBuffer($username, ($domainInfo[0] + $domainInfo[1]) / 2); - $userInfo = $this->readSecurityBuffer(bin2hex($userSec)); - $workSec = $this->createSecurityBuffer($workstation, ($userInfo[0] + $userInfo[1]) / 2); - $workInfo = $this->readSecurityBuffer(bin2hex($workSec)); - $lmSec = $this->createSecurityBuffer($lmResponse, ($workInfo[0] + $workInfo[1]) / 2, true); - $lmInfo = $this->readSecurityBuffer(bin2hex($lmSec)); - $ntlmSec = $this->createSecurityBuffer($ntlmResponse, ($lmInfo[0] + $lmInfo[1]) / 2, true); - - return self::NTLMSIG - .$this->createByte('03') // TYPE 3 message - .$lmSec // LM response header - .$ntlmSec // NTLM response header - .$domainSec // Domain header - .$userSec // User header - .$workSec // Workstation header - .$this->createByte('000000009a', 8) // session key header (empty) - .$this->createByte('01020000') // FLAGS - .$this->convertTo16bit($domain) // domain name - .$this->convertTo16bit($username) // username - .$this->convertTo16bit($workstation) // workstation - .$lmResponse - .$ntlmResponse; - } - - /** - * @param string $timestamp Epoch timestamp in microseconds - * @param string $client Random bytes - * @param string $targetInfo - * - * @return string - */ - protected function createBlob($timestamp, $client, $targetInfo) - { - return $this->createByte('0101') - .$this->createByte('00') - .$timestamp - .$client - .$this->createByte('00') - .$targetInfo - .$this->createByte('00'); - } - - /** - * Get domain and username from our username. - * - * @example DOMAIN\username - * - * @param string $name - * - * @return array - */ - protected function getDomainAndUsername($name) - { - if (false !== strpos($name, '\\')) { - return explode('\\', $name); - } - - if (false !== strpos($name, '@')) { - list($user, $domain) = explode('@', $name); - - return [$domain, $user]; - } - - // no domain passed - return ['', $name]; - } - - /** - * Create LMv1 response. - * - * @param string $password - * @param string $challenge - * - * @return string - */ - protected function createLMPassword($password, $challenge) - { - // FIRST PART - $password = $this->createByte(strtoupper($password), 14, false); - list($key1, $key2) = str_split($password, 7); - - $desKey1 = $this->createDesKey($key1); - $desKey2 = $this->createDesKey($key2); - - $constantDecrypt = $this->createByte($this->desEncrypt(self::DESCONST, $desKey1).$this->desEncrypt(self::DESCONST, $desKey2), 21, false); - - // SECOND PART - list($key1, $key2, $key3) = str_split($constantDecrypt, 7); - - $desKey1 = $this->createDesKey($key1); - $desKey2 = $this->createDesKey($key2); - $desKey3 = $this->createDesKey($key3); - - return $this->desEncrypt($challenge, $desKey1).$this->desEncrypt($challenge, $desKey2).$this->desEncrypt($challenge, $desKey3); - } - - /** - * Create NTLMv1 response. - * - * @param string $password - * @param string $challenge - * - * @return string - */ - protected function createNTLMPassword($password, $challenge) - { - // FIRST PART - $ntlmHash = $this->createByte($this->md4Encrypt($password), 21, false); - list($key1, $key2, $key3) = str_split($ntlmHash, 7); - - $desKey1 = $this->createDesKey($key1); - $desKey2 = $this->createDesKey($key2); - $desKey3 = $this->createDesKey($key3); - - return $this->desEncrypt($challenge, $desKey1).$this->desEncrypt($challenge, $desKey2).$this->desEncrypt($challenge, $desKey3); - } - - /** - * Convert a normal timestamp to a tenth of a microtime epoch time. - * - * @param string $time - * - * @return string - */ - protected function getCorrectTimestamp($time) - { - // Get our timestamp (tricky!) - $time = number_format($time, 0, '.', ''); // save microtime to string - $time = bcadd($time, '11644473600000', 0); // add epoch time - $time = bcmul($time, 10000, 0); // tenths of a microsecond. - - $binary = $this->si2bin($time, 64); // create 64 bit binary string - $timestamp = ''; - for ($i = 0; $i < 8; ++$i) { - $timestamp .= \chr(bindec(substr($binary, -(($i + 1) * 8), 8))); - } - - return $timestamp; - } - - /** - * Create LMv2 response. - * - * @param string $password - * @param string $username - * @param string $domain - * @param string $challenge NTLM Challenge - * @param string $client Random string - * - * @return string - */ - protected function createLMv2Password($password, $username, $domain, $challenge, $client) - { - $lmPass = '00'; // by default 00 - // if $password > 15 than we can't use this method - if (\strlen($password) <= 15) { - $ntlmHash = $this->md4Encrypt($password); - $ntml2Hash = $this->md5Encrypt($ntlmHash, $this->convertTo16bit(strtoupper($username).$domain)); - - $lmPass = bin2hex($this->md5Encrypt($ntml2Hash, $challenge.$client).$client); - } - - return $this->createByte($lmPass, 24); - } - - /** - * Create NTLMv2 response. - * - * @param string $password - * @param string $username - * @param string $domain - * @param string $challenge Hex values - * @param string $targetInfo Hex values - * @param string $timestamp - * @param string $client Random bytes - * - * @return string - * - * @see http://davenport.sourceforge.net/ntlm.html#theNtlmResponse - */ - protected function createNTLMv2Hash($password, $username, $domain, $challenge, $targetInfo, $timestamp, $client) - { - $ntlmHash = $this->md4Encrypt($password); - $ntml2Hash = $this->md5Encrypt($ntlmHash, $this->convertTo16bit(strtoupper($username).$domain)); - - // create blob - $blob = $this->createBlob($timestamp, $client, $targetInfo); - - $ntlmv2Response = $this->md5Encrypt($ntml2Hash, $challenge.$blob); - - return $ntlmv2Response.$blob; - } - - protected function createDesKey($key) - { - $material = [bin2hex($key[0])]; - $len = \strlen($key); - for ($i = 1; $i < $len; ++$i) { - list($high, $low) = str_split(bin2hex($key[$i])); - $v = $this->castToByte(\ord($key[$i - 1]) << (7 + 1 - $i) | $this->uRShift(hexdec(dechex(hexdec($high) & 0xf).dechex(hexdec($low) & 0xf)), $i)); - $material[] = str_pad(substr(dechex($v), -2), 2, '0', STR_PAD_LEFT); // cast to byte - } - $material[] = str_pad(substr(dechex($this->castToByte(\ord($key[6]) << 1)), -2), 2, '0'); - - // odd parity - foreach ($material as $k => $v) { - $b = $this->castToByte(hexdec($v)); - $needsParity = 0 == (($this->uRShift($b, 7) ^ $this->uRShift($b, 6) ^ $this->uRShift($b, 5) - ^ $this->uRShift($b, 4) ^ $this->uRShift($b, 3) ^ $this->uRShift($b, 2) - ^ $this->uRShift($b, 1)) & 0x01); - - list($high, $low) = str_split($v); - if ($needsParity) { - $material[$k] = dechex(hexdec($high) | 0x0).dechex(hexdec($low) | 0x1); - } else { - $material[$k] = dechex(hexdec($high) & 0xf).dechex(hexdec($low) & 0xe); - } - } - - return hex2bin(implode('', $material)); - } - - /** HELPER FUNCTIONS */ - - /** - * Create our security buffer depending on length and offset. - * - * @param string $value Value we want to put in - * @param int $offset start of value - * @param bool $is16 Do we 16bit string or not? - * - * @return string - */ - protected function createSecurityBuffer($value, $offset, $is16 = false) - { - $length = \strlen(bin2hex($value)); - $length = $is16 ? $length / 2 : $length; - $length = $this->createByte(str_pad(dechex($length), 2, '0', STR_PAD_LEFT), 2); - - return $length.$length.$this->createByte(dechex($offset), 4); - } - - /** - * Read our security buffer to fetch length and offset of our value. - * - * @param string $value Securitybuffer in hex - * - * @return array array with length and offset - */ - protected function readSecurityBuffer($value) - { - $length = floor(hexdec(substr($value, 0, 4)) / 256) * 2; - $offset = floor(hexdec(substr($value, 8, 4)) / 256) * 2; - - return [$length, $offset]; - } - - /** - * Cast to byte java equivalent to (byte). - * - * @param int $v - * - * @return int - */ - protected function castToByte($v) - { - return (($v + 128) % 256) - 128; - } - - /** - * Java unsigned right bitwise - * $a >>> $b. - * - * @param int $a - * @param int $b - * - * @return int - */ - protected function uRShift($a, $b) - { - if (0 == $b) { - return $a; - } - - return ($a >> $b) & ~(1 << (8 * PHP_INT_SIZE - 1) >> ($b - 1)); - } - - /** - * Right padding with 0 to certain length. - * - * @param string $input - * @param int $bytes Length of bytes - * @param bool $isHex Did we provided hex value - * - * @return string - */ - protected function createByte($input, $bytes = 4, $isHex = true) - { - if ($isHex) { - $byte = hex2bin(str_pad($input, $bytes * 2, '00')); - } else { - $byte = str_pad($input, $bytes, "\x00"); - } - - return $byte; - } - - /** ENCRYPTION ALGORITHMS */ - - /** - * DES Encryption. - * - * @param string $value An 8-byte string - * @param string $key - * - * @return string - */ - protected function desEncrypt($value, $key) - { - return substr(openssl_encrypt($value, 'DES-ECB', $key, \OPENSSL_RAW_DATA), 0, 8); - } - - /** - * MD5 Encryption. - * - * @param string $key Encryption key - * @param string $msg Message to encrypt - * - * @return string - */ - protected function md5Encrypt($key, $msg) - { - $blocksize = 64; - if (\strlen($key) > $blocksize) { - $key = pack('H*', md5($key)); - } - - $key = str_pad($key, $blocksize, "\0"); - $ipadk = $key ^ str_repeat("\x36", $blocksize); - $opadk = $key ^ str_repeat("\x5c", $blocksize); - - return pack('H*', md5($opadk.pack('H*', md5($ipadk.$msg)))); - } - - /** - * MD4 Encryption. - * - * @param string $input - * - * @return string - * - * @see https://secure.php.net/manual/en/ref.hash.php - */ - protected function md4Encrypt($input) - { - $input = $this->convertTo16bit($input); - - return \function_exists('hash') ? hex2bin(hash('md4', $input)) : mhash(MHASH_MD4, $input); - } - - /** - * Convert UTF-8 to UTF-16. - * - * @param string $input - * - * @return string - */ - protected function convertTo16bit($input) - { - return iconv('UTF-8', 'UTF-16LE', $input); - } - - /** - * @param string $message - */ - protected function debug($message) - { - $message = bin2hex($message); - $messageId = substr($message, 16, 8); - echo substr($message, 0, 16)." NTLMSSP Signature
\n"; - echo $messageId." Type Indicator
\n"; - - if ('02000000' == $messageId) { - $map = [ - 'Challenge', - 'Context', - 'Target Information Security Buffer', - 'Target Name Data', - 'NetBIOS Domain Name', - 'NetBIOS Server Name', - 'DNS Domain Name', - 'DNS Server Name', - 'BLOB', - 'Target Information Terminator', - ]; - - $data = $this->parseMessage2(hex2bin($message)); - - foreach ($map as $key => $value) { - echo bin2hex($data[$key]).' - '.$data[$key].' ||| '.$value."
\n"; - } - } elseif ('03000000' == $messageId) { - $i = 0; - $data[$i++] = substr($message, 24, 16); - list($lmLength, $lmOffset) = $this->readSecurityBuffer($data[$i - 1]); - - $data[$i++] = substr($message, 40, 16); - list($ntmlLength, $ntmlOffset) = $this->readSecurityBuffer($data[$i - 1]); - - $data[$i++] = substr($message, 56, 16); - list($targetLength, $targetOffset) = $this->readSecurityBuffer($data[$i - 1]); - - $data[$i++] = substr($message, 72, 16); - list($userLength, $userOffset) = $this->readSecurityBuffer($data[$i - 1]); - - $data[$i++] = substr($message, 88, 16); - list($workLength, $workOffset) = $this->readSecurityBuffer($data[$i - 1]); - - $data[$i++] = substr($message, 104, 16); - $data[$i++] = substr($message, 120, 8); - $data[$i++] = substr($message, $targetOffset, $targetLength); - $data[$i++] = substr($message, $userOffset, $userLength); - $data[$i++] = substr($message, $workOffset, $workLength); - $data[$i++] = substr($message, $lmOffset, $lmLength); - $data[$i] = substr($message, $ntmlOffset, $ntmlLength); - - $map = [ - 'LM Response Security Buffer', - 'NTLM Response Security Buffer', - 'Target Name Security Buffer', - 'User Name Security Buffer', - 'Workstation Name Security Buffer', - 'Session Key Security Buffer', - 'Flags', - 'Target Name Data', - 'User Name Data', - 'Workstation Name Data', - 'LM Response Data', - 'NTLM Response Data', - ]; - - foreach ($map as $key => $value) { - echo $data[$key].' - '.hex2bin($data[$key]).' ||| '.$value."
\n"; - } - } - - echo '

'; - } + const NTLMSIG = "NTLMSSP\x00"; + const DESCONST = 'KGS!@#$%'; + + /** + * Get the name of the AUTH mechanism this Authenticator handles. + * + * @return string + */ + public function getAuthKeyword() + { + return 'NTLM'; + } + + /** + * {@inheritdoc} + * + * @throws \LogicException + */ + public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password) + { + if (!\function_exists('openssl_encrypt')) { + throw new LogicException('The OpenSSL extension must be enabled to use the NTLM authenticator.'); + } + + if (!\function_exists('bcmul')) { + throw new LogicException('The BCMath functions must be enabled to use the NTLM authenticator.'); + } + + try { + // execute AUTH command and filter out the code at the beginning + // AUTH NTLM xxxx + $response = base64_decode(substr(trim($this->sendMessage1($agent) ?? ''), 4)); + + // extra parameters for our unit cases + $timestamp = \func_num_args() > 3 ? func_get_arg(3) : $this->getCorrectTimestamp(bcmul(microtime(true), '1000')); + $client = \func_num_args() > 4 ? func_get_arg(4) : random_bytes(8); + + // Message 3 response + $this->sendMessage3($response, $username, $password, $timestamp, $client, $agent); + + return true; + } catch (Swift_TransportException $e) { + $agent->executeCommand("RSET\r\n", [250]); + + throw $e; + } + } + + protected function si2bin($si, $bits = 32) + { + $bin = null; + if ($si >= -2 ** ($bits - 1) && ($si <= 2 ** ($bits - 1))) { + // positive or zero + if ($si >= 0) { + $bin = base_convert($si, 10, 2); + // pad to $bits bit + $bin_length = \strlen($bin); + if ($bin_length < $bits) { + $bin = str_repeat('0', $bits - $bin_length).$bin; + } + } else { + // negative + $si = -$si - 2 ** $bits; + $bin = base_convert($si, 10, 2); + $bin_length = \strlen($bin); + if ($bin_length > $bits) { + $bin = str_repeat('1', $bits - $bin_length).$bin; + } + } + } + + return $bin; + } + + /** + * Send our auth message and returns the response. + * + * @return string SMTP Response + */ + protected function sendMessage1(Swift_Transport_SmtpAgent $agent) + { + $message = $this->createMessage1(); + + return $agent->executeCommand(sprintf("AUTH %s %s\r\n", $this->getAuthKeyword(), base64_encode($message)), [334]); + } + + /** + * Fetch all details of our response (message 2). + * + * @param string $response + * + * @return array our response parsed + */ + protected function parseMessage2($response) + { + $responseHex = bin2hex($response); + $length = floor(hexdec(substr($responseHex, 28, 4)) / 256) * 2; + $offset = floor(hexdec(substr($responseHex, 32, 4)) / 256) * 2; + $challenge = hex2bin(substr($responseHex, 48, 16)); + $context = hex2bin(substr($responseHex, 64, 16)); + $targetInfoH = hex2bin(substr($responseHex, 80, 16)); + $targetName = hex2bin(substr($responseHex, $offset, $length)); + $offset = floor(hexdec(substr($responseHex, 88, 4)) / 256) * 2; + $targetInfoBlock = substr($responseHex, $offset); + list($domainName, $serverName, $DNSDomainName, $DNSServerName, $terminatorByte) = $this->readSubBlock($targetInfoBlock); + + return [ + $challenge, + $context, + $targetInfoH, + $targetName, + $domainName, + $serverName, + $DNSDomainName, + $DNSServerName, + hex2bin($targetInfoBlock), + $terminatorByte, + ]; + } + + /** + * Read the blob information in from message2. + * + * @return array + */ + protected function readSubBlock($block) + { + // remove terminatorByte cause it's always the same + $block = substr($block, 0, -8); + + $length = \strlen($block); + $offset = 0; + $data = []; + while ($offset < $length) { + $blockLength = hexdec(substr(substr($block, $offset, 8), -4)) / 256; + $offset += 8; + $data[] = hex2bin(substr($block, $offset, $blockLength * 2)); + $offset += $blockLength * 2; + } + + if (3 == \count($data)) { + $data[] = $data[2]; + $data[2] = ''; + } + + $data[] = $this->createByte('00'); + + return $data; + } + + /** + * Send our final message with all our data. + * + * @param string $response Message 1 response (message 2) + * @param string $username + * @param string $password + * @param string $timestamp + * @param string $client + * @param bool $v2 Use version2 of the protocol + * + * @return string + */ + protected function sendMessage3($response, $username, $password, $timestamp, $client, Swift_Transport_SmtpAgent $agent, $v2 = true) + { + list($domain, $username) = $this->getDomainAndUsername($username); + //$challenge, $context, $targetInfoH, $targetName, $domainName, $workstation, $DNSDomainName, $DNSServerName, $blob, $ter + list($challenge, , , , , $workstation, , , $blob) = $this->parseMessage2($response); + + if (!$v2) { + // LMv1 + $lmResponse = $this->createLMPassword($password, $challenge); + // NTLMv1 + $ntlmResponse = $this->createNTLMPassword($password, $challenge); + } else { + // LMv2 + $lmResponse = $this->createLMv2Password($password, $username, $domain, $challenge, $client); + // NTLMv2 + $ntlmResponse = $this->createNTLMv2Hash($password, $username, $domain, $challenge, $blob, $timestamp, $client); + } + + $message = $this->createMessage3($domain, $username, $workstation, $lmResponse, $ntlmResponse); + + return $agent->executeCommand(sprintf("%s\r\n", base64_encode($message)), [235]); + } + + /** + * Create our message 1. + * + * @return string + */ + protected function createMessage1() + { + return self::NTLMSIG + .$this->createByte('01') // Message 1 +.$this->createByte('0702'); // Flags + } + + /** + * Create our message 3. + * + * @param string $domain + * @param string $username + * @param string $workstation + * @param string $lmResponse + * @param string $ntlmResponse + * + * @return string + */ + protected function createMessage3($domain, $username, $workstation, $lmResponse, $ntlmResponse) + { + // Create security buffers + $domainSec = $this->createSecurityBuffer($domain, 64); + $domainInfo = $this->readSecurityBuffer(bin2hex($domainSec)); + $userSec = $this->createSecurityBuffer($username, ($domainInfo[0] + $domainInfo[1]) / 2); + $userInfo = $this->readSecurityBuffer(bin2hex($userSec)); + $workSec = $this->createSecurityBuffer($workstation, ($userInfo[0] + $userInfo[1]) / 2); + $workInfo = $this->readSecurityBuffer(bin2hex($workSec)); + $lmSec = $this->createSecurityBuffer($lmResponse, ($workInfo[0] + $workInfo[1]) / 2, true); + $lmInfo = $this->readSecurityBuffer(bin2hex($lmSec)); + $ntlmSec = $this->createSecurityBuffer($ntlmResponse, ($lmInfo[0] + $lmInfo[1]) / 2, true); + + return self::NTLMSIG + .$this->createByte('03') // TYPE 3 message +.$lmSec // LM response header +.$ntlmSec // NTLM response header +.$domainSec // Domain header +.$userSec // User header +.$workSec // Workstation header +.$this->createByte('000000009a', 8) // session key header (empty) +.$this->createByte('01020000') // FLAGS +.$this->convertTo16bit($domain) // domain name +.$this->convertTo16bit($username) // username +.$this->convertTo16bit($workstation) // workstation +.$lmResponse + .$ntlmResponse; + } + + /** + * @param string $timestamp Epoch timestamp in microseconds + * @param string $client Random bytes + * @param string $targetInfo + * + * @return string + */ + protected function createBlob($timestamp, $client, $targetInfo) + { + return $this->createByte('0101') + .$this->createByte('00') + .$timestamp + .$client + .$this->createByte('00') + .$targetInfo + .$this->createByte('00'); + } + + /** + * Get domain and username from our username. + * + * @example DOMAIN\username + * + * @param string $name + * + * @return array + */ + protected function getDomainAndUsername($name) + { + if (false !== strpos($name, '\\')) { + return explode('\\', $name); + } + + if (false !== strpos($name, '@')) { + list($user, $domain) = explode('@', $name); + + return [$domain, $user]; + } + + // no domain passed + return ['', $name]; + } + + /** + * Create LMv1 response. + * + * @param string $password + * @param string $challenge + * + * @return string + */ + protected function createLMPassword($password, $challenge) + { + // FIRST PART + $password = $this->createByte(strtoupper($password), 14, false); + list($key1, $key2) = str_split($password, 7); + + $desKey1 = $this->createDesKey($key1); + $desKey2 = $this->createDesKey($key2); + + $constantDecrypt = $this->createByte($this->desEncrypt(self::DESCONST, $desKey1).$this->desEncrypt(self::DESCONST, $desKey2), 21, false); + + // SECOND PART + list($key1, $key2, $key3) = str_split($constantDecrypt, 7); + + $desKey1 = $this->createDesKey($key1); + $desKey2 = $this->createDesKey($key2); + $desKey3 = $this->createDesKey($key3); + + return $this->desEncrypt($challenge, $desKey1).$this->desEncrypt($challenge, $desKey2).$this->desEncrypt($challenge, $desKey3); + } + + /** + * Create NTLMv1 response. + * + * @param string $password + * @param string $challenge + * + * @return string + */ + protected function createNTLMPassword($password, $challenge) + { + // FIRST PART + $ntlmHash = $this->createByte($this->md4Encrypt($password), 21, false); + list($key1, $key2, $key3) = str_split($ntlmHash, 7); + + $desKey1 = $this->createDesKey($key1); + $desKey2 = $this->createDesKey($key2); + $desKey3 = $this->createDesKey($key3); + + return $this->desEncrypt($challenge, $desKey1).$this->desEncrypt($challenge, $desKey2).$this->desEncrypt($challenge, $desKey3); + } + + /** + * Convert a normal timestamp to a tenth of a microtime epoch time. + * + * @param string $time + * + * @return string + */ + protected function getCorrectTimestamp($time) + { + // Get our timestamp (tricky!) + $time = number_format($time, 0, '.', ''); // save microtime to string + $time = bcadd($time, '11644473600000', 0); // add epoch time + $time = bcmul($time, 10000, 0); // tenths of a microsecond. + + $binary = $this->si2bin($time, 64); // create 64 bit binary string + $timestamp = ''; + for ($i = 0; $i < 8; ++$i) { + $timestamp .= \chr(bindec(substr($binary, -(($i + 1) * 8), 8))); + } + + return $timestamp; + } + + /** + * Create LMv2 response. + * + * @param string $password + * @param string $username + * @param string $domain + * @param string $challenge NTLM Challenge + * @param string $client Random string + * + * @return string + */ + protected function createLMv2Password($password, $username, $domain, $challenge, $client) + { + $lmPass = '00'; // by default 00 + // if $password > 15 than we can't use this method + if (\strlen($password) <= 15) { + $ntlmHash = $this->md4Encrypt($password); + $ntml2Hash = $this->md5Encrypt($ntlmHash, $this->convertTo16bit(strtoupper($username).$domain)); + + $lmPass = bin2hex($this->md5Encrypt($ntml2Hash, $challenge.$client).$client); + } + + return $this->createByte($lmPass, 24); + } + + /** + * Create NTLMv2 response. + * + * @param string $password + * @param string $username + * @param string $domain + * @param string $challenge Hex values + * @param string $targetInfo Hex values + * @param string $timestamp + * @param string $client Random bytes + * + * @return string + * + * @see http://davenport.sourceforge.net/ntlm.html#theNtlmResponse + */ + protected function createNTLMv2Hash($password, $username, $domain, $challenge, $targetInfo, $timestamp, $client) + { + $ntlmHash = $this->md4Encrypt($password); + $ntml2Hash = $this->md5Encrypt($ntlmHash, $this->convertTo16bit(strtoupper($username).$domain)); + + // create blob + $blob = $this->createBlob($timestamp, $client, $targetInfo); + + $ntlmv2Response = $this->md5Encrypt($ntml2Hash, $challenge.$blob); + + return $ntlmv2Response.$blob; + } + + protected function createDesKey($key) + { + $material = [bin2hex($key[0])]; + $len = \strlen($key); + for ($i = 1; $i < $len; ++$i) { + list($high, $low) = str_split(bin2hex($key[$i])); + $v = $this->castToByte(\ord($key[$i - 1]) << (7 + 1 - $i) | $this->uRShift(hexdec(dechex(hexdec($high) & 0xf).dechex(hexdec($low) & 0xf)), $i)); + $material[] = str_pad(substr(dechex($v), -2), 2, '0', STR_PAD_LEFT); // cast to byte + } + $material[] = str_pad(substr(dechex($this->castToByte(\ord($key[6]) << 1)), -2), 2, '0'); + + // odd parity + foreach ($material as $k => $v) { + $b = $this->castToByte(hexdec($v)); + $needsParity = 0 == (($this->uRShift($b, 7) ^ $this->uRShift($b, 6) ^ $this->uRShift($b, 5) + ^ $this->uRShift($b, 4) ^ $this->uRShift($b, 3) ^ $this->uRShift($b, 2) + ^ $this->uRShift($b, 1)) & 0x01); + + list($high, $low) = str_split($v); + if ($needsParity) { + $material[$k] = dechex(hexdec($high) | 0x0).dechex(hexdec($low) | 0x1); + } else { + $material[$k] = dechex(hexdec($high) & 0xf).dechex(hexdec($low) & 0xe); + } + } + + return hex2bin(implode('', $material)); + } + + /** HELPER FUNCTIONS */ + + /** + * Create our security buffer depending on length and offset. + * + * @param string $value Value we want to put in + * @param int $offset start of value + * @param bool $is16 Do we 16bit string or not? + * + * @return string + */ + protected function createSecurityBuffer($value, $offset, $is16 = false) + { + $length = \strlen(bin2hex($value)); + $length = $is16 ? $length / 2 : $length; + $length = $this->createByte(str_pad(dechex($length), 2, '0', STR_PAD_LEFT), 2); + + return $length.$length.$this->createByte(dechex($offset), 4); + } + + /** + * Read our security buffer to fetch length and offset of our value. + * + * @param string $value Securitybuffer in hex + * + * @return array array with length and offset + */ + protected function readSecurityBuffer($value) + { + $length = floor(hexdec(substr($value, 0, 4)) / 256) * 2; + $offset = floor(hexdec(substr($value, 8, 4)) / 256) * 2; + + return [$length, $offset]; + } + + /** + * Cast to byte java equivalent to (byte). + * + * @param int $v + * + * @return int + */ + protected function castToByte($v) + { + return (($v + 128) % 256) - 128; + } + + /** + * Java unsigned right bitwise + * $a >>> $b. + * + * @param int $a + * @param int $b + * + * @return int + */ + protected function uRShift($a, $b) + { + if (0 == $b) { + return $a; + } + + return ($a >> $b) & ~(1 << (8 * PHP_INT_SIZE - 1) >> ($b - 1)); + } + + /** + * Right padding with 0 to certain length. + * + * @param string $input + * @param int $bytes Length of bytes + * @param bool $isHex Did we provided hex value + * + * @return string + */ + protected function createByte($input, $bytes = 4, $isHex = true) + { + if ($isHex) { + $byte = hex2bin(str_pad($input, $bytes * 2, '00')); + } else { + $byte = str_pad($input, $bytes, "\x00"); + } + + return $byte; + } + + /** ENCRYPTION ALGORITHMS */ + + /** + * DES Encryption. + * + * @param string $value An 8-byte string + * @param string $key + * + * @return string + */ + protected function desEncrypt($value, $key) + { + return substr(openssl_encrypt($value, 'DES-ECB', $key, \OPENSSL_RAW_DATA), 0, 8); + } + + /** + * MD5 Encryption. + * + * @param string $key Encryption key + * @param string $msg Message to encrypt + * + * @return string + */ + protected function md5Encrypt($key, $msg) + { + $blocksize = 64; + if (\strlen($key) > $blocksize) { + $key = pack('H*', md5($key)); + } + + $key = str_pad($key, $blocksize, "\0"); + $ipadk = $key ^ str_repeat("\x36", $blocksize); + $opadk = $key ^ str_repeat("\x5c", $blocksize); + + return pack('H*', md5($opadk.pack('H*', md5($ipadk.$msg)))); + } + + /** + * MD4 Encryption. + * + * @param string $input + * + * @return string + * + * @see https://secure.php.net/manual/en/ref.hash.php + */ + protected function md4Encrypt($input) + { + $input = $this->convertTo16bit($input); + + return \function_exists('hash') ? hex2bin(hash('md4', $input)) : mhash(MHASH_MD4, $input); + } + + /** + * Convert UTF-8 to UTF-16. + * + * @param string $input + * + * @return string + */ + protected function convertTo16bit($input) + { + return iconv('UTF-8', 'UTF-16LE', $input); + } + + /** + * @param string $message + */ + protected function debug($message) + { + $message = bin2hex($message); + $messageId = substr($message, 16, 8); + echo substr($message, 0, 16)." NTLMSSP Signature
\n"; + echo $messageId." Type Indicator
\n"; + + if ('02000000' == $messageId) { + $map = [ + 'Challenge', + 'Context', + 'Target Information Security Buffer', + 'Target Name Data', + 'NetBIOS Domain Name', + 'NetBIOS Server Name', + 'DNS Domain Name', + 'DNS Server Name', + 'BLOB', + 'Target Information Terminator', + ]; + + $data = $this->parseMessage2(hex2bin($message)); + + foreach ($map as $key => $value) { + echo bin2hex($data[$key]).' - '.$data[$key].' ||| '.$value."
\n"; + } + } elseif ('03000000' == $messageId) { + $i = 0; + $data[$i++] = substr($message, 24, 16); + list($lmLength, $lmOffset) = $this->readSecurityBuffer($data[$i - 1]); + + $data[$i++] = substr($message, 40, 16); + list($ntmlLength, $ntmlOffset) = $this->readSecurityBuffer($data[$i - 1]); + + $data[$i++] = substr($message, 56, 16); + list($targetLength, $targetOffset) = $this->readSecurityBuffer($data[$i - 1]); + + $data[$i++] = substr($message, 72, 16); + list($userLength, $userOffset) = $this->readSecurityBuffer($data[$i - 1]); + + $data[$i++] = substr($message, 88, 16); + list($workLength, $workOffset) = $this->readSecurityBuffer($data[$i - 1]); + + $data[$i++] = substr($message, 104, 16); + $data[$i++] = substr($message, 120, 8); + $data[$i++] = substr($message, $targetOffset, $targetLength); + $data[$i++] = substr($message, $userOffset, $userLength); + $data[$i++] = substr($message, $workOffset, $workLength); + $data[$i++] = substr($message, $lmOffset, $lmLength); + $data[$i] = substr($message, $ntmlOffset, $ntmlLength); + + $map = [ + 'LM Response Security Buffer', + 'NTLM Response Security Buffer', + 'Target Name Security Buffer', + 'User Name Security Buffer', + 'Workstation Name Security Buffer', + 'Session Key Security Buffer', + 'Flags', + 'Target Name Data', + 'User Name Data', + 'Workstation Name Data', + 'LM Response Data', + 'NTLM Response Data', + ]; + + foreach ($map as $key => $value) { + echo $data[$key].' - '.hex2bin($data[$key]).' ||| '.$value."
\n"; + } + } + + echo '

'; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/PlainAuthenticator.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/PlainAuthenticator.php index cd1a2831e82..41d0a50a82b 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/PlainAuthenticator.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/PlainAuthenticator.php @@ -15,30 +15,30 @@ */ class Swift_Transport_Esmtp_Auth_PlainAuthenticator implements Swift_Transport_Esmtp_Authenticator { - /** - * Get the name of the AUTH mechanism this Authenticator handles. - * - * @return string - */ - public function getAuthKeyword() - { - return 'PLAIN'; - } + /** + * Get the name of the AUTH mechanism this Authenticator handles. + * + * @return string + */ + public function getAuthKeyword() + { + return 'PLAIN'; + } - /** - * {@inheritdoc} - */ - public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password) - { - try { - $message = base64_encode($username.\chr(0).$username.\chr(0).$password); - $agent->executeCommand(sprintf("AUTH PLAIN %s\r\n", $message), [235]); + /** + * {@inheritdoc} + */ + public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password) + { + try { + $message = base64_encode($username.\chr(0).$username.\chr(0).$password); + $agent->executeCommand(sprintf("AUTH PLAIN %s\r\n", $message), [235]); - return true; - } catch (Swift_TransportException $e) { - $agent->executeCommand("RSET\r\n", [250]); + return true; + } catch (Swift_TransportException $e) { + $agent->executeCommand("RSET\r\n", [250]); - throw $e; - } - } + throw $e; + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/XOAuth2Authenticator.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/XOAuth2Authenticator.php index c541b0ca952..859f22f3d5e 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/XOAuth2Authenticator.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/XOAuth2Authenticator.php @@ -25,40 +25,40 @@ */ class Swift_Transport_Esmtp_Auth_XOAuth2Authenticator implements Swift_Transport_Esmtp_Authenticator { - /** - * Get the name of the AUTH mechanism this Authenticator handles. - * - * @return string - */ - public function getAuthKeyword() - { - return 'XOAUTH2'; - } + /** + * Get the name of the AUTH mechanism this Authenticator handles. + * + * @return string + */ + public function getAuthKeyword() + { + return 'XOAUTH2'; + } - /** - * {@inheritdoc} - */ - public function authenticate(Swift_Transport_SmtpAgent $agent, $email, $token) - { - try { - $param = $this->constructXOAuth2Params($email, $token); - $agent->executeCommand('AUTH XOAUTH2 '.$param."\r\n", [235]); + /** + * {@inheritdoc} + */ + public function authenticate(Swift_Transport_SmtpAgent $agent, $email, $token) + { + try { + $param = $this->constructXOAuth2Params($email, $token); + $agent->executeCommand('AUTH XOAUTH2 '.$param."\r\n", [235]); - return true; - } catch (Swift_TransportException $e) { - $agent->executeCommand("RSET\r\n", [250]); + return true; + } catch (Swift_TransportException $e) { + $agent->executeCommand("RSET\r\n", [250]); - throw $e; - } - } + throw $e; + } + } - /** - * Construct the auth parameter. - * - * @see https://developers.google.com/google-apps/gmail/xoauth2_protocol#the_sasl_xoauth2_mechanism - */ - protected function constructXOAuth2Params($email, $token) - { - return base64_encode("user=$email\1auth=Bearer $token\1\1"); - } + /** + * Construct the auth parameter. + * + * @see https://developers.google.com/google-apps/gmail/xoauth2_protocol#the_sasl_xoauth2_mechanism + */ + protected function constructXOAuth2Params($email, $token) + { + return base64_encode("user=$email\1auth=Bearer $token\1\1"); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/AuthHandler.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/AuthHandler.php index 26ac6086fdf..53a90a87383 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/AuthHandler.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/AuthHandler.php @@ -15,254 +15,254 @@ */ class Swift_Transport_Esmtp_AuthHandler implements Swift_Transport_EsmtpHandler { - /** - * Authenticators available to process the request. - * - * @var Swift_Transport_Esmtp_Authenticator[] - */ - private $authenticators = []; + /** + * Authenticators available to process the request. + * + * @var Swift_Transport_Esmtp_Authenticator[] + */ + private $authenticators = []; - /** - * The username for authentication. - * - * @var string - */ - private $username; + /** + * The username for authentication. + * + * @var string + */ + private $username; - /** - * The password for authentication. - * - * @var string - */ - private $password; + /** + * The password for authentication. + * + * @var string + */ + private $password; - /** - * The auth mode for authentication. - * - * @var string - */ - private $auth_mode; + /** + * The auth mode for authentication. + * + * @var string + */ + private $auth_mode; - /** - * The ESMTP AUTH parameters available. - * - * @var string[] - */ - private $esmtpParams = []; + /** + * The ESMTP AUTH parameters available. + * + * @var string[] + */ + private $esmtpParams = []; - /** - * Create a new AuthHandler with $authenticators for support. - * - * @param Swift_Transport_Esmtp_Authenticator[] $authenticators - */ - public function __construct(array $authenticators) - { - $this->setAuthenticators($authenticators); - } + /** + * Create a new AuthHandler with $authenticators for support. + * + * @param Swift_Transport_Esmtp_Authenticator[] $authenticators + */ + public function __construct(array $authenticators) + { + $this->setAuthenticators($authenticators); + } - /** - * Set the Authenticators which can process a login request. - * - * @param Swift_Transport_Esmtp_Authenticator[] $authenticators - */ - public function setAuthenticators(array $authenticators) - { - $this->authenticators = $authenticators; - } + /** + * Set the Authenticators which can process a login request. + * + * @param Swift_Transport_Esmtp_Authenticator[] $authenticators + */ + public function setAuthenticators(array $authenticators) + { + $this->authenticators = $authenticators; + } - /** - * Get the Authenticators which can process a login request. - * - * @return Swift_Transport_Esmtp_Authenticator[] - */ - public function getAuthenticators() - { - return $this->authenticators; - } + /** + * Get the Authenticators which can process a login request. + * + * @return Swift_Transport_Esmtp_Authenticator[] + */ + public function getAuthenticators() + { + return $this->authenticators; + } - /** - * Set the username to authenticate with. - * - * @param string $username - */ - public function setUsername($username) - { - $this->username = $username; - } + /** + * Set the username to authenticate with. + * + * @param string $username + */ + public function setUsername($username) + { + $this->username = $username; + } - /** - * Get the username to authenticate with. - * - * @return string - */ - public function getUsername() - { - return $this->username; - } + /** + * Get the username to authenticate with. + * + * @return string + */ + public function getUsername() + { + return $this->username; + } - /** - * Set the password to authenticate with. - * - * @param string $password - */ - public function setPassword($password) - { - $this->password = $password; - } + /** + * Set the password to authenticate with. + * + * @param string $password + */ + public function setPassword($password) + { + $this->password = $password; + } - /** - * Get the password to authenticate with. - * - * @return string - */ - public function getPassword() - { - return $this->password; - } + /** + * Get the password to authenticate with. + * + * @return string + */ + public function getPassword() + { + return $this->password; + } - /** - * Set the auth mode to use to authenticate. - * - * @param string $mode - */ - public function setAuthMode($mode) - { - $this->auth_mode = $mode; - } + /** + * Set the auth mode to use to authenticate. + * + * @param string $mode + */ + public function setAuthMode($mode) + { + $this->auth_mode = $mode; + } - /** - * Get the auth mode to use to authenticate. - * - * @return string - */ - public function getAuthMode() - { - return $this->auth_mode; - } + /** + * Get the auth mode to use to authenticate. + * + * @return string + */ + public function getAuthMode() + { + return $this->auth_mode; + } - /** - * Get the name of the ESMTP extension this handles. - * - * @return string - */ - public function getHandledKeyword() - { - return 'AUTH'; - } + /** + * Get the name of the ESMTP extension this handles. + * + * @return string + */ + public function getHandledKeyword() + { + return 'AUTH'; + } - /** - * Set the parameters which the EHLO greeting indicated. - * - * @param string[] $parameters - */ - public function setKeywordParams(array $parameters) - { - $this->esmtpParams = $parameters; - } + /** + * Set the parameters which the EHLO greeting indicated. + * + * @param string[] $parameters + */ + public function setKeywordParams(array $parameters) + { + $this->esmtpParams = $parameters; + } - /** - * Runs immediately after a EHLO has been issued. - * - * @param Swift_Transport_SmtpAgent $agent to read/write - */ - public function afterEhlo(Swift_Transport_SmtpAgent $agent) - { - if ($this->username) { - $count = 0; - $errors = []; - foreach ($this->getAuthenticatorsForAgent() as $authenticator) { - if (\in_array(strtolower($authenticator->getAuthKeyword() ?? ''), array_map('strtolower', $this->esmtpParams))) { - ++$count; - try { - if ($authenticator->authenticate($agent, $this->username, $this->password)) { - return; - } - } catch (Swift_TransportException $e) { - // keep the error message, but tries the other authenticators - $errors[] = [$authenticator->getAuthKeyword(), $e->getMessage()]; - } - } - } + /** + * Runs immediately after a EHLO has been issued. + * + * @param Swift_Transport_SmtpAgent $agent to read/write + */ + public function afterEhlo(Swift_Transport_SmtpAgent $agent) + { + if ($this->username) { + $count = 0; + $errors = []; + foreach ($this->getAuthenticatorsForAgent() as $authenticator) { + if (\in_array(strtolower($authenticator->getAuthKeyword() ?? ''), array_map('strtolower', $this->esmtpParams))) { + ++$count; + try { + if ($authenticator->authenticate($agent, $this->username, $this->password)) { + return; + } + } catch (Swift_TransportException $e) { + // keep the error message, but tries the other authenticators + $errors[] = [$authenticator->getAuthKeyword(), $e->getMessage()]; + } + } + } - $message = 'Failed to authenticate on SMTP server with username "'.$this->username.'" using '.$count.' possible authenticators.'; - foreach ($errors as $error) { - $message .= ' Authenticator '.$error[0].' returned '.$error[1].'.'; - } - throw new Swift_TransportException($message); - } - } + $message = 'Failed to authenticate on SMTP server with username "'.$this->username.'" using '.$count.' possible authenticators.'; + foreach ($errors as $error) { + $message .= ' Authenticator '.$error[0].' returned '.$error[1].'.'; + } + throw new Swift_TransportException($message); + } + } - /** - * Not used. - */ - public function getMailParams() - { - return []; - } + /** + * Not used. + */ + public function getMailParams() + { + return []; + } - /** - * Not used. - */ - public function getRcptParams() - { - return []; - } + /** + * Not used. + */ + public function getRcptParams() + { + return []; + } - /** - * Not used. - */ - public function onCommand(Swift_Transport_SmtpAgent $agent, $command, $codes = [], &$failedRecipients = null, &$stop = false) - { - } + /** + * Not used. + */ + public function onCommand(Swift_Transport_SmtpAgent $agent, $command, $codes = [], &$failedRecipients = null, &$stop = false) + { + } - /** - * Returns +1, -1 or 0 according to the rules for usort(). - * - * This method is called to ensure extensions can be execute in an appropriate order. - * - * @param string $esmtpKeyword to compare with - * - * @return int - */ - public function getPriorityOver($esmtpKeyword) - { - return 0; - } + /** + * Returns +1, -1 or 0 according to the rules for usort(). + * + * This method is called to ensure extensions can be execute in an appropriate order. + * + * @param string $esmtpKeyword to compare with + * + * @return int + */ + public function getPriorityOver($esmtpKeyword) + { + return 0; + } - /** - * Returns an array of method names which are exposed to the Esmtp class. - * - * @return string[] - */ - public function exposeMixinMethods() - { - return ['setUsername', 'getUsername', 'setPassword', 'getPassword', 'setAuthMode', 'getAuthMode']; - } + /** + * Returns an array of method names which are exposed to the Esmtp class. + * + * @return string[] + */ + public function exposeMixinMethods() + { + return ['setUsername', 'getUsername', 'setPassword', 'getPassword', 'setAuthMode', 'getAuthMode']; + } - /** - * Not used. - */ - public function resetState() - { - } + /** + * Not used. + */ + public function resetState() + { + } - /** - * Returns the authenticator list for the given agent. - * - * @return array - */ - protected function getAuthenticatorsForAgent() - { - if (!$mode = strtolower($this->auth_mode ?? '')) { - return $this->authenticators; - } + /** + * Returns the authenticator list for the given agent. + * + * @return array + */ + protected function getAuthenticatorsForAgent() + { + if (!$mode = strtolower($this->auth_mode ?? '')) { + return $this->authenticators; + } - foreach ($this->authenticators as $authenticator) { - if (strtolower($authenticator->getAuthKeyword() ?? '') == $mode) { - return [$authenticator]; - } - } + foreach ($this->authenticators as $authenticator) { + if (strtolower($authenticator->getAuthKeyword() ?? '') == $mode) { + return [$authenticator]; + } + } - throw new Swift_TransportException('Auth mode '.$mode.' is invalid'); - } + throw new Swift_TransportException('Auth mode '.$mode.' is invalid'); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Authenticator.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Authenticator.php index 40aeb1a65cc..f692a6fe40d 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Authenticator.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/Authenticator.php @@ -15,22 +15,22 @@ */ interface Swift_Transport_Esmtp_Authenticator { - /** - * Get the name of the AUTH mechanism this Authenticator handles. - * - * @return string - */ - public function getAuthKeyword(); + /** + * Get the name of the AUTH mechanism this Authenticator handles. + * + * @return string + */ + public function getAuthKeyword(); - /** - * Try to authenticate the user with $username and $password. - * - * @param string $username - * @param string $password - * - * @return bool true if authentication worked (returning false is deprecated, throw a Swift_TransportException instead) - * - * @throws Swift_TransportException Allows the message to bubble up when authentication was not successful - */ - public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password); + /** + * Try to authenticate the user with $username and $password. + * + * @param string $username + * @param string $password + * + * @return bool true if authentication worked (returning false is deprecated, throw a Swift_TransportException instead) + * + * @throws Swift_TransportException Allows the message to bubble up when authentication was not successful + */ + public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/EightBitMimeHandler.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/EightBitMimeHandler.php index f2ab8d2e3cc..63f70866939 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/EightBitMimeHandler.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/EightBitMimeHandler.php @@ -22,92 +22,92 @@ */ class Swift_Transport_Esmtp_EightBitMimeHandler implements Swift_Transport_EsmtpHandler { - protected $encoding; + protected $encoding; - /** - * @param string $encoding The parameter so send with the MAIL FROM command; - * either "8BITMIME" or "7BIT" - */ - public function __construct(string $encoding = '8BITMIME') - { - $this->encoding = $encoding; - } + /** + * @param string $encoding The parameter so send with the MAIL FROM command; + * either "8BITMIME" or "7BIT" + */ + public function __construct(string $encoding = '8BITMIME') + { + $this->encoding = $encoding; + } - /** - * Get the name of the ESMTP extension this handles. - * - * @return string - */ - public function getHandledKeyword() - { - return '8BITMIME'; - } + /** + * Get the name of the ESMTP extension this handles. + * + * @return string + */ + public function getHandledKeyword() + { + return '8BITMIME'; + } - /** - * Not used. - */ - public function setKeywordParams(array $parameters) - { - } + /** + * Not used. + */ + public function setKeywordParams(array $parameters) + { + } - /** - * Not used. - */ - public function afterEhlo(Swift_Transport_SmtpAgent $agent) - { - } + /** + * Not used. + */ + public function afterEhlo(Swift_Transport_SmtpAgent $agent) + { + } - /** - * Get params which are appended to MAIL FROM:<>. - * - * @return string[] - */ - public function getMailParams() - { - return ['BODY='.$this->encoding]; - } + /** + * Get params which are appended to MAIL FROM:<>. + * + * @return string[] + */ + public function getMailParams() + { + return ['BODY='.$this->encoding]; + } - /** - * Not used. - */ - public function getRcptParams() - { - return []; - } + /** + * Not used. + */ + public function getRcptParams() + { + return []; + } - /** - * Not used. - */ - public function onCommand(Swift_Transport_SmtpAgent $agent, $command, $codes = [], &$failedRecipients = null, &$stop = false) - { - } + /** + * Not used. + */ + public function onCommand(Swift_Transport_SmtpAgent $agent, $command, $codes = [], &$failedRecipients = null, &$stop = false) + { + } - /** - * Returns +1, -1 or 0 according to the rules for usort(). - * - * This method is called to ensure extensions can be execute in an appropriate order. - * - * @param string $esmtpKeyword to compare with - * - * @return int - */ - public function getPriorityOver($esmtpKeyword) - { - return 0; - } + /** + * Returns +1, -1 or 0 according to the rules for usort(). + * + * This method is called to ensure extensions can be execute in an appropriate order. + * + * @param string $esmtpKeyword to compare with + * + * @return int + */ + public function getPriorityOver($esmtpKeyword) + { + return 0; + } - /** - * Not used. - */ - public function exposeMixinMethods() - { - return []; - } + /** + * Not used. + */ + public function exposeMixinMethods() + { + return []; + } - /** - * Not used. - */ - public function resetState() - { - } + /** + * Not used. + */ + public function resetState() + { + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/SmtpUtf8Handler.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/SmtpUtf8Handler.php index e9b4b69ea6a..7d0252a01bf 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/SmtpUtf8Handler.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/Esmtp/SmtpUtf8Handler.php @@ -23,85 +23,85 @@ */ class Swift_Transport_Esmtp_SmtpUtf8Handler implements Swift_Transport_EsmtpHandler { - public function __construct() - { - } + public function __construct() + { + } - /** - * Get the name of the ESMTP extension this handles. - * - * @return string - */ - public function getHandledKeyword() - { - return 'SMTPUTF8'; - } + /** + * Get the name of the ESMTP extension this handles. + * + * @return string + */ + public function getHandledKeyword() + { + return 'SMTPUTF8'; + } - /** - * Not used. - */ - public function setKeywordParams(array $parameters) - { - } + /** + * Not used. + */ + public function setKeywordParams(array $parameters) + { + } - /** - * Not used. - */ - public function afterEhlo(Swift_Transport_SmtpAgent $agent) - { - } + /** + * Not used. + */ + public function afterEhlo(Swift_Transport_SmtpAgent $agent) + { + } - /** - * Get params which are appended to MAIL FROM:<>. - * - * @return string[] - */ - public function getMailParams() - { - return ['SMTPUTF8']; - } + /** + * Get params which are appended to MAIL FROM:<>. + * + * @return string[] + */ + public function getMailParams() + { + return ['SMTPUTF8']; + } - /** - * Not used. - */ - public function getRcptParams() - { - return []; - } + /** + * Not used. + */ + public function getRcptParams() + { + return []; + } - /** - * Not used. - */ - public function onCommand(Swift_Transport_SmtpAgent $agent, $command, $codes = [], &$failedRecipients = null, &$stop = false) - { - } + /** + * Not used. + */ + public function onCommand(Swift_Transport_SmtpAgent $agent, $command, $codes = [], &$failedRecipients = null, &$stop = false) + { + } - /** - * Returns +1, -1 or 0 according to the rules for usort(). - * - * This method is called to ensure extensions can be execute in an appropriate order. - * - * @param string $esmtpKeyword to compare with - * - * @return int - */ - public function getPriorityOver($esmtpKeyword) - { - return 0; - } + /** + * Returns +1, -1 or 0 according to the rules for usort(). + * + * This method is called to ensure extensions can be execute in an appropriate order. + * + * @param string $esmtpKeyword to compare with + * + * @return int + */ + public function getPriorityOver($esmtpKeyword) + { + return 0; + } - /** - * Not used. - */ - public function exposeMixinMethods() - { - return []; - } + /** + * Not used. + */ + public function exposeMixinMethods() + { + return []; + } - /** - * Not used. - */ - public function resetState() - { - } + /** + * Not used. + */ + public function resetState() + { + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/EsmtpHandler.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/EsmtpHandler.php index 7dad692f12a..b8ea36e2fa8 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/EsmtpHandler.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/EsmtpHandler.php @@ -15,72 +15,72 @@ */ interface Swift_Transport_EsmtpHandler { - /** - * Get the name of the ESMTP extension this handles. - * - * @return string - */ - public function getHandledKeyword(); + /** + * Get the name of the ESMTP extension this handles. + * + * @return string + */ + public function getHandledKeyword(); - /** - * Set the parameters which the EHLO greeting indicated. - * - * @param string[] $parameters - */ - public function setKeywordParams(array $parameters); + /** + * Set the parameters which the EHLO greeting indicated. + * + * @param string[] $parameters + */ + public function setKeywordParams(array $parameters); - /** - * Runs immediately after a EHLO has been issued. - * - * @param Swift_Transport_SmtpAgent $agent to read/write - */ - public function afterEhlo(Swift_Transport_SmtpAgent $agent); + /** + * Runs immediately after a EHLO has been issued. + * + * @param Swift_Transport_SmtpAgent $agent to read/write + */ + public function afterEhlo(Swift_Transport_SmtpAgent $agent); - /** - * Get params which are appended to MAIL FROM:<>. - * - * @return string[] - */ - public function getMailParams(); + /** + * Get params which are appended to MAIL FROM:<>. + * + * @return string[] + */ + public function getMailParams(); - /** - * Get params which are appended to RCPT TO:<>. - * - * @return string[] - */ - public function getRcptParams(); + /** + * Get params which are appended to RCPT TO:<>. + * + * @return string[] + */ + public function getRcptParams(); - /** - * Runs when a command is due to be sent. - * - * @param Swift_Transport_SmtpAgent $agent to read/write - * @param string $command to send - * @param int[] $codes expected in response - * @param string[] $failedRecipients to collect failures - * @param bool $stop to be set true by-reference if the command is now sent - */ - public function onCommand(Swift_Transport_SmtpAgent $agent, $command, $codes = [], &$failedRecipients = null, &$stop = false); + /** + * Runs when a command is due to be sent. + * + * @param Swift_Transport_SmtpAgent $agent to read/write + * @param string $command to send + * @param int[] $codes expected in response + * @param string[] $failedRecipients to collect failures + * @param bool $stop to be set true by-reference if the command is now sent + */ + public function onCommand(Swift_Transport_SmtpAgent $agent, $command, $codes = [], &$failedRecipients = null, &$stop = false); - /** - * Returns +1, -1 or 0 according to the rules for usort(). - * - * This method is called to ensure extensions can be execute in an appropriate order. - * - * @param string $esmtpKeyword to compare with - * - * @return int - */ - public function getPriorityOver($esmtpKeyword); + /** + * Returns +1, -1 or 0 according to the rules for usort(). + * + * This method is called to ensure extensions can be execute in an appropriate order. + * + * @param string $esmtpKeyword to compare with + * + * @return int + */ + public function getPriorityOver($esmtpKeyword); - /** - * Returns an array of method names which are exposed to the Esmtp class. - * - * @return string[] - */ - public function exposeMixinMethods(); + /** + * Returns an array of method names which are exposed to the Esmtp class. + * + * @return string[] + */ + public function exposeMixinMethods(); - /** - * Tells this handler to clear any buffers and reset its state. - */ - public function resetState(); + /** + * Tells this handler to clear any buffers and reset its state. + */ + public function resetState(); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/EsmtpTransport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/EsmtpTransport.php index 281337ee855..36545f51feb 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/EsmtpTransport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/EsmtpTransport.php @@ -15,432 +15,432 @@ */ class Swift_Transport_EsmtpTransport extends Swift_Transport_AbstractSmtpTransport implements Swift_Transport_SmtpAgent { - /** - * ESMTP extension handlers. - * - * @var Swift_Transport_EsmtpHandler[] - */ - private $handlers = []; + /** + * ESMTP extension handlers. + * + * @var Swift_Transport_EsmtpHandler[] + */ + private $handlers = []; - /** - * ESMTP capabilities. - * - * @var string[] - */ - private $capabilities = []; + /** + * ESMTP capabilities. + * + * @var string[] + */ + private $capabilities = []; - /** - * Connection buffer parameters. - * - * @var array - */ - private $params = [ - 'protocol' => 'tcp', - 'host' => 'localhost', - 'port' => 25, - 'timeout' => 30, - 'blocking' => 1, - 'tls' => false, - 'type' => Swift_Transport_IoBuffer::TYPE_SOCKET, - 'stream_context_options' => [], - ]; + /** + * Connection buffer parameters. + * + * @var array + */ + private $params = [ + 'protocol' => 'tcp', + 'host' => 'localhost', + 'port' => 25, + 'timeout' => 30, + 'blocking' => 1, + 'tls' => false, + 'type' => Swift_Transport_IoBuffer::TYPE_SOCKET, + 'stream_context_options' => [], + ]; - /** - * Creates a new EsmtpTransport using the given I/O buffer. - * - * @param Swift_Transport_EsmtpHandler[] $extensionHandlers - * @param string $localDomain - */ - public function __construct(Swift_Transport_IoBuffer $buf, array $extensionHandlers, Swift_Events_EventDispatcher $dispatcher, $localDomain = '127.0.0.1', Swift_AddressEncoder $addressEncoder = null) - { - parent::__construct($buf, $dispatcher, $localDomain, $addressEncoder); - $this->setExtensionHandlers($extensionHandlers); - } + /** + * Creates a new EsmtpTransport using the given I/O buffer. + * + * @param Swift_Transport_EsmtpHandler[] $extensionHandlers + * @param string $localDomain + */ + public function __construct(Swift_Transport_IoBuffer $buf, array $extensionHandlers, Swift_Events_EventDispatcher $dispatcher, $localDomain = '127.0.0.1', Swift_AddressEncoder $addressEncoder = null) + { + parent::__construct($buf, $dispatcher, $localDomain, $addressEncoder); + $this->setExtensionHandlers($extensionHandlers); + } - /** - * Set the host to connect to. - * - * Literal IPv6 addresses should be wrapped in square brackets. - * - * @param string $host - * - * @return $this - */ - public function setHost($host) - { - $this->params['host'] = $host; + /** + * Set the host to connect to. + * + * Literal IPv6 addresses should be wrapped in square brackets. + * + * @param string $host + * + * @return $this + */ + public function setHost($host) + { + $this->params['host'] = $host; - return $this; - } + return $this; + } - /** - * Get the host to connect to. - * - * @return string - */ - public function getHost() - { - return $this->params['host']; - } + /** + * Get the host to connect to. + * + * @return string + */ + public function getHost() + { + return $this->params['host']; + } - /** - * Set the port to connect to. - * - * @param int $port - * - * @return $this - */ - public function setPort($port) - { - $this->params['port'] = (int) $port; + /** + * Set the port to connect to. + * + * @param int $port + * + * @return $this + */ + public function setPort($port) + { + $this->params['port'] = (int) $port; - return $this; - } + return $this; + } - /** - * Get the port to connect to. - * - * @return int - */ - public function getPort() - { - return $this->params['port']; - } + /** + * Get the port to connect to. + * + * @return int + */ + public function getPort() + { + return $this->params['port']; + } - /** - * Set the connection timeout. - * - * @param int $timeout seconds - * - * @return $this - */ - public function setTimeout($timeout) - { - $this->params['timeout'] = (int) $timeout; - $this->buffer->setParam('timeout', (int) $timeout); + /** + * Set the connection timeout. + * + * @param int $timeout seconds + * + * @return $this + */ + public function setTimeout($timeout) + { + $this->params['timeout'] = (int) $timeout; + $this->buffer->setParam('timeout', (int) $timeout); - return $this; - } + return $this; + } - /** - * Get the connection timeout. - * - * @return int - */ - public function getTimeout() - { - return $this->params['timeout']; - } + /** + * Get the connection timeout. + * + * @return int + */ + public function getTimeout() + { + return $this->params['timeout']; + } - /** - * Set the encryption type (tls or ssl). - * - * @param string $encryption - * - * @return $this - */ - public function setEncryption($encryption) - { - $encryption = strtolower($encryption ?? ''); - if ('tls' == $encryption) { - $this->params['protocol'] = 'tcp'; - $this->params['tls'] = true; - } else { - $this->params['protocol'] = $encryption; - $this->params['tls'] = false; - } + /** + * Set the encryption type (tls or ssl). + * + * @param string $encryption + * + * @return $this + */ + public function setEncryption($encryption) + { + $encryption = strtolower($encryption ?? ''); + if ('tls' == $encryption) { + $this->params['protocol'] = 'tcp'; + $this->params['tls'] = true; + } else { + $this->params['protocol'] = $encryption; + $this->params['tls'] = false; + } - return $this; - } + return $this; + } - /** - * Get the encryption type. - * - * @return string - */ - public function getEncryption() - { - return $this->params['tls'] ? 'tls' : $this->params['protocol']; - } + /** + * Get the encryption type. + * + * @return string + */ + public function getEncryption() + { + return $this->params['tls'] ? 'tls' : $this->params['protocol']; + } - /** - * Sets the stream context options. - * - * @param array $options - * - * @return $this - */ - public function setStreamOptions($options) - { - $this->params['stream_context_options'] = $options; + /** + * Sets the stream context options. + * + * @param array $options + * + * @return $this + */ + public function setStreamOptions($options) + { + $this->params['stream_context_options'] = $options; - return $this; - } + return $this; + } - /** - * Returns the stream context options. - * - * @return array - */ - public function getStreamOptions() - { - return $this->params['stream_context_options']; - } + /** + * Returns the stream context options. + * + * @return array + */ + public function getStreamOptions() + { + return $this->params['stream_context_options']; + } - /** - * Sets the source IP. - * - * IPv6 addresses should be wrapped in square brackets. - * - * @param string $source - * - * @return $this - */ - public function setSourceIp($source) - { - $this->params['sourceIp'] = $source; + /** + * Sets the source IP. + * + * IPv6 addresses should be wrapped in square brackets. + * + * @param string $source + * + * @return $this + */ + public function setSourceIp($source) + { + $this->params['sourceIp'] = $source; - return $this; - } + return $this; + } - /** - * Returns the IP used to connect to the destination. - * - * @return string - */ - public function getSourceIp() - { - return $this->params['sourceIp'] ?? null; - } + /** + * Returns the IP used to connect to the destination. + * + * @return string + */ + public function getSourceIp() + { + return $this->params['sourceIp'] ?? null; + } - /** - * Sets whether SMTP pipelining is enabled. - * - * By default, support is auto-detected using the PIPELINING SMTP extension. - * Use this function to override that in the unlikely event of compatibility - * issues. - * - * @param bool $enabled - * - * @return $this - */ - public function setPipelining($enabled) - { - $this->pipelining = $enabled; + /** + * Sets whether SMTP pipelining is enabled. + * + * By default, support is auto-detected using the PIPELINING SMTP extension. + * Use this function to override that in the unlikely event of compatibility + * issues. + * + * @param bool $enabled + * + * @return $this + */ + public function setPipelining($enabled) + { + $this->pipelining = $enabled; - return $this; - } + return $this; + } - /** - * Returns whether SMTP pipelining is enabled. - * - * @return bool|null a boolean if pipelining is explicitly enabled or disabled, - * or null if support is auto-detected - */ - public function getPipelining() - { - return $this->pipelining; - } + /** + * Returns whether SMTP pipelining is enabled. + * + * @return bool|null a boolean if pipelining is explicitly enabled or disabled, + * or null if support is auto-detected + */ + public function getPipelining() + { + return $this->pipelining; + } - /** - * Set ESMTP extension handlers. - * - * @param Swift_Transport_EsmtpHandler[] $handlers - * - * @return $this - */ - public function setExtensionHandlers(array $handlers) - { - $assoc = []; - foreach ($handlers as $handler) { - $assoc[$handler->getHandledKeyword()] = $handler; - } - uasort($assoc, function ($a, $b) { - return $a->getPriorityOver($b->getHandledKeyword()); - }); - $this->handlers = $assoc; - $this->setHandlerParams(); + /** + * Set ESMTP extension handlers. + * + * @param Swift_Transport_EsmtpHandler[] $handlers + * + * @return $this + */ + public function setExtensionHandlers(array $handlers) + { + $assoc = []; + foreach ($handlers as $handler) { + $assoc[$handler->getHandledKeyword()] = $handler; + } + uasort($assoc, function ($a, $b) { + return $a->getPriorityOver($b->getHandledKeyword()); + }); + $this->handlers = $assoc; + $this->setHandlerParams(); - return $this; - } + return $this; + } - /** - * Get ESMTP extension handlers. - * - * @return Swift_Transport_EsmtpHandler[] - */ - public function getExtensionHandlers() - { - return array_values($this->handlers); - } + /** + * Get ESMTP extension handlers. + * + * @return Swift_Transport_EsmtpHandler[] + */ + public function getExtensionHandlers() + { + return array_values($this->handlers); + } - /** - * Run a command against the buffer, expecting the given response codes. - * - * If no response codes are given, the response will not be validated. - * If codes are given, an exception will be thrown on an invalid response. - * - * @param string $command - * @param int[] $codes - * @param string[] $failures An array of failures by-reference - * @param bool $pipeline Do not wait for response - * @param string $address the address, if command is RCPT TO - * - * @return string|null The server response, or null if pipelining is enabled - */ - public function executeCommand($command, $codes = [], &$failures = null, $pipeline = false, $address = null) - { - $failures = (array) $failures; - $stopSignal = false; - $response = null; - foreach ($this->getActiveHandlers() as $handler) { - $response = $handler->onCommand( - $this, $command, $codes, $failures, $stopSignal - ); - if ($stopSignal) { - return $response; - } - } + /** + * Run a command against the buffer, expecting the given response codes. + * + * If no response codes are given, the response will not be validated. + * If codes are given, an exception will be thrown on an invalid response. + * + * @param string $command + * @param int[] $codes + * @param string[] $failures An array of failures by-reference + * @param bool $pipeline Do not wait for response + * @param string $address the address, if command is RCPT TO + * + * @return string|null The server response, or null if pipelining is enabled + */ + public function executeCommand($command, $codes = [], &$failures = null, $pipeline = false, $address = null) + { + $failures = (array) $failures; + $stopSignal = false; + $response = null; + foreach ($this->getActiveHandlers() as $handler) { + $response = $handler->onCommand( + $this, $command, $codes, $failures, $stopSignal + ); + if ($stopSignal) { + return $response; + } + } - return parent::executeCommand($command, $codes, $failures, $pipeline, $address); - } + return parent::executeCommand($command, $codes, $failures, $pipeline, $address); + } - /** Mixin handling method for ESMTP handlers */ - public function __call($method, $args) - { - foreach ($this->handlers as $handler) { - if (\in_array(strtolower($method), - array_map('strtolower', (array) $handler->exposeMixinMethods()) - )) { - $return = \call_user_func_array([$handler, $method], $args); - // Allow fluid method calls - if (null === $return && 'set' == substr($method, 0, 3)) { - return $this; - } else { - return $return; - } - } - } - trigger_error('Call to undefined method '.$method, E_USER_ERROR); - } + /** Mixin handling method for ESMTP handlers */ + public function __call($method, $args) + { + foreach ($this->handlers as $handler) { + if (\in_array(strtolower($method), + array_map('strtolower', (array) $handler->exposeMixinMethods()) + )) { + $return = \call_user_func_array([$handler, $method], $args); + // Allow fluid method calls + if (null === $return && 'set' == substr($method, 0, 3)) { + return $this; + } else { + return $return; + } + } + } + trigger_error('Call to undefined method '.$method, E_USER_ERROR); + } - /** Get the params to initialize the buffer */ - protected function getBufferParams() - { - return $this->params; - } + /** Get the params to initialize the buffer */ + protected function getBufferParams() + { + return $this->params; + } - /** Overridden to perform EHLO instead */ - protected function doHeloCommand() - { - try { - $response = $this->executeCommand( - sprintf("EHLO %s\r\n", $this->domain), [250] - ); - } catch (Swift_TransportException $e) { - return parent::doHeloCommand(); - } + /** Overridden to perform EHLO instead */ + protected function doHeloCommand() + { + try { + $response = $this->executeCommand( + sprintf("EHLO %s\r\n", $this->domain), [250] + ); + } catch (Swift_TransportException $e) { + return parent::doHeloCommand(); + } - if ($this->params['tls']) { - try { - $this->executeCommand("STARTTLS\r\n", [220]); + if ($this->params['tls']) { + try { + $this->executeCommand("STARTTLS\r\n", [220]); - if (!$this->buffer->startTLS()) { - throw new Swift_TransportException('Unable to connect with TLS encryption'); - } + if (!$this->buffer->startTLS()) { + throw new Swift_TransportException('Unable to connect with TLS encryption'); + } - try { - $response = $this->executeCommand( - sprintf("EHLO %s\r\n", $this->domain), [250] - ); - } catch (Swift_TransportException $e) { - return parent::doHeloCommand(); - } - } catch (Swift_TransportException $e) { - $this->throwException($e); - } - } + try { + $response = $this->executeCommand( + sprintf("EHLO %s\r\n", $this->domain), [250] + ); + } catch (Swift_TransportException $e) { + return parent::doHeloCommand(); + } + } catch (Swift_TransportException $e) { + $this->throwException($e); + } + } - $this->capabilities = $this->getCapabilities($response); - if (!isset($this->pipelining)) { - $this->pipelining = isset($this->capabilities['PIPELINING']); - } + $this->capabilities = $this->getCapabilities($response); + if (!isset($this->pipelining)) { + $this->pipelining = isset($this->capabilities['PIPELINING']); + } - $this->setHandlerParams(); - foreach ($this->getActiveHandlers() as $handler) { - $handler->afterEhlo($this); - } - } + $this->setHandlerParams(); + foreach ($this->getActiveHandlers() as $handler) { + $handler->afterEhlo($this); + } + } - /** Overridden to add Extension support */ - protected function doMailFromCommand($address) - { - $address = $this->addressEncoder->encodeString($address); - $handlers = $this->getActiveHandlers(); - $params = []; - foreach ($handlers as $handler) { - $params = array_merge($params, (array) $handler->getMailParams()); - } - $paramStr = !empty($params) ? ' '.implode(' ', $params) : ''; - $this->executeCommand( - sprintf("MAIL FROM:<%s>%s\r\n", $address, $paramStr), [250], $failures, true - ); - } + /** Overridden to add Extension support */ + protected function doMailFromCommand($address) + { + $address = $this->addressEncoder->encodeString($address); + $handlers = $this->getActiveHandlers(); + $params = []; + foreach ($handlers as $handler) { + $params = array_merge($params, (array) $handler->getMailParams()); + } + $paramStr = !empty($params) ? ' '.implode(' ', $params) : ''; + $this->executeCommand( + sprintf("MAIL FROM:<%s>%s\r\n", $address, $paramStr), [250], $failures, true + ); + } - /** Overridden to add Extension support */ - protected function doRcptToCommand($address) - { - $address = $this->addressEncoder->encodeString($address); - $handlers = $this->getActiveHandlers(); - $params = []; - foreach ($handlers as $handler) { - $params = array_merge($params, (array) $handler->getRcptParams()); - } - $paramStr = !empty($params) ? ' '.implode(' ', $params) : ''; - $this->executeCommand( - sprintf("RCPT TO:<%s>%s\r\n", $address, $paramStr), [250, 251, 252], $failures, true, $address - ); - } + /** Overridden to add Extension support */ + protected function doRcptToCommand($address) + { + $address = $this->addressEncoder->encodeString($address); + $handlers = $this->getActiveHandlers(); + $params = []; + foreach ($handlers as $handler) { + $params = array_merge($params, (array) $handler->getRcptParams()); + } + $paramStr = !empty($params) ? ' '.implode(' ', $params) : ''; + $this->executeCommand( + sprintf("RCPT TO:<%s>%s\r\n", $address, $paramStr), [250, 251, 252], $failures, true, $address + ); + } - /** Determine ESMTP capabilities by function group */ - private function getCapabilities($ehloResponse) - { - $capabilities = []; - $ehloResponse = trim($ehloResponse ?? ''); - $lines = explode("\r\n", $ehloResponse); - array_shift($lines); - foreach ($lines as $line) { - if (preg_match('/^[0-9]{3}[ -]([A-Z0-9-]+)((?:[ =].*)?)$/Di', $line, $matches)) { - $keyword = strtoupper($matches[1]); - $paramStr = strtoupper(ltrim($matches[2], ' =')); - $params = !empty($paramStr) ? explode(' ', $paramStr) : []; - $capabilities[$keyword] = $params; - } - } + /** Determine ESMTP capabilities by function group */ + private function getCapabilities($ehloResponse) + { + $capabilities = []; + $ehloResponse = trim($ehloResponse ?? ''); + $lines = explode("\r\n", $ehloResponse); + array_shift($lines); + foreach ($lines as $line) { + if (preg_match('/^[0-9]{3}[ -]([A-Z0-9-]+)((?:[ =].*)?)$/Di', $line, $matches)) { + $keyword = strtoupper($matches[1]); + $paramStr = strtoupper(ltrim($matches[2], ' =')); + $params = !empty($paramStr) ? explode(' ', $paramStr) : []; + $capabilities[$keyword] = $params; + } + } - return $capabilities; - } + return $capabilities; + } - /** Set parameters which are used by each extension handler */ - private function setHandlerParams() - { - foreach ($this->handlers as $keyword => $handler) { - if (\array_key_exists($keyword, $this->capabilities)) { - $handler->setKeywordParams($this->capabilities[$keyword]); - } - } - } + /** Set parameters which are used by each extension handler */ + private function setHandlerParams() + { + foreach ($this->handlers as $keyword => $handler) { + if (\array_key_exists($keyword, $this->capabilities)) { + $handler->setKeywordParams($this->capabilities[$keyword]); + } + } + } - /** Get ESMTP handlers which are currently ok to use */ - private function getActiveHandlers() - { - $handlers = []; - foreach ($this->handlers as $keyword => $handler) { - if (\array_key_exists($keyword, $this->capabilities)) { - $handlers[] = $handler; - } - } + /** Get ESMTP handlers which are currently ok to use */ + private function getActiveHandlers() + { + $handlers = []; + foreach ($this->handlers as $keyword => $handler) { + if (\array_key_exists($keyword, $this->capabilities)) { + $handlers[] = $handler; + } + } - return $handlers; - } + return $handlers; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/FailoverTransport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/FailoverTransport.php index 1e007b00201..1a4b4754f07 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/FailoverTransport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/FailoverTransport.php @@ -15,89 +15,89 @@ */ class Swift_Transport_FailoverTransport extends Swift_Transport_LoadBalancedTransport { - /** - * Registered transport currently used. - * - * @var Swift_Transport - */ - private $currentTransport; + /** + * Registered transport currently used. + * + * @var Swift_Transport + */ + private $currentTransport; - // needed as __construct is called from elsewhere explicitly - public function __construct() - { - parent::__construct(); - } + // needed as __construct is called from elsewhere explicitly + public function __construct() + { + parent::__construct(); + } - /** - * {@inheritdoc} - */ - public function ping() - { - $maxTransports = \count($this->transports); - for ($i = 0; $i < $maxTransports - && $transport = $this->getNextTransport(); ++$i) { - if ($transport->ping()) { - return true; - } else { - $this->killCurrentTransport(); - } - } + /** + * {@inheritdoc} + */ + public function ping() + { + $maxTransports = \count($this->transports); + for ($i = 0; $i < $maxTransports + && $transport = $this->getNextTransport(); ++$i) { + if ($transport->ping()) { + return true; + } else { + $this->killCurrentTransport(); + } + } - return \count($this->transports) > 0; - } + return \count($this->transports) > 0; + } - /** - * Send the given Message. - * - * Recipient/sender data will be retrieved from the Message API. - * The return value is the number of recipients who were accepted for delivery. - * - * @param string[] $failedRecipients An array of failures by-reference - * - * @return int - */ - public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) - { - $maxTransports = \count($this->transports); - $sent = 0; - $this->lastUsedTransport = null; + /** + * Send the given Message. + * + * Recipient/sender data will be retrieved from the Message API. + * The return value is the number of recipients who were accepted for delivery. + * + * @param string[] $failedRecipients An array of failures by-reference + * + * @return int + */ + public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) + { + $maxTransports = \count($this->transports); + $sent = 0; + $this->lastUsedTransport = null; - for ($i = 0; $i < $maxTransports - && $transport = $this->getNextTransport(); ++$i) { - try { - if (!$transport->isStarted()) { - $transport->start(); - } + for ($i = 0; $i < $maxTransports + && $transport = $this->getNextTransport(); ++$i) { + try { + if (!$transport->isStarted()) { + $transport->start(); + } - if ($sent = $transport->send($message, $failedRecipients)) { - $this->lastUsedTransport = $transport; + if ($sent = $transport->send($message, $failedRecipients)) { + $this->lastUsedTransport = $transport; - return $sent; - } - } catch (Swift_TransportException $e) { - $this->killCurrentTransport(); - } - } + return $sent; + } + } catch (Swift_TransportException $e) { + $this->killCurrentTransport(); + } + } - if (0 == \count($this->transports)) { - throw new Swift_TransportException('All Transports in FailoverTransport failed, or no Transports available'); - } + if (0 == \count($this->transports)) { + throw new Swift_TransportException('All Transports in FailoverTransport failed, or no Transports available'); + } - return $sent; - } + return $sent; + } - protected function getNextTransport() - { - if (!isset($this->currentTransport)) { - $this->currentTransport = parent::getNextTransport(); - } + protected function getNextTransport() + { + if (!isset($this->currentTransport)) { + $this->currentTransport = parent::getNextTransport(); + } - return $this->currentTransport; - } + return $this->currentTransport; + } - protected function killCurrentTransport() - { - $this->currentTransport = null; - parent::killCurrentTransport(); - } + protected function killCurrentTransport() + { + $this->currentTransport = null; + parent::killCurrentTransport(); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/IoBuffer.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/IoBuffer.php index 799ad8ae085..50f1e5e403c 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/IoBuffer.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/IoBuffer.php @@ -15,51 +15,51 @@ */ interface Swift_Transport_IoBuffer extends Swift_InputByteStream, Swift_OutputByteStream { - /** A socket buffer over TCP */ - const TYPE_SOCKET = 0x0001; + /** A socket buffer over TCP */ + const TYPE_SOCKET = 0x0001; - /** A process buffer with I/O support */ - const TYPE_PROCESS = 0x0010; + /** A process buffer with I/O support */ + const TYPE_PROCESS = 0x0010; - /** - * Perform any initialization needed, using the given $params. - * - * Parameters will vary depending upon the type of IoBuffer used. - */ - public function initialize(array $params); + /** + * Perform any initialization needed, using the given $params. + * + * Parameters will vary depending upon the type of IoBuffer used. + */ + public function initialize(array $params); - /** - * Set an individual param on the buffer (e.g. switching to SSL). - * - * @param string $param - * @param mixed $value - */ - public function setParam($param, $value); + /** + * Set an individual param on the buffer (e.g. switching to SSL). + * + * @param string $param + * @param mixed $value + */ + public function setParam($param, $value); - /** - * Perform any shutdown logic needed. - */ - public function terminate(); + /** + * Perform any shutdown logic needed. + */ + public function terminate(); - /** - * Set an array of string replacements which should be made on data written - * to the buffer. - * - * This could replace LF with CRLF for example. - * - * @param string[] $replacements - */ - public function setWriteTranslations(array $replacements); + /** + * Set an array of string replacements which should be made on data written + * to the buffer. + * + * This could replace LF with CRLF for example. + * + * @param string[] $replacements + */ + public function setWriteTranslations(array $replacements); - /** - * Get a line of output (including any CRLF). - * - * The $sequence number comes from any writes and may or may not be used - * depending upon the implementation. - * - * @param int $sequence of last write to scan from - * - * @return string - */ - public function readLine($sequence); + /** + * Get a line of output (including any CRLF). + * + * The $sequence number comes from any writes and may or may not be used + * depending upon the implementation. + * + * @param int $sequence of last write to scan from + * + * @return string + */ + public function readLine($sequence); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/LoadBalancedTransport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/LoadBalancedTransport.php index e4262069ffb..0b5ba9d304e 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/LoadBalancedTransport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/LoadBalancedTransport.php @@ -15,178 +15,178 @@ */ class Swift_Transport_LoadBalancedTransport implements Swift_Transport { - /** - * Transports which are deemed useless. - * - * @var Swift_Transport[] - */ - private $deadTransports = []; + /** + * Transports which are deemed useless. + * + * @var Swift_Transport[] + */ + private $deadTransports = []; - /** - * The Transports which are used in rotation. - * - * @var Swift_Transport[] - */ - protected $transports = []; + /** + * The Transports which are used in rotation. + * + * @var Swift_Transport[] + */ + protected $transports = []; - /** - * The Transport used in the last successful send operation. - * - * @var Swift_Transport - */ - protected $lastUsedTransport = null; + /** + * The Transport used in the last successful send operation. + * + * @var Swift_Transport + */ + protected $lastUsedTransport = null; - // needed as __construct is called from elsewhere explicitly - public function __construct() - { - } + // needed as __construct is called from elsewhere explicitly + public function __construct() + { + } - /** - * Set $transports to delegate to. - * - * @param Swift_Transport[] $transports - */ - public function setTransports(array $transports) - { - $this->transports = $transports; - $this->deadTransports = []; - } + /** + * Set $transports to delegate to. + * + * @param Swift_Transport[] $transports + */ + public function setTransports(array $transports) + { + $this->transports = $transports; + $this->deadTransports = []; + } - /** - * Get $transports to delegate to. - * - * @return Swift_Transport[] - */ - public function getTransports() - { - return array_merge($this->transports, $this->deadTransports); - } + /** + * Get $transports to delegate to. + * + * @return Swift_Transport[] + */ + public function getTransports() + { + return array_merge($this->transports, $this->deadTransports); + } - /** - * Get the Transport used in the last successful send operation. - * - * @return Swift_Transport - */ - public function getLastUsedTransport() - { - return $this->lastUsedTransport; - } + /** + * Get the Transport used in the last successful send operation. + * + * @return Swift_Transport + */ + public function getLastUsedTransport() + { + return $this->lastUsedTransport; + } - /** - * Test if this Transport mechanism has started. - * - * @return bool - */ - public function isStarted() - { - return \count($this->transports) > 0; - } + /** + * Test if this Transport mechanism has started. + * + * @return bool + */ + public function isStarted() + { + return \count($this->transports) > 0; + } - /** - * Start this Transport mechanism. - */ - public function start() - { - $this->transports = array_merge($this->transports, $this->deadTransports); - } + /** + * Start this Transport mechanism. + */ + public function start() + { + $this->transports = array_merge($this->transports, $this->deadTransports); + } - /** - * Stop this Transport mechanism. - */ - public function stop() - { - foreach ($this->transports as $transport) { - $transport->stop(); - } - } + /** + * Stop this Transport mechanism. + */ + public function stop() + { + foreach ($this->transports as $transport) { + $transport->stop(); + } + } - /** - * {@inheritdoc} - */ - public function ping() - { - foreach ($this->transports as $transport) { - if (!$transport->ping()) { - $this->killCurrentTransport(); - } - } + /** + * {@inheritdoc} + */ + public function ping() + { + foreach ($this->transports as $transport) { + if (!$transport->ping()) { + $this->killCurrentTransport(); + } + } - return \count($this->transports) > 0; - } + return \count($this->transports) > 0; + } - /** - * Send the given Message. - * - * Recipient/sender data will be retrieved from the Message API. - * The return value is the number of recipients who were accepted for delivery. - * - * @param string[] $failedRecipients An array of failures by-reference - * - * @return int - */ - public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) - { - $maxTransports = \count($this->transports); - $sent = 0; - $this->lastUsedTransport = null; + /** + * Send the given Message. + * + * Recipient/sender data will be retrieved from the Message API. + * The return value is the number of recipients who were accepted for delivery. + * + * @param string[] $failedRecipients An array of failures by-reference + * + * @return int + */ + public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) + { + $maxTransports = \count($this->transports); + $sent = 0; + $this->lastUsedTransport = null; - for ($i = 0; $i < $maxTransports - && $transport = $this->getNextTransport(); ++$i) { - try { - if (!$transport->isStarted()) { - $transport->start(); - } - if ($sent = $transport->send($message, $failedRecipients)) { - $this->lastUsedTransport = $transport; - break; - } - } catch (Swift_TransportException $e) { - $this->killCurrentTransport(); - } - } + for ($i = 0; $i < $maxTransports + && $transport = $this->getNextTransport(); ++$i) { + try { + if (!$transport->isStarted()) { + $transport->start(); + } + if ($sent = $transport->send($message, $failedRecipients)) { + $this->lastUsedTransport = $transport; + break; + } + } catch (Swift_TransportException $e) { + $this->killCurrentTransport(); + } + } - if (0 == \count($this->transports)) { - throw new Swift_TransportException('All Transports in LoadBalancedTransport failed, or no Transports available'); - } + if (0 == \count($this->transports)) { + throw new Swift_TransportException('All Transports in LoadBalancedTransport failed, or no Transports available'); + } - return $sent; - } + return $sent; + } - /** - * Register a plugin. - */ - public function registerPlugin(Swift_Events_EventListener $plugin) - { - foreach ($this->transports as $transport) { - $transport->registerPlugin($plugin); - } - } + /** + * Register a plugin. + */ + public function registerPlugin(Swift_Events_EventListener $plugin) + { + foreach ($this->transports as $transport) { + $transport->registerPlugin($plugin); + } + } - /** - * Rotates the transport list around and returns the first instance. - * - * @return Swift_Transport - */ - protected function getNextTransport() - { - if ($next = array_shift($this->transports)) { - $this->transports[] = $next; - } + /** + * Rotates the transport list around and returns the first instance. + * + * @return Swift_Transport + */ + protected function getNextTransport() + { + if ($next = array_shift($this->transports)) { + $this->transports[] = $next; + } - return $next; - } + return $next; + } - /** - * Tag the currently used (top of stack) transport as dead/useless. - */ - protected function killCurrentTransport() - { - if ($transport = array_pop($this->transports)) { - try { - $transport->stop(); - } catch (Exception $e) { - } - $this->deadTransports[] = $transport; - } - } + /** + * Tag the currently used (top of stack) transport as dead/useless. + */ + protected function killCurrentTransport() + { + if ($transport = array_pop($this->transports)) { + try { + $transport->stop(); + } catch (Exception $e) { + } + $this->deadTransports[] = $transport; + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/NullTransport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/NullTransport.php index ec82fced23b..7d910db5a58 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/NullTransport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/NullTransport.php @@ -15,84 +15,84 @@ */ class Swift_Transport_NullTransport implements Swift_Transport { - /** The event dispatcher from the plugin API */ - private $eventDispatcher; + /** The event dispatcher from the plugin API */ + private $eventDispatcher; - /** - * Constructor. - */ - public function __construct(Swift_Events_EventDispatcher $eventDispatcher) - { - $this->eventDispatcher = $eventDispatcher; - } + /** + * Constructor. + */ + public function __construct(Swift_Events_EventDispatcher $eventDispatcher) + { + $this->eventDispatcher = $eventDispatcher; + } - /** - * Tests if this Transport mechanism has started. - * - * @return bool - */ - public function isStarted() - { - return true; - } + /** + * Tests if this Transport mechanism has started. + * + * @return bool + */ + public function isStarted() + { + return true; + } - /** - * Starts this Transport mechanism. - */ - public function start() - { - } + /** + * Starts this Transport mechanism. + */ + public function start() + { + } - /** - * Stops this Transport mechanism. - */ - public function stop() - { - } + /** + * Stops this Transport mechanism. + */ + public function stop() + { + } - /** - * {@inheritdoc} - */ - public function ping() - { - return true; - } + /** + * {@inheritdoc} + */ + public function ping() + { + return true; + } - /** - * Sends the given message. - * - * @param string[] $failedRecipients An array of failures by-reference - * - * @return int The number of sent emails - */ - public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) - { - if ($evt = $this->eventDispatcher->createSendEvent($this, $message)) { - $this->eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed'); - if ($evt->bubbleCancelled()) { - return 0; - } - } + /** + * Sends the given message. + * + * @param string[] $failedRecipients An array of failures by-reference + * + * @return int The number of sent emails + */ + public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) + { + if ($evt = $this->eventDispatcher->createSendEvent($this, $message)) { + $this->eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed'); + if ($evt->bubbleCancelled()) { + return 0; + } + } - if ($evt) { - $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS); - $this->eventDispatcher->dispatchEvent($evt, 'sendPerformed'); - } + if ($evt) { + $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS); + $this->eventDispatcher->dispatchEvent($evt, 'sendPerformed'); + } - $count = ( - \count((array) $message->getTo()) - + \count((array) $message->getCc()) - + \count((array) $message->getBcc()) - ); + $count = ( + \count((array) $message->getTo()) + + \count((array) $message->getCc()) + + \count((array) $message->getBcc()) + ); - return $count; - } + return $count; + } - /** - * Register a plugin. - */ - public function registerPlugin(Swift_Events_EventListener $plugin) - { - $this->eventDispatcher->bindEventListener($plugin); - } + /** + * Register a plugin. + */ + public function registerPlugin(Swift_Events_EventListener $plugin) + { + $this->eventDispatcher->bindEventListener($plugin); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/SendmailTransport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/SendmailTransport.php index e1723b24f10..65a434d1173 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/SendmailTransport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/SendmailTransport.php @@ -19,139 +19,140 @@ */ class Swift_Transport_SendmailTransport extends Swift_Transport_AbstractSmtpTransport { - /** - * Connection buffer parameters. - * - * @var array - */ - private $params = [ - 'timeout' => 30, - 'blocking' => 1, - 'command' => '/usr/sbin/sendmail -bs', - 'type' => Swift_Transport_IoBuffer::TYPE_PROCESS, - ]; + /** + * Connection buffer parameters. + * + * @var array + */ + private $params = [ + 'timeout' => 30, + 'blocking' => 1, + 'command' => '/usr/sbin/sendmail -bs', + 'type' => Swift_Transport_IoBuffer::TYPE_PROCESS, + ]; - /** - * Create a new SendmailTransport with $buf for I/O. - * - * @param string $localDomain - */ - public function __construct(Swift_Transport_IoBuffer $buf, Swift_Events_EventDispatcher $dispatcher, $localDomain = '127.0.0.1', Swift_AddressEncoder $addressEncoder = null) - { - parent::__construct($buf, $dispatcher, $localDomain, $addressEncoder); - } + /** + * Create a new SendmailTransport with $buf for I/O. + * + * @param string $localDomain + */ + public function __construct(Swift_Transport_IoBuffer $buf, Swift_Events_EventDispatcher $dispatcher, $localDomain = '127.0.0.1', Swift_AddressEncoder $addressEncoder = null) + { + parent::__construct($buf, $dispatcher, $localDomain, $addressEncoder); + } - /** - * Start the standalone SMTP session if running in -bs mode. - */ - public function start() - { - if (false !== strpos($this->getCommand(), ' -bs')) { - parent::start(); - } - } + /** + * Start the standalone SMTP session if running in -bs mode. + */ + public function start() + { + if (false !== strpos($this->getCommand(), ' -bs')) { + parent::start(); + } + } - /** - * Set the command to invoke. - * - * If using -t mode you are strongly advised to include -oi or -i in the flags. - * For example: /usr/sbin/sendmail -oi -t - * Swift will append a -f flag if one is not present. - * - * The recommended mode is "-bs" since it is interactive and failure notifications - * are hence possible. - * - * @param string $command - * - * @return $this - */ - public function setCommand($command) - { - $this->params['command'] = $command; + /** + * Set the command to invoke. + * + * If using -t mode you are strongly advised to include -oi or -i in the flags. + * For example: /usr/sbin/sendmail -oi -t + * Swift will append a -f flag if one is not present. + * + * The recommended mode is "-bs" since it is interactive and failure notifications + * are hence possible. + * + * @param string $command + * + * @return $this + */ + public function setCommand($command) + { + $this->params['command'] = $command; - return $this; - } + return $this; + } - /** - * Get the sendmail command which will be invoked. - * - * @return string - */ - public function getCommand() - { - return $this->params['command']; - } + /** + * Get the sendmail command which will be invoked. + * + * @return string + */ + public function getCommand() + { + return $this->params['command']; + } - /** - * Send the given Message. - * - * Recipient/sender data will be retrieved from the Message API. - * - * The return value is the number of recipients who were accepted for delivery. - * NOTE: If using 'sendmail -t' you will not be aware of any failures until - * they bounce (i.e. send() will always return 100% success). - * - * @param string[] $failedRecipients An array of failures by-reference - * - * @return int - */ - public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) - { - $failedRecipients = (array) $failedRecipients; - $command = $this->getCommand(); - $buffer = $this->getBuffer(); - $count = 0; + /** + * Send the given Message. + * + * Recipient/sender data will be retrieved from the Message API. + * + * The return value is the number of recipients who were accepted for delivery. + * NOTE: If using 'sendmail -t' you will not be aware of any failures until + * they bounce (i.e. send() will always return 100% success). + * + * @param string[] $failedRecipients An array of failures by-reference + * + * @return int + */ + public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) + { + $failedRecipients = (array) $failedRecipients; + $command = $this->getCommand(); + $buffer = $this->getBuffer(); + $count = 0; - if (false !== strpos($command, ' -t')) { - if ($evt = $this->eventDispatcher->createSendEvent($this, $message)) { - $this->eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed'); - if ($evt->bubbleCancelled()) { - return 0; - } - } + if (false !== strpos($command, ' -t')) { + if ($evt = $this->eventDispatcher->createSendEvent($this, $message)) { + $this->eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed'); + if ($evt->bubbleCancelled()) { + return 0; + } + } - if (false === strpos($command, ' -f')) { - $command .= ' -f'.escapeshellarg($this->getReversePath($message) ?? ''); - } + if (false === strpos($command, ' -f')) { + $command .= ' -f'.escapeshellarg($this->getReversePath($message) ?? ''); + } - $buffer->initialize(array_merge($this->params, ['command' => $command])); + $buffer->initialize(array_merge($this->params, ['command' => $command])); - if (false === strpos($command, ' -i') && false === strpos($command, ' -oi')) { - $buffer->setWriteTranslations(["\r\n" => "\n", "\n." => "\n.."]); - } else { - $buffer->setWriteTranslations(["\r\n" => "\n"]); - } + if (false === strpos($command, ' -i') && false === strpos($command, ' -oi')) { + $buffer->setWriteTranslations(["\r\n" => "\n", "\n." => "\n.."]); + } else { + $buffer->setWriteTranslations(["\r\n" => "\n"]); + } - $count = \count((array) $message->getTo()) - + \count((array) $message->getCc()) - + \count((array) $message->getBcc()); - $message->toByteStream($buffer); - $buffer->flushBuffers(); - $buffer->setWriteTranslations([]); - $buffer->terminate(); + $count = \count((array) $message->getTo()) + + \count((array) $message->getCc()) + + \count((array) $message->getBcc()) + ; + $message->toByteStream($buffer); + $buffer->flushBuffers(); + $buffer->setWriteTranslations([]); + $buffer->terminate(); - if ($evt) { - $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS); - $evt->setFailedRecipients($failedRecipients); - $this->eventDispatcher->dispatchEvent($evt, 'sendPerformed'); - } + if ($evt) { + $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS); + $evt->setFailedRecipients($failedRecipients); + $this->eventDispatcher->dispatchEvent($evt, 'sendPerformed'); + } - $message->generateId(); - } elseif (false !== strpos($command, ' -bs')) { - $count = parent::send($message, $failedRecipients); - } else { - $this->throwException(new Swift_TransportException( - 'Unsupported sendmail command flags ['.$command.']. '. - 'Must be one of "-bs" or "-t" but can include additional flags.' - )); - } + $message->generateId(); + } elseif (false !== strpos($command, ' -bs')) { + $count = parent::send($message, $failedRecipients); + } else { + $this->throwException(new Swift_TransportException( + 'Unsupported sendmail command flags ['.$command.']. '. + 'Must be one of "-bs" or "-t" but can include additional flags.' + )); + } - return $count; - } + return $count; + } - /** Get the params to initialize the buffer */ - protected function getBufferParams() - { - return $this->params; - } + /** Get the params to initialize the buffer */ + protected function getBufferParams() + { + return $this->params; + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/SmtpAgent.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/SmtpAgent.php index bb761237b1c..e8ce65c2648 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/SmtpAgent.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/SmtpAgent.php @@ -15,22 +15,22 @@ */ interface Swift_Transport_SmtpAgent { - /** - * Get the IoBuffer where read/writes are occurring. - * - * @return Swift_Transport_IoBuffer - */ - public function getBuffer(); + /** + * Get the IoBuffer where read/writes are occurring. + * + * @return Swift_Transport_IoBuffer + */ + public function getBuffer(); - /** - * Run a command against the buffer, expecting the given response codes. - * - * If no response codes are given, the response will not be validated. - * If codes are given, an exception will be thrown on an invalid response. - * - * @param string $command - * @param int[] $codes - * @param string[] $failures An array of failures by-reference - */ - public function executeCommand($command, $codes = [], &$failures = null); + /** + * Run a command against the buffer, expecting the given response codes. + * + * If no response codes are given, the response will not be validated. + * If codes are given, an exception will be thrown on an invalid response. + * + * @param string $command + * @param int[] $codes + * @param string[] $failures An array of failures by-reference + */ + public function executeCommand($command, $codes = [], &$failures = null); } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/SpoolTransport.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/SpoolTransport.php index f7c19d05579..0cb6a5b80a9 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/SpoolTransport.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/SpoolTransport.php @@ -15,106 +15,106 @@ */ class Swift_Transport_SpoolTransport implements Swift_Transport { - /** The spool instance */ - private $spool; + /** The spool instance */ + private $spool; - /** The event dispatcher from the plugin API */ - private $eventDispatcher; + /** The event dispatcher from the plugin API */ + private $eventDispatcher; - /** - * Constructor. - */ - public function __construct(Swift_Events_EventDispatcher $eventDispatcher, Swift_Spool $spool = null) - { - $this->eventDispatcher = $eventDispatcher; - $this->spool = $spool; - } + /** + * Constructor. + */ + public function __construct(Swift_Events_EventDispatcher $eventDispatcher, Swift_Spool $spool = null) + { + $this->eventDispatcher = $eventDispatcher; + $this->spool = $spool; + } - /** - * Sets the spool object. - * - * @return $this - */ - public function setSpool(Swift_Spool $spool) - { - $this->spool = $spool; + /** + * Sets the spool object. + * + * @return $this + */ + public function setSpool(Swift_Spool $spool) + { + $this->spool = $spool; - return $this; - } + return $this; + } - /** - * Get the spool object. - * - * @return Swift_Spool - */ - public function getSpool() - { - return $this->spool; - } + /** + * Get the spool object. + * + * @return Swift_Spool + */ + public function getSpool() + { + return $this->spool; + } - /** - * Tests if this Transport mechanism has started. - * - * @return bool - */ - public function isStarted() - { - return true; - } + /** + * Tests if this Transport mechanism has started. + * + * @return bool + */ + public function isStarted() + { + return true; + } - /** - * Starts this Transport mechanism. - */ - public function start() - { - } + /** + * Starts this Transport mechanism. + */ + public function start() + { + } - /** - * Stops this Transport mechanism. - */ - public function stop() - { - } + /** + * Stops this Transport mechanism. + */ + public function stop() + { + } - /** - * {@inheritdoc} - */ - public function ping() - { - return true; - } + /** + * {@inheritdoc} + */ + public function ping() + { + return true; + } - /** - * Sends the given message. - * - * @param string[] $failedRecipients An array of failures by-reference - * - * @return int The number of sent e-mail's - */ - public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) - { - if ($evt = $this->eventDispatcher->createSendEvent($this, $message)) { - $this->eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed'); - if ($evt->bubbleCancelled()) { - return 0; - } - } + /** + * Sends the given message. + * + * @param string[] $failedRecipients An array of failures by-reference + * + * @return int The number of sent e-mail's + */ + public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) + { + if ($evt = $this->eventDispatcher->createSendEvent($this, $message)) { + $this->eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed'); + if ($evt->bubbleCancelled()) { + return 0; + } + } - $success = $this->spool->queueMessage($message); + $success = $this->spool->queueMessage($message); - if ($evt) { - $evt->setResult($success ? Swift_Events_SendEvent::RESULT_SPOOLED : Swift_Events_SendEvent::RESULT_FAILED); - $this->eventDispatcher->dispatchEvent($evt, 'sendPerformed'); - } + if ($evt) { + $evt->setResult($success ? Swift_Events_SendEvent::RESULT_SPOOLED : Swift_Events_SendEvent::RESULT_FAILED); + $this->eventDispatcher->dispatchEvent($evt, 'sendPerformed'); + } - return 1; - } + return 1; + } - /** - * Register a plugin. - */ - public function registerPlugin(Swift_Events_EventListener $plugin) - { - $this->eventDispatcher->bindEventListener($plugin); - } + /** + * Register a plugin. + */ + public function registerPlugin(Swift_Events_EventListener $plugin) + { + $this->eventDispatcher->bindEventListener($plugin); + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php index 6a09db7938f..70782ada044 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php @@ -15,305 +15,305 @@ */ class Swift_Transport_StreamBuffer extends Swift_ByteStream_AbstractFilterableInputStream implements Swift_Transport_IoBuffer { - /** A primary socket */ - private $stream; + /** A primary socket */ + private $stream; - /** The input stream */ - private $in; + /** The input stream */ + private $in; - /** The output stream */ - private $out; + /** The output stream */ + private $out; - /** Buffer initialization parameters */ - private $params = []; + /** Buffer initialization parameters */ + private $params = []; - /** The ReplacementFilterFactory */ - private $replacementFactory; + /** The ReplacementFilterFactory */ + private $replacementFactory; - /** Translations performed on data being streamed into the buffer */ - private $translations = []; + /** Translations performed on data being streamed into the buffer */ + private $translations = []; - /** - * Create a new StreamBuffer using $replacementFactory for transformations. - */ - public function __construct(Swift_ReplacementFilterFactory $replacementFactory) - { - $this->replacementFactory = $replacementFactory; - } + /** + * Create a new StreamBuffer using $replacementFactory for transformations. + */ + public function __construct(Swift_ReplacementFilterFactory $replacementFactory) + { + $this->replacementFactory = $replacementFactory; + } - /** - * Perform any initialization needed, using the given $params. - * - * Parameters will vary depending upon the type of IoBuffer used. - */ - public function initialize(array $params) - { - $this->params = $params; - switch ($params['type']) { - case self::TYPE_PROCESS: - $this->establishProcessConnection(); - break; - case self::TYPE_SOCKET: - default: - $this->establishSocketConnection(); - break; - } - } + /** + * Perform any initialization needed, using the given $params. + * + * Parameters will vary depending upon the type of IoBuffer used. + */ + public function initialize(array $params) + { + $this->params = $params; + switch ($params['type']) { + case self::TYPE_PROCESS: + $this->establishProcessConnection(); + break; + case self::TYPE_SOCKET: + default: + $this->establishSocketConnection(); + break; + } + } - /** - * Set an individual param on the buffer (e.g. switching to SSL). - * - * @param string $param - * @param mixed $value - */ - public function setParam($param, $value) - { - if (isset($this->stream)) { - switch ($param) { - case 'timeout': - if ($this->stream) { - stream_set_timeout($this->stream, $value); - } - break; + /** + * Set an individual param on the buffer (e.g. switching to SSL). + * + * @param string $param + * @param mixed $value + */ + public function setParam($param, $value) + { + if (isset($this->stream)) { + switch ($param) { + case 'timeout': + if ($this->stream) { + stream_set_timeout($this->stream, $value); + } + break; - case 'blocking': - if ($this->stream) { - stream_set_blocking($this->stream, 1); - } - } - } - $this->params[$param] = $value; - } + case 'blocking': + if ($this->stream) { + stream_set_blocking($this->stream, 1); + } + } + } + $this->params[$param] = $value; + } - public function startTLS() - { - // STREAM_CRYPTO_METHOD_TLS_CLIENT only allow tls1.0 connections (some php versions) - // To support modern tls we allow explicit tls1.0, tls1.1, tls1.2 - // Ssl3 and older are not allowed because they are vulnerable - // @TODO make tls arguments configurable - return stream_socket_enable_crypto($this->stream, true, STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT); - } + public function startTLS() + { + // STREAM_CRYPTO_METHOD_TLS_CLIENT only allow tls1.0 connections (some php versions) + // To support modern tls we allow explicit tls1.0, tls1.1, tls1.2 + // Ssl3 and older are not allowed because they are vulnerable + // @TODO make tls arguments configurable + return stream_socket_enable_crypto($this->stream, true, STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT); + } - /** - * Perform any shutdown logic needed. - */ - public function terminate() - { - if (isset($this->stream)) { - switch ($this->params['type']) { - case self::TYPE_PROCESS: - fclose($this->in); - fclose($this->out); - proc_close($this->stream); - break; - case self::TYPE_SOCKET: - default: - fclose($this->stream); - break; - } - } - $this->stream = null; - $this->out = null; - $this->in = null; - } + /** + * Perform any shutdown logic needed. + */ + public function terminate() + { + if (isset($this->stream)) { + switch ($this->params['type']) { + case self::TYPE_PROCESS: + fclose($this->in); + fclose($this->out); + proc_close($this->stream); + break; + case self::TYPE_SOCKET: + default: + fclose($this->stream); + break; + } + } + $this->stream = null; + $this->out = null; + $this->in = null; + } - /** - * Set an array of string replacements which should be made on data written - * to the buffer. - * - * This could replace LF with CRLF for example. - * - * @param string[] $replacements - */ - public function setWriteTranslations(array $replacements) - { - foreach ($this->translations as $search => $replace) { - if (!isset($replacements[$search])) { - $this->removeFilter($search); - unset($this->translations[$search]); - } - } + /** + * Set an array of string replacements which should be made on data written + * to the buffer. + * + * This could replace LF with CRLF for example. + * + * @param string[] $replacements + */ + public function setWriteTranslations(array $replacements) + { + foreach ($this->translations as $search => $replace) { + if (!isset($replacements[$search])) { + $this->removeFilter($search); + unset($this->translations[$search]); + } + } - foreach ($replacements as $search => $replace) { - if (!isset($this->translations[$search])) { - $this->addFilter( - $this->replacementFactory->createFilter($search, $replace), $search - ); - $this->translations[$search] = true; - } - } - } + foreach ($replacements as $search => $replace) { + if (!isset($this->translations[$search])) { + $this->addFilter( + $this->replacementFactory->createFilter($search, $replace), $search + ); + $this->translations[$search] = true; + } + } + } - /** - * Get a line of output (including any CRLF). - * - * The $sequence number comes from any writes and may or may not be used - * depending upon the implementation. - * - * @param int $sequence of last write to scan from - * - * @return string - * - * @throws Swift_IoException - */ - public function readLine($sequence) - { - if (isset($this->out) && !feof($this->out)) { - $line = fgets($this->out); - if (0 == \strlen($line)) { - $metas = stream_get_meta_data($this->out); - if ($metas['timed_out']) { - throw new Swift_IoException('Connection to '.$this->getReadConnectionDescription().' Timed Out'); - } - } + /** + * Get a line of output (including any CRLF). + * + * The $sequence number comes from any writes and may or may not be used + * depending upon the implementation. + * + * @param int $sequence of last write to scan from + * + * @return string + * + * @throws Swift_IoException + */ + public function readLine($sequence) + { + if (isset($this->out) && !feof($this->out)) { + $line = fgets($this->out); + if (0 == \strlen($line)) { + $metas = stream_get_meta_data($this->out); + if ($metas['timed_out']) { + throw new Swift_IoException('Connection to '.$this->getReadConnectionDescription().' Timed Out'); + } + } - return $line; - } - } + return $line; + } + } - /** - * Reads $length bytes from the stream into a string and moves the pointer - * through the stream by $length. - * - * If less bytes exist than are requested the remaining bytes are given instead. - * If no bytes are remaining at all, boolean false is returned. - * - * @param int $length - * - * @return string|bool - * - * @throws Swift_IoException - */ - public function read($length) - { - if (isset($this->out) && !feof($this->out)) { - $ret = fread($this->out, $length); - if (0 == \strlen($ret)) { - $metas = stream_get_meta_data($this->out); - if ($metas['timed_out']) { - throw new Swift_IoException('Connection to '.$this->getReadConnectionDescription().' Timed Out'); - } - } + /** + * Reads $length bytes from the stream into a string and moves the pointer + * through the stream by $length. + * + * If less bytes exist than are requested the remaining bytes are given instead. + * If no bytes are remaining at all, boolean false is returned. + * + * @param int $length + * + * @return string|bool + * + * @throws Swift_IoException + */ + public function read($length) + { + if (isset($this->out) && !feof($this->out)) { + $ret = fread($this->out, $length); + if (0 == \strlen($ret)) { + $metas = stream_get_meta_data($this->out); + if ($metas['timed_out']) { + throw new Swift_IoException('Connection to '.$this->getReadConnectionDescription().' Timed Out'); + } + } - return $ret; - } - } + return $ret; + } + } - /** Not implemented */ - public function setReadPointer($byteOffset) - { - } + /** Not implemented */ + public function setReadPointer($byteOffset) + { + } - /** Flush the stream contents */ - protected function flush() - { - if (isset($this->in)) { - fflush($this->in); - } - } + /** Flush the stream contents */ + protected function flush() + { + if (isset($this->in)) { + fflush($this->in); + } + } - /** Write this bytes to the stream */ - protected function doCommit($bytes) - { - if (isset($this->in)) { - $bytesToWrite = \strlen($bytes); - $totalBytesWritten = 0; + /** Write this bytes to the stream */ + protected function doCommit($bytes) + { + if (isset($this->in)) { + $bytesToWrite = \strlen($bytes); + $totalBytesWritten = 0; - while ($totalBytesWritten < $bytesToWrite) { - $bytesWritten = fwrite($this->in, substr($bytes, $totalBytesWritten)); - if (false === $bytesWritten || 0 === $bytesWritten) { - break; - } + while ($totalBytesWritten < $bytesToWrite) { + $bytesWritten = fwrite($this->in, substr($bytes, $totalBytesWritten)); + if (false === $bytesWritten || 0 === $bytesWritten) { + break; + } - $totalBytesWritten += $bytesWritten; - } + $totalBytesWritten += $bytesWritten; + } - if ($totalBytesWritten > 0) { - return ++$this->sequence; - } - } - } + if ($totalBytesWritten > 0) { + return ++$this->sequence; + } + } + } - /** - * Establishes a connection to a remote server. - */ - private function establishSocketConnection() - { - $host = $this->params['host']; - if (!empty($this->params['protocol'])) { - $host = $this->params['protocol'].'://'.$host; - } - $timeout = 15; - if (!empty($this->params['timeout'])) { - $timeout = $this->params['timeout']; - } - $options = []; - if (!empty($this->params['sourceIp'])) { - $options['socket']['bindto'] = $this->params['sourceIp'].':0'; - } + /** + * Establishes a connection to a remote server. + */ + private function establishSocketConnection() + { + $host = $this->params['host']; + if (!empty($this->params['protocol'])) { + $host = $this->params['protocol'].'://'.$host; + } + $timeout = 15; + if (!empty($this->params['timeout'])) { + $timeout = $this->params['timeout']; + } + $options = []; + if (!empty($this->params['sourceIp'])) { + $options['socket']['bindto'] = $this->params['sourceIp'].':0'; + } - if (isset($this->params['stream_context_options'])) { - $options = array_merge($options, $this->params['stream_context_options']); - } - $streamContext = stream_context_create($options); + if (isset($this->params['stream_context_options'])) { + $options = array_merge($options, $this->params['stream_context_options']); + } + $streamContext = stream_context_create($options); - set_error_handler(function ($type, $msg) { - throw new Swift_TransportException('Connection could not be established with host '.$this->params['host'].' :'.$msg); - }); - try { - $this->stream = stream_socket_client($host.':'.$this->params['port'], $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $streamContext); - } finally { - restore_error_handler(); - } + set_error_handler(function ($type, $msg) { + throw new Swift_TransportException('Connection could not be established with host '.$this->params['host'].' :'.$msg); + }); + try { + $this->stream = stream_socket_client($host.':'.$this->params['port'], $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $streamContext); + } finally { + restore_error_handler(); + } - if (!empty($this->params['blocking'])) { - stream_set_blocking($this->stream, 1); - } else { - stream_set_blocking($this->stream, 0); - } - stream_set_timeout($this->stream, $timeout); - $this->in = &$this->stream; - $this->out = &$this->stream; - } + if (!empty($this->params['blocking'])) { + stream_set_blocking($this->stream, 1); + } else { + stream_set_blocking($this->stream, 0); + } + stream_set_timeout($this->stream, $timeout); + $this->in = &$this->stream; + $this->out = &$this->stream; + } - /** - * Opens a process for input/output. - */ - private function establishProcessConnection() - { - $command = $this->params['command']; - $descriptorSpec = [ - 0 => ['pipe', 'r'], - 1 => ['pipe', 'w'], - 2 => ['pipe', 'w'], - ]; - $pipes = []; - $this->stream = proc_open($command, $descriptorSpec, $pipes); - stream_set_blocking($pipes[2], 0); - if ($err = stream_get_contents($pipes[2])) { - throw new Swift_TransportException('Process could not be started ['.$err.']'); - } - $this->in = &$pipes[0]; - $this->out = &$pipes[1]; - } + /** + * Opens a process for input/output. + */ + private function establishProcessConnection() + { + $command = $this->params['command']; + $descriptorSpec = [ + 0 => ['pipe', 'r'], + 1 => ['pipe', 'w'], + 2 => ['pipe', 'w'], + ]; + $pipes = []; + $this->stream = proc_open($command, $descriptorSpec, $pipes); + stream_set_blocking($pipes[2], 0); + if ($err = stream_get_contents($pipes[2])) { + throw new Swift_TransportException('Process could not be started ['.$err.']'); + } + $this->in = &$pipes[0]; + $this->out = &$pipes[1]; + } - private function getReadConnectionDescription() - { - switch ($this->params['type']) { - case self::TYPE_PROCESS: - return 'Process '.$this->params['command']; - break; + private function getReadConnectionDescription() + { + switch ($this->params['type']) { + case self::TYPE_PROCESS: + return 'Process '.$this->params['command']; + break; - case self::TYPE_SOCKET: - default: - $host = $this->params['host']; - if (!empty($this->params['protocol'])) { - $host = $this->params['protocol'].'://'.$host; - } - $host .= ':'.$this->params['port']; + case self::TYPE_SOCKET: + default: + $host = $this->params['host']; + if (!empty($this->params['protocol'])) { + $host = $this->params['protocol'].'://'.$host; + } + $host .= ':'.$this->params['port']; - return $host; - break; - } - } + return $host; + break; + } + } } diff --git a/htdocs/includes/swiftmailer/lib/classes/Swift/TransportException.php b/htdocs/includes/swiftmailer/lib/classes/Swift/TransportException.php index 763c9fed2ee..c7417455b3e 100644 --- a/htdocs/includes/swiftmailer/lib/classes/Swift/TransportException.php +++ b/htdocs/includes/swiftmailer/lib/classes/Swift/TransportException.php @@ -15,14 +15,14 @@ */ class Swift_TransportException extends Swift_IoException { - /** - * Create a new TransportException with $message. - * - * @param string $message - * @param int $code - */ - public function __construct($message, $code = 0, Exception $previous = null) - { - parent::__construct($message, $code, $previous); - } + /** + * Create a new TransportException with $message. + * + * @param string $message + * @param int $code + */ + public function __construct($message, $code = 0, Exception $previous = null) + { + parent::__construct($message, $code, $previous); + } } diff --git a/htdocs/includes/swiftmailer/lib/dependency_maps/cache_deps.php b/htdocs/includes/swiftmailer/lib/dependency_maps/cache_deps.php index c2f2df20bc3..9d94d774014 100644 --- a/htdocs/includes/swiftmailer/lib/dependency_maps/cache_deps.php +++ b/htdocs/includes/swiftmailer/lib/dependency_maps/cache_deps.php @@ -1,22 +1,23 @@ register('cache') - ->asAliasOf('cache.array') + ->register('cache') + ->asAliasOf('cache.array') - ->register('tempdir') - ->asValue('/tmp') + ->register('tempdir') + ->asValue('/tmp') - ->register('cache.null') - ->asSharedInstanceOf('Swift_KeyCache_NullKeyCache') + ->register('cache.null') + ->asSharedInstanceOf('Swift_KeyCache_NullKeyCache') - ->register('cache.array') - ->asSharedInstanceOf('Swift_KeyCache_ArrayKeyCache') - ->withDependencies(['cache.inputstream']) + ->register('cache.array') + ->asSharedInstanceOf('Swift_KeyCache_ArrayKeyCache') + ->withDependencies(['cache.inputstream']) - ->register('cache.disk') - ->asSharedInstanceOf('Swift_KeyCache_DiskKeyCache') - ->withDependencies(['cache.inputstream', 'tempdir']) + ->register('cache.disk') + ->asSharedInstanceOf('Swift_KeyCache_DiskKeyCache') + ->withDependencies(['cache.inputstream', 'tempdir']) - ->register('cache.inputstream') - ->asNewInstanceOf('Swift_KeyCache_SimpleKeyCacheInputStream'); + ->register('cache.inputstream') + ->asNewInstanceOf('Swift_KeyCache_SimpleKeyCacheInputStream') +; diff --git a/htdocs/includes/swiftmailer/lib/dependency_maps/mime_deps.php b/htdocs/includes/swiftmailer/lib/dependency_maps/mime_deps.php index 3ee1b762ebe..307756c89f3 100644 --- a/htdocs/includes/swiftmailer/lib/dependency_maps/mime_deps.php +++ b/htdocs/includes/swiftmailer/lib/dependency_maps/mime_deps.php @@ -3,131 +3,132 @@ require __DIR__.'/../mime_types.php'; Swift_DependencyContainer::getInstance() - ->register('properties.charset') - ->asValue('utf-8') + ->register('properties.charset') + ->asValue('utf-8') - ->register('email.validator') - ->asSharedInstanceOf('Egulias\EmailValidator\EmailValidator') + ->register('email.validator') + ->asSharedInstanceOf('Egulias\EmailValidator\EmailValidator') - ->register('mime.idgenerator.idright') - // As SERVER_NAME can come from the user in certain configurations, check that - // it does not contain forbidden characters (see RFC 952 and RFC 2181). Use - // preg_replace() instead of preg_match() to prevent DoS attacks with long host names. - ->asValue(!empty($_SERVER['SERVER_NAME']) && '' === preg_replace('/(?:^\[)?[a-zA-Z0-9-:\]_]+\.?/', '', $_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'swift.generated') + ->register('mime.idgenerator.idright') + // As SERVER_NAME can come from the user in certain configurations, check that + // it does not contain forbidden characters (see RFC 952 and RFC 2181). Use + // preg_replace() instead of preg_match() to prevent DoS attacks with long host names. + ->asValue(!empty($_SERVER['SERVER_NAME']) && '' === preg_replace('/(?:^\[)?[a-zA-Z0-9-:\]_]+\.?/', '', $_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'swift.generated') - ->register('mime.idgenerator') - ->asSharedInstanceOf('Swift_Mime_IdGenerator') - ->withDependencies([ - 'mime.idgenerator.idright', - ]) + ->register('mime.idgenerator') + ->asSharedInstanceOf('Swift_Mime_IdGenerator') + ->withDependencies([ + 'mime.idgenerator.idright', + ]) - ->register('mime.message') - ->asNewInstanceOf('Swift_Mime_SimpleMessage') - ->withDependencies([ - 'mime.headerset', - 'mime.textcontentencoder', - 'cache', - 'mime.idgenerator', - 'properties.charset', - ]) + ->register('mime.message') + ->asNewInstanceOf('Swift_Mime_SimpleMessage') + ->withDependencies([ + 'mime.headerset', + 'mime.textcontentencoder', + 'cache', + 'mime.idgenerator', + 'properties.charset', + ]) - ->register('mime.part') - ->asNewInstanceOf('Swift_Mime_MimePart') - ->withDependencies([ - 'mime.headerset', - 'mime.textcontentencoder', - 'cache', - 'mime.idgenerator', - 'properties.charset', - ]) + ->register('mime.part') + ->asNewInstanceOf('Swift_Mime_MimePart') + ->withDependencies([ + 'mime.headerset', + 'mime.textcontentencoder', + 'cache', + 'mime.idgenerator', + 'properties.charset', + ]) - ->register('mime.attachment') - ->asNewInstanceOf('Swift_Mime_Attachment') - ->withDependencies([ - 'mime.headerset', - 'mime.base64contentencoder', - 'cache', - 'mime.idgenerator', - ]) - ->addConstructorValue($swift_mime_types) + ->register('mime.attachment') + ->asNewInstanceOf('Swift_Mime_Attachment') + ->withDependencies([ + 'mime.headerset', + 'mime.base64contentencoder', + 'cache', + 'mime.idgenerator', + ]) + ->addConstructorValue($swift_mime_types) - ->register('mime.embeddedfile') - ->asNewInstanceOf('Swift_Mime_EmbeddedFile') - ->withDependencies([ - 'mime.headerset', - 'mime.base64contentencoder', - 'cache', - 'mime.idgenerator', - ]) - ->addConstructorValue($swift_mime_types) + ->register('mime.embeddedfile') + ->asNewInstanceOf('Swift_Mime_EmbeddedFile') + ->withDependencies([ + 'mime.headerset', + 'mime.base64contentencoder', + 'cache', + 'mime.idgenerator', + ]) + ->addConstructorValue($swift_mime_types) - ->register('mime.headerfactory') - ->asNewInstanceOf('Swift_Mime_SimpleHeaderFactory') - ->withDependencies([ - 'mime.qpheaderencoder', - 'mime.rfc2231encoder', - 'email.validator', - 'properties.charset', - 'address.idnaddressencoder', - ]) + ->register('mime.headerfactory') + ->asNewInstanceOf('Swift_Mime_SimpleHeaderFactory') + ->withDependencies([ + 'mime.qpheaderencoder', + 'mime.rfc2231encoder', + 'email.validator', + 'properties.charset', + 'address.idnaddressencoder', + ]) - ->register('mime.headerset') - ->asNewInstanceOf('Swift_Mime_SimpleHeaderSet') - ->withDependencies(['mime.headerfactory', 'properties.charset']) + ->register('mime.headerset') + ->asNewInstanceOf('Swift_Mime_SimpleHeaderSet') + ->withDependencies(['mime.headerfactory', 'properties.charset']) - ->register('mime.qpheaderencoder') - ->asNewInstanceOf('Swift_Mime_HeaderEncoder_QpHeaderEncoder') - ->withDependencies(['mime.charstream']) + ->register('mime.qpheaderencoder') + ->asNewInstanceOf('Swift_Mime_HeaderEncoder_QpHeaderEncoder') + ->withDependencies(['mime.charstream']) - ->register('mime.base64headerencoder') - ->asNewInstanceOf('Swift_Mime_HeaderEncoder_Base64HeaderEncoder') - ->withDependencies(['mime.charstream']) + ->register('mime.base64headerencoder') + ->asNewInstanceOf('Swift_Mime_HeaderEncoder_Base64HeaderEncoder') + ->withDependencies(['mime.charstream']) - ->register('mime.charstream') - ->asNewInstanceOf('Swift_CharacterStream_NgCharacterStream') - ->withDependencies(['mime.characterreaderfactory', 'properties.charset']) + ->register('mime.charstream') + ->asNewInstanceOf('Swift_CharacterStream_NgCharacterStream') + ->withDependencies(['mime.characterreaderfactory', 'properties.charset']) - ->register('mime.bytecanonicalizer') - ->asSharedInstanceOf('Swift_StreamFilters_ByteArrayReplacementFilter') - ->addConstructorValue([[0x0D, 0x0A], [0x0D], [0x0A]]) - ->addConstructorValue([[0x0A], [0x0A], [0x0D, 0x0A]]) + ->register('mime.bytecanonicalizer') + ->asSharedInstanceOf('Swift_StreamFilters_ByteArrayReplacementFilter') + ->addConstructorValue([[0x0D, 0x0A], [0x0D], [0x0A]]) + ->addConstructorValue([[0x0A], [0x0A], [0x0D, 0x0A]]) - ->register('mime.characterreaderfactory') - ->asSharedInstanceOf('Swift_CharacterReaderFactory_SimpleCharacterReaderFactory') + ->register('mime.characterreaderfactory') + ->asSharedInstanceOf('Swift_CharacterReaderFactory_SimpleCharacterReaderFactory') - ->register('mime.textcontentencoder') - ->asAliasOf('mime.qpcontentencoder') + ->register('mime.textcontentencoder') + ->asAliasOf('mime.qpcontentencoder') - ->register('mime.safeqpcontentencoder') - ->asNewInstanceOf('Swift_Mime_ContentEncoder_QpContentEncoder') - ->withDependencies(['mime.charstream', 'mime.bytecanonicalizer']) + ->register('mime.safeqpcontentencoder') + ->asNewInstanceOf('Swift_Mime_ContentEncoder_QpContentEncoder') + ->withDependencies(['mime.charstream', 'mime.bytecanonicalizer']) - ->register('mime.rawcontentencoder') - ->asNewInstanceOf('Swift_Mime_ContentEncoder_RawContentEncoder') + ->register('mime.rawcontentencoder') + ->asNewInstanceOf('Swift_Mime_ContentEncoder_RawContentEncoder') - ->register('mime.nativeqpcontentencoder') - ->withDependencies(['properties.charset']) - ->asNewInstanceOf('Swift_Mime_ContentEncoder_NativeQpContentEncoder') + ->register('mime.nativeqpcontentencoder') + ->withDependencies(['properties.charset']) + ->asNewInstanceOf('Swift_Mime_ContentEncoder_NativeQpContentEncoder') - ->register('mime.qpcontentencoder') - ->asNewInstanceOf('Swift_Mime_ContentEncoder_QpContentEncoderProxy') - ->withDependencies(['mime.safeqpcontentencoder', 'mime.nativeqpcontentencoder', 'properties.charset']) + ->register('mime.qpcontentencoder') + ->asNewInstanceOf('Swift_Mime_ContentEncoder_QpContentEncoderProxy') + ->withDependencies(['mime.safeqpcontentencoder', 'mime.nativeqpcontentencoder', 'properties.charset']) - ->register('mime.7bitcontentencoder') - ->asNewInstanceOf('Swift_Mime_ContentEncoder_PlainContentEncoder') - ->addConstructorValue('7bit') - ->addConstructorValue(true) + ->register('mime.7bitcontentencoder') + ->asNewInstanceOf('Swift_Mime_ContentEncoder_PlainContentEncoder') + ->addConstructorValue('7bit') + ->addConstructorValue(true) - ->register('mime.8bitcontentencoder') - ->asNewInstanceOf('Swift_Mime_ContentEncoder_PlainContentEncoder') - ->addConstructorValue('8bit') - ->addConstructorValue(true) + ->register('mime.8bitcontentencoder') + ->asNewInstanceOf('Swift_Mime_ContentEncoder_PlainContentEncoder') + ->addConstructorValue('8bit') + ->addConstructorValue(true) - ->register('mime.base64contentencoder') - ->asSharedInstanceOf('Swift_Mime_ContentEncoder_Base64ContentEncoder') + ->register('mime.base64contentencoder') + ->asSharedInstanceOf('Swift_Mime_ContentEncoder_Base64ContentEncoder') - ->register('mime.rfc2231encoder') - ->asNewInstanceOf('Swift_Encoder_Rfc2231Encoder') - ->withDependencies(['mime.charstream']); + ->register('mime.rfc2231encoder') + ->asNewInstanceOf('Swift_Encoder_Rfc2231Encoder') + ->withDependencies(['mime.charstream']) +; unset($swift_mime_types); diff --git a/htdocs/includes/swiftmailer/lib/dependency_maps/transport_deps.php b/htdocs/includes/swiftmailer/lib/dependency_maps/transport_deps.php index 40d65b176b9..34a63c78e51 100644 --- a/htdocs/includes/swiftmailer/lib/dependency_maps/transport_deps.php +++ b/htdocs/includes/swiftmailer/lib/dependency_maps/transport_deps.php @@ -1,96 +1,97 @@ register('transport.localdomain') - // As SERVER_NAME can come from the user in certain configurations, check that - // it does not contain forbidden characters (see RFC 952 and RFC 2181). Use - // preg_replace() instead of preg_match() to prevent DoS attacks with long host names. - ->asValue(!empty($_SERVER['SERVER_NAME']) && '' === preg_replace('/(?:^\[)?[a-zA-Z0-9-:\]_]+\.?/', '', $_SERVER['SERVER_NAME']) ? trim($_SERVER['SERVER_NAME'], '[]') : '127.0.0.1') + ->register('transport.localdomain') + // As SERVER_NAME can come from the user in certain configurations, check that + // it does not contain forbidden characters (see RFC 952 and RFC 2181). Use + // preg_replace() instead of preg_match() to prevent DoS attacks with long host names. + ->asValue(!empty($_SERVER['SERVER_NAME']) && '' === preg_replace('/(?:^\[)?[a-zA-Z0-9-:\]_]+\.?/', '', $_SERVER['SERVER_NAME']) ? trim($_SERVER['SERVER_NAME'], '[]') : '127.0.0.1') - ->register('transport.smtp') - ->asNewInstanceOf('Swift_Transport_EsmtpTransport') - ->withDependencies([ - 'transport.buffer', - 'transport.smtphandlers', - 'transport.eventdispatcher', - 'transport.localdomain', - 'address.idnaddressencoder', - ]) + ->register('transport.smtp') + ->asNewInstanceOf('Swift_Transport_EsmtpTransport') + ->withDependencies([ + 'transport.buffer', + 'transport.smtphandlers', + 'transport.eventdispatcher', + 'transport.localdomain', + 'address.idnaddressencoder', + ]) - ->register('transport.sendmail') - ->asNewInstanceOf('Swift_Transport_SendmailTransport') - ->withDependencies([ - 'transport.buffer', - 'transport.eventdispatcher', - 'transport.localdomain', - ]) + ->register('transport.sendmail') + ->asNewInstanceOf('Swift_Transport_SendmailTransport') + ->withDependencies([ + 'transport.buffer', + 'transport.eventdispatcher', + 'transport.localdomain', + ]) - ->register('transport.loadbalanced') - ->asNewInstanceOf('Swift_Transport_LoadBalancedTransport') + ->register('transport.loadbalanced') + ->asNewInstanceOf('Swift_Transport_LoadBalancedTransport') - ->register('transport.failover') - ->asNewInstanceOf('Swift_Transport_FailoverTransport') + ->register('transport.failover') + ->asNewInstanceOf('Swift_Transport_FailoverTransport') - ->register('transport.spool') - ->asNewInstanceOf('Swift_Transport_SpoolTransport') - ->withDependencies(['transport.eventdispatcher']) + ->register('transport.spool') + ->asNewInstanceOf('Swift_Transport_SpoolTransport') + ->withDependencies(['transport.eventdispatcher']) - ->register('transport.null') - ->asNewInstanceOf('Swift_Transport_NullTransport') - ->withDependencies(['transport.eventdispatcher']) + ->register('transport.null') + ->asNewInstanceOf('Swift_Transport_NullTransport') + ->withDependencies(['transport.eventdispatcher']) - ->register('transport.buffer') - ->asNewInstanceOf('Swift_Transport_StreamBuffer') - ->withDependencies(['transport.replacementfactory']) + ->register('transport.buffer') + ->asNewInstanceOf('Swift_Transport_StreamBuffer') + ->withDependencies(['transport.replacementfactory']) - ->register('transport.smtphandlers') - ->asArray() - ->withDependencies(['transport.authhandler']) + ->register('transport.smtphandlers') + ->asArray() + ->withDependencies(['transport.authhandler']) - ->register('transport.authhandler') - ->asNewInstanceOf('Swift_Transport_Esmtp_AuthHandler') - ->withDependencies(['transport.authhandlers']) + ->register('transport.authhandler') + ->asNewInstanceOf('Swift_Transport_Esmtp_AuthHandler') + ->withDependencies(['transport.authhandlers']) - ->register('transport.authhandlers') - ->asArray() - ->withDependencies([ - 'transport.crammd5auth', - 'transport.loginauth', - 'transport.plainauth', - 'transport.ntlmauth', - 'transport.xoauth2auth', - ]) + ->register('transport.authhandlers') + ->asArray() + ->withDependencies([ + 'transport.crammd5auth', + 'transport.loginauth', + 'transport.plainauth', + 'transport.ntlmauth', + 'transport.xoauth2auth', + ]) - ->register('transport.smtputf8handler') - ->asNewInstanceOf('Swift_Transport_Esmtp_SmtpUtf8Handler') + ->register('transport.smtputf8handler') + ->asNewInstanceOf('Swift_Transport_Esmtp_SmtpUtf8Handler') - ->register('transport.8bitmimehandler') - ->asNewInstanceOf('Swift_Transport_Esmtp_EightBitMimeHandler') - ->addConstructorValue('8BITMIME') + ->register('transport.8bitmimehandler') + ->asNewInstanceOf('Swift_Transport_Esmtp_EightBitMimeHandler') + ->addConstructorValue('8BITMIME') - ->register('transport.crammd5auth') - ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_CramMd5Authenticator') + ->register('transport.crammd5auth') + ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_CramMd5Authenticator') - ->register('transport.loginauth') - ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_LoginAuthenticator') + ->register('transport.loginauth') + ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_LoginAuthenticator') - ->register('transport.plainauth') - ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_PlainAuthenticator') + ->register('transport.plainauth') + ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_PlainAuthenticator') - ->register('transport.xoauth2auth') - ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_XOAuth2Authenticator') + ->register('transport.xoauth2auth') + ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_XOAuth2Authenticator') - ->register('transport.ntlmauth') - ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_NTLMAuthenticator') + ->register('transport.ntlmauth') + ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_NTLMAuthenticator') - ->register('transport.eventdispatcher') - ->asNewInstanceOf('Swift_Events_SimpleEventDispatcher') + ->register('transport.eventdispatcher') + ->asNewInstanceOf('Swift_Events_SimpleEventDispatcher') - ->register('transport.replacementfactory') - ->asSharedInstanceOf('Swift_StreamFilters_StringReplacementFilterFactory') + ->register('transport.replacementfactory') + ->asSharedInstanceOf('Swift_StreamFilters_StringReplacementFilterFactory') - ->register('address.idnaddressencoder') - ->asNewInstanceOf('Swift_AddressEncoder_IdnAddressEncoder') + ->register('address.idnaddressencoder') + ->asNewInstanceOf('Swift_AddressEncoder_IdnAddressEncoder') - ->register('address.utf8addressencoder') - ->asNewInstanceOf('Swift_AddressEncoder_Utf8AddressEncoder'); + ->register('address.utf8addressencoder') + ->asNewInstanceOf('Swift_AddressEncoder_Utf8AddressEncoder') +; diff --git a/htdocs/includes/swiftmailer/lib/mime_types.php b/htdocs/includes/swiftmailer/lib/mime_types.php index 0cb61d18832..72c6fd2afa6 100644 --- a/htdocs/includes/swiftmailer/lib/mime_types.php +++ b/htdocs/includes/swiftmailer/lib/mime_types.php @@ -18,990 +18,990 @@ // You may add or take away what you like (lowercase required) $swift_mime_types = [ - '3dml' => 'text/vnd.in3d.3dml', - '3ds' => 'image/x-3ds', - '3g2' => 'video/3gpp2', - '3gp' => 'video/3gpp', - '7z' => 'application/x-7z-compressed', - 'aab' => 'application/x-authorware-bin', - 'aac' => 'audio/x-aac', - 'aam' => 'application/x-authorware-map', - 'aas' => 'application/x-authorware-seg', - 'abw' => 'application/x-abiword', - 'ac' => 'application/pkix-attr-cert', - 'acc' => 'application/vnd.americandynamics.acc', - 'ace' => 'application/x-ace-compressed', - 'acu' => 'application/vnd.acucobol', - 'acutc' => 'application/vnd.acucorp', - 'adp' => 'audio/adpcm', - 'aep' => 'application/vnd.audiograph', - 'afm' => 'application/x-font-type1', - 'afp' => 'application/vnd.ibm.modcap', - 'ahead' => 'application/vnd.ahead.space', - 'ai' => 'application/postscript', - 'aif' => 'audio/x-aiff', - 'aifc' => 'audio/x-aiff', - 'aiff' => 'audio/x-aiff', - 'air' => 'application/vnd.adobe.air-application-installer-package+zip', - 'ait' => 'application/vnd.dvb.ait', - 'ami' => 'application/vnd.amiga.ami', - 'apk' => 'application/vnd.android.package-archive', - 'appcache' => 'text/cache-manifest', - 'apr' => 'application/vnd.lotus-approach', - 'aps' => 'application/postscript', - 'arc' => 'application/x-freearc', - 'asc' => 'application/pgp-signature', - 'asf' => 'video/x-ms-asf', - 'asm' => 'text/x-asm', - 'aso' => 'application/vnd.accpac.simply.aso', - 'asx' => 'video/x-ms-asf', - 'atc' => 'application/vnd.acucorp', - 'atom' => 'application/atom+xml', - 'atomcat' => 'application/atomcat+xml', - 'atomsvc' => 'application/atomsvc+xml', - 'atx' => 'application/vnd.antix.game-component', - 'au' => 'audio/basic', - 'avi' => 'video/x-msvideo', - 'aw' => 'application/applixware', - 'azf' => 'application/vnd.airzip.filesecure.azf', - 'azs' => 'application/vnd.airzip.filesecure.azs', - 'azw' => 'application/vnd.amazon.ebook', - 'bat' => 'application/x-msdownload', - 'bcpio' => 'application/x-bcpio', - 'bdf' => 'application/x-font-bdf', - 'bdm' => 'application/vnd.syncml.dm+wbxml', - 'bed' => 'application/vnd.realvnc.bed', - 'bh2' => 'application/vnd.fujitsu.oasysprs', - 'bin' => 'application/octet-stream', - 'blb' => 'application/x-blorb', - 'blorb' => 'application/x-blorb', - 'bmi' => 'application/vnd.bmi', - 'bmp' => 'image/bmp', - 'book' => 'application/vnd.framemaker', - 'box' => 'application/vnd.previewsystems.box', - 'boz' => 'application/x-bzip2', - 'bpk' => 'application/octet-stream', - 'btif' => 'image/prs.btif', - 'bz' => 'application/x-bzip', - 'bz2' => 'application/x-bzip2', - 'c' => 'text/x-c', - 'c11amc' => 'application/vnd.cluetrust.cartomobile-config', - 'c11amz' => 'application/vnd.cluetrust.cartomobile-config-pkg', - 'c4d' => 'application/vnd.clonk.c4group', - 'c4f' => 'application/vnd.clonk.c4group', - 'c4g' => 'application/vnd.clonk.c4group', - 'c4p' => 'application/vnd.clonk.c4group', - 'c4u' => 'application/vnd.clonk.c4group', - 'cab' => 'application/vnd.ms-cab-compressed', - 'caf' => 'audio/x-caf', - 'cap' => 'application/vnd.tcpdump.pcap', - 'car' => 'application/vnd.curl.car', - 'cat' => 'application/vnd.ms-pki.seccat', - 'cb7' => 'application/x-cbr', - 'cba' => 'application/x-cbr', - 'cbr' => 'application/x-cbr', - 'cbt' => 'application/x-cbr', - 'cbz' => 'application/x-cbr', - 'cc' => 'text/x-c', - 'cct' => 'application/x-director', - 'ccxml' => 'application/ccxml+xml', - 'cdbcmsg' => 'application/vnd.contact.cmsg', - 'cdf' => 'application/x-netcdf', - 'cdkey' => 'application/vnd.mediastation.cdkey', - 'cdmia' => 'application/cdmi-capability', - 'cdmic' => 'application/cdmi-container', - 'cdmid' => 'application/cdmi-domain', - 'cdmio' => 'application/cdmi-object', - 'cdmiq' => 'application/cdmi-queue', - 'cdx' => 'chemical/x-cdx', - 'cdxml' => 'application/vnd.chemdraw+xml', - 'cdy' => 'application/vnd.cinderella', - 'cer' => 'application/pkix-cert', - 'cfs' => 'application/x-cfs-compressed', - 'cgm' => 'image/cgm', - 'chat' => 'application/x-chat', - 'chm' => 'application/vnd.ms-htmlhelp', - 'chrt' => 'application/vnd.kde.kchart', - 'cif' => 'chemical/x-cif', - 'cii' => 'application/vnd.anser-web-certificate-issue-initiation', - 'cil' => 'application/vnd.ms-artgalry', - 'cla' => 'application/vnd.claymore', - 'class' => 'application/java-vm', - 'clkk' => 'application/vnd.crick.clicker.keyboard', - 'clkp' => 'application/vnd.crick.clicker.palette', - 'clkt' => 'application/vnd.crick.clicker.template', - 'clkw' => 'application/vnd.crick.clicker.wordbank', - 'clkx' => 'application/vnd.crick.clicker', - 'clp' => 'application/x-msclip', - 'cmc' => 'application/vnd.cosmocaller', - 'cmdf' => 'chemical/x-cmdf', - 'cml' => 'chemical/x-cml', - 'cmp' => 'application/vnd.yellowriver-custom-menu', - 'cmx' => 'image/x-cmx', - 'cod' => 'application/vnd.rim.cod', - 'com' => 'application/x-msdownload', - 'conf' => 'text/plain', - 'cpio' => 'application/x-cpio', - 'cpp' => 'text/x-c', - 'cpt' => 'application/mac-compactpro', - 'crd' => 'application/x-mscardfile', - 'crl' => 'application/pkix-crl', - 'crt' => 'application/x-x509-ca-cert', - 'csh' => 'application/x-csh', - 'csml' => 'chemical/x-csml', - 'csp' => 'application/vnd.commonspace', - 'css' => 'text/css', - 'cst' => 'application/x-director', - 'csv' => 'text/csv', - 'cu' => 'application/cu-seeme', - 'curl' => 'text/vnd.curl', - 'cww' => 'application/prs.cww', - 'cxt' => 'application/x-director', - 'cxx' => 'text/x-c', - 'dae' => 'model/vnd.collada+xml', - 'daf' => 'application/vnd.mobius.daf', - 'dart' => 'application/vnd.dart', - 'dataless' => 'application/vnd.fdsn.seed', - 'davmount' => 'application/davmount+xml', - 'dbk' => 'application/docbook+xml', - 'dcr' => 'application/x-director', - 'dcurl' => 'text/vnd.curl.dcurl', - 'dd2' => 'application/vnd.oma.dd2+xml', - 'ddd' => 'application/vnd.fujixerox.ddd', - 'deb' => 'application/x-debian-package', - 'def' => 'text/plain', - 'deploy' => 'application/octet-stream', - 'der' => 'application/x-x509-ca-cert', - 'dfac' => 'application/vnd.dreamfactory', - 'dgc' => 'application/x-dgc-compressed', - 'dic' => 'text/x-c', - 'dir' => 'application/x-director', - 'dis' => 'application/vnd.mobius.dis', - 'dist' => 'application/octet-stream', - 'distz' => 'application/octet-stream', - 'djv' => 'image/vnd.djvu', - 'djvu' => 'image/vnd.djvu', - 'dll' => 'application/x-msdownload', - 'dmg' => 'application/x-apple-diskimage', - 'dmp' => 'application/vnd.tcpdump.pcap', - 'dms' => 'application/octet-stream', - 'dna' => 'application/vnd.dna', - 'doc' => 'application/msword', - 'docm' => 'application/vnd.ms-word.document.macroenabled.12', - 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', - 'dot' => 'application/msword', - 'dotm' => 'application/vnd.ms-word.template.macroenabled.12', - 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', - 'dp' => 'application/vnd.osgi.dp', - 'dpg' => 'application/vnd.dpgraph', - 'dra' => 'audio/vnd.dra', - 'dsc' => 'text/prs.lines.tag', - 'dssc' => 'application/dssc+der', - 'dtb' => 'application/x-dtbook+xml', - 'dtd' => 'application/xml-dtd', - 'dts' => 'audio/vnd.dts', - 'dtshd' => 'audio/vnd.dts.hd', - 'dump' => 'application/octet-stream', - 'dvb' => 'video/vnd.dvb.file', - 'dvi' => 'application/x-dvi', - 'dwf' => 'model/vnd.dwf', - 'dwg' => 'image/vnd.dwg', - 'dxf' => 'image/vnd.dxf', - 'dxp' => 'application/vnd.spotfire.dxp', - 'dxr' => 'application/x-director', - 'ecelp4800' => 'audio/vnd.nuera.ecelp4800', - 'ecelp7470' => 'audio/vnd.nuera.ecelp7470', - 'ecelp9600' => 'audio/vnd.nuera.ecelp9600', - 'ecma' => 'application/ecmascript', - 'edm' => 'application/vnd.novadigm.edm', - 'edx' => 'application/vnd.novadigm.edx', - 'efif' => 'application/vnd.picsel', - 'ei6' => 'application/vnd.pg.osasli', - 'elc' => 'application/octet-stream', - 'emf' => 'application/x-msmetafile', - 'eml' => 'message/rfc822', - 'emma' => 'application/emma+xml', - 'emz' => 'application/x-msmetafile', - 'eol' => 'audio/vnd.digital-winds', - 'eot' => 'application/vnd.ms-fontobject', - 'eps' => 'application/postscript', - 'epub' => 'application/epub+zip', - 'es3' => 'application/vnd.eszigno3+xml', - 'esa' => 'application/vnd.osgi.subsystem', - 'esf' => 'application/vnd.epson.esf', - 'et3' => 'application/vnd.eszigno3+xml', - 'etx' => 'text/x-setext', - 'eva' => 'application/x-eva', - 'evy' => 'application/x-envoy', - 'exe' => 'application/x-msdownload', - 'exi' => 'application/exi', - 'ext' => 'application/vnd.novadigm.ext', - 'ez' => 'application/andrew-inset', - 'ez2' => 'application/vnd.ezpix-album', - 'ez3' => 'application/vnd.ezpix-package', - 'f' => 'text/x-fortran', - 'f4v' => 'video/x-f4v', - 'f77' => 'text/x-fortran', - 'f90' => 'text/x-fortran', - 'fbs' => 'image/vnd.fastbidsheet', - 'fcdt' => 'application/vnd.adobe.formscentral.fcdt', - 'fcs' => 'application/vnd.isac.fcs', - 'fdf' => 'application/vnd.fdf', - 'fe_launch' => 'application/vnd.denovo.fcselayout-link', - 'fg5' => 'application/vnd.fujitsu.oasysgp', - 'fgd' => 'application/x-director', - 'fh' => 'image/x-freehand', - 'fh4' => 'image/x-freehand', - 'fh5' => 'image/x-freehand', - 'fh7' => 'image/x-freehand', - 'fhc' => 'image/x-freehand', - 'fig' => 'application/x-xfig', - 'flac' => 'audio/x-flac', - 'fli' => 'video/x-fli', - 'flo' => 'application/vnd.micrografx.flo', - 'flv' => 'video/x-flv', - 'flw' => 'application/vnd.kde.kivio', - 'flx' => 'text/vnd.fmi.flexstor', - 'fly' => 'text/vnd.fly', - 'fm' => 'application/vnd.framemaker', - 'fnc' => 'application/vnd.frogans.fnc', - 'for' => 'text/x-fortran', - 'fpx' => 'image/vnd.fpx', - 'frame' => 'application/vnd.framemaker', - 'fsc' => 'application/vnd.fsc.weblaunch', - 'fst' => 'image/vnd.fst', - 'ftc' => 'application/vnd.fluxtime.clip', - 'fti' => 'application/vnd.anser-web-funds-transfer-initiation', - 'fvt' => 'video/vnd.fvt', - 'fxp' => 'application/vnd.adobe.fxp', - 'fxpl' => 'application/vnd.adobe.fxp', - 'fzs' => 'application/vnd.fuzzysheet', - 'g2w' => 'application/vnd.geoplan', - 'g3' => 'image/g3fax', - 'g3w' => 'application/vnd.geospace', - 'gac' => 'application/vnd.groove-account', - 'gam' => 'application/x-tads', - 'gbr' => 'application/rpki-ghostbusters', - 'gca' => 'application/x-gca-compressed', - 'gdl' => 'model/vnd.gdl', - 'geo' => 'application/vnd.dynageo', - 'gex' => 'application/vnd.geometry-explorer', - 'ggb' => 'application/vnd.geogebra.file', - 'ggt' => 'application/vnd.geogebra.tool', - 'ghf' => 'application/vnd.groove-help', - 'gif' => 'image/gif', - 'gim' => 'application/vnd.groove-identity-message', - 'gml' => 'application/gml+xml', - 'gmx' => 'application/vnd.gmx', - 'gnumeric' => 'application/x-gnumeric', - 'gph' => 'application/vnd.flographit', - 'gpx' => 'application/gpx+xml', - 'gqf' => 'application/vnd.grafeq', - 'gqs' => 'application/vnd.grafeq', - 'gram' => 'application/srgs', - 'gramps' => 'application/x-gramps-xml', - 'gre' => 'application/vnd.geometry-explorer', - 'grv' => 'application/vnd.groove-injector', - 'grxml' => 'application/srgs+xml', - 'gsf' => 'application/x-font-ghostscript', - 'gtar' => 'application/x-gtar', - 'gtm' => 'application/vnd.groove-tool-message', - 'gtw' => 'model/vnd.gtw', - 'gv' => 'text/vnd.graphviz', - 'gxf' => 'application/gxf', - 'gxt' => 'application/vnd.geonext', - 'gz' => 'application/x-gzip', - 'h' => 'text/x-c', - 'h261' => 'video/h261', - 'h263' => 'video/h263', - 'h264' => 'video/h264', - 'hal' => 'application/vnd.hal+xml', - 'hbci' => 'application/vnd.hbci', - 'hdf' => 'application/x-hdf', - 'hh' => 'text/x-c', - 'hlp' => 'application/winhlp', - 'hpgl' => 'application/vnd.hp-hpgl', - 'hpid' => 'application/vnd.hp-hpid', - 'hps' => 'application/vnd.hp-hps', - 'hqx' => 'application/mac-binhex40', - 'htke' => 'application/vnd.kenameaapp', - 'htm' => 'text/html', - 'html' => 'text/html', - 'hvd' => 'application/vnd.yamaha.hv-dic', - 'hvp' => 'application/vnd.yamaha.hv-voice', - 'hvs' => 'application/vnd.yamaha.hv-script', - 'i2g' => 'application/vnd.intergeo', - 'icc' => 'application/vnd.iccprofile', - 'ice' => 'x-conference/x-cooltalk', - 'icm' => 'application/vnd.iccprofile', - 'ico' => 'image/x-icon', - 'ics' => 'text/calendar', - 'ief' => 'image/ief', - 'ifb' => 'text/calendar', - 'ifm' => 'application/vnd.shana.informed.formdata', - 'iges' => 'model/iges', - 'igl' => 'application/vnd.igloader', - 'igm' => 'application/vnd.insors.igm', - 'igs' => 'model/iges', - 'igx' => 'application/vnd.micrografx.igx', - 'iif' => 'application/vnd.shana.informed.interchange', - 'imp' => 'application/vnd.accpac.simply.imp', - 'ims' => 'application/vnd.ms-ims', - 'in' => 'text/plain', - 'ink' => 'application/inkml+xml', - 'inkml' => 'application/inkml+xml', - 'install' => 'application/x-install-instructions', - 'iota' => 'application/vnd.astraea-software.iota', - 'ipfix' => 'application/ipfix', - 'ipk' => 'application/vnd.shana.informed.package', - 'irm' => 'application/vnd.ibm.rights-management', - 'irp' => 'application/vnd.irepository.package+xml', - 'iso' => 'application/x-iso9660-image', - 'itp' => 'application/vnd.shana.informed.formtemplate', - 'ivp' => 'application/vnd.immervision-ivp', - 'ivu' => 'application/vnd.immervision-ivu', - 'jad' => 'text/vnd.sun.j2me.app-descriptor', - 'jam' => 'application/vnd.jam', - 'jar' => 'application/java-archive', - 'java' => 'text/x-java-source', - 'jisp' => 'application/vnd.jisp', - 'jlt' => 'application/vnd.hp-jlyt', - 'jnlp' => 'application/x-java-jnlp-file', - 'joda' => 'application/vnd.joost.joda-archive', - 'jpe' => 'image/jpeg', - 'jpeg' => 'image/jpeg', - 'jpg' => 'image/jpeg', - 'jpgm' => 'video/jpm', - 'jpgv' => 'video/jpeg', - 'jpm' => 'video/jpm', - 'js' => 'application/javascript', - 'json' => 'application/json', - 'jsonml' => 'application/jsonml+json', - 'kar' => 'audio/midi', - 'karbon' => 'application/vnd.kde.karbon', - 'kfo' => 'application/vnd.kde.kformula', - 'kia' => 'application/vnd.kidspiration', - 'kml' => 'application/vnd.google-earth.kml+xml', - 'kmz' => 'application/vnd.google-earth.kmz', - 'kne' => 'application/vnd.kinar', - 'knp' => 'application/vnd.kinar', - 'kon' => 'application/vnd.kde.kontour', - 'kpr' => 'application/vnd.kde.kpresenter', - 'kpt' => 'application/vnd.kde.kpresenter', - 'kpxx' => 'application/vnd.ds-keypoint', - 'ksp' => 'application/vnd.kde.kspread', - 'ktr' => 'application/vnd.kahootz', - 'ktx' => 'image/ktx', - 'ktz' => 'application/vnd.kahootz', - 'kwd' => 'application/vnd.kde.kword', - 'kwt' => 'application/vnd.kde.kword', - 'lasxml' => 'application/vnd.las.las+xml', - 'latex' => 'application/x-latex', - 'lbd' => 'application/vnd.llamagraphics.life-balance.desktop', - 'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml', - 'les' => 'application/vnd.hhe.lesson-player', - 'lha' => 'application/x-lzh-compressed', - 'link66' => 'application/vnd.route66.link66+xml', - 'list' => 'text/plain', - 'list3820' => 'application/vnd.ibm.modcap', - 'listafp' => 'application/vnd.ibm.modcap', - 'lnk' => 'application/x-ms-shortcut', - 'log' => 'text/plain', - 'lostxml' => 'application/lost+xml', - 'lrf' => 'application/octet-stream', - 'lrm' => 'application/vnd.ms-lrm', - 'ltf' => 'application/vnd.frogans.ltf', - 'lvp' => 'audio/vnd.lucent.voice', - 'lwp' => 'application/vnd.lotus-wordpro', - 'lzh' => 'application/x-lzh-compressed', - 'm13' => 'application/x-msmediaview', - 'm14' => 'application/x-msmediaview', - 'm1v' => 'video/mpeg', - 'm21' => 'application/mp21', - 'm2a' => 'audio/mpeg', - 'm2v' => 'video/mpeg', - 'm3a' => 'audio/mpeg', - 'm3u' => 'audio/x-mpegurl', - 'm3u8' => 'application/vnd.apple.mpegurl', - 'm4a' => 'audio/mp4', - 'm4u' => 'video/vnd.mpegurl', - 'm4v' => 'video/x-m4v', - 'ma' => 'application/mathematica', - 'mads' => 'application/mads+xml', - 'mag' => 'application/vnd.ecowin.chart', - 'maker' => 'application/vnd.framemaker', - 'man' => 'text/troff', - 'mar' => 'application/octet-stream', - 'mathml' => 'application/mathml+xml', - 'mb' => 'application/mathematica', - 'mbk' => 'application/vnd.mobius.mbk', - 'mbox' => 'application/mbox', - 'mc1' => 'application/vnd.medcalcdata', - 'mcd' => 'application/vnd.mcd', - 'mcurl' => 'text/vnd.curl.mcurl', - 'mdb' => 'application/x-msaccess', - 'mdi' => 'image/vnd.ms-modi', - 'me' => 'text/troff', - 'mesh' => 'model/mesh', - 'meta4' => 'application/metalink4+xml', - 'metalink' => 'application/metalink+xml', - 'mets' => 'application/mets+xml', - 'mfm' => 'application/vnd.mfmp', - 'mft' => 'application/rpki-manifest', - 'mgp' => 'application/vnd.osgeo.mapguide.package', - 'mgz' => 'application/vnd.proteus.magazine', - 'mid' => 'audio/midi', - 'midi' => 'audio/midi', - 'mie' => 'application/x-mie', - 'mif' => 'application/vnd.mif', - 'mime' => 'message/rfc822', - 'mj2' => 'video/mj2', - 'mjp2' => 'video/mj2', - 'mk3d' => 'video/x-matroska', - 'mka' => 'audio/x-matroska', - 'mks' => 'video/x-matroska', - 'mkv' => 'video/x-matroska', - 'mlp' => 'application/vnd.dolby.mlp', - 'mmd' => 'application/vnd.chipnuts.karaoke-mmd', - 'mmf' => 'application/vnd.smaf', - 'mmr' => 'image/vnd.fujixerox.edmics-mmr', - 'mng' => 'video/x-mng', - 'mny' => 'application/x-msmoney', - 'mobi' => 'application/x-mobipocket-ebook', - 'mods' => 'application/mods+xml', - 'mov' => 'video/quicktime', - 'movie' => 'video/x-sgi-movie', - 'mp2' => 'audio/mpeg', - 'mp21' => 'application/mp21', - 'mp2a' => 'audio/mpeg', - 'mp3' => 'audio/mpeg', - 'mp4' => 'video/mp4', - 'mp4a' => 'audio/mp4', - 'mp4s' => 'application/mp4', - 'mp4v' => 'video/mp4', - 'mpc' => 'application/vnd.mophun.certificate', - 'mpe' => 'video/mpeg', - 'mpeg' => 'video/mpeg', - 'mpg' => 'video/mpeg', - 'mpg4' => 'video/mp4', - 'mpga' => 'audio/mpeg', - 'mpkg' => 'application/vnd.apple.installer+xml', - 'mpm' => 'application/vnd.blueice.multipass', - 'mpn' => 'application/vnd.mophun.application', - 'mpp' => 'application/vnd.ms-project', - 'mpt' => 'application/vnd.ms-project', - 'mpy' => 'application/vnd.ibm.minipay', - 'mqy' => 'application/vnd.mobius.mqy', - 'mrc' => 'application/marc', - 'mrcx' => 'application/marcxml+xml', - 'ms' => 'text/troff', - 'mscml' => 'application/mediaservercontrol+xml', - 'mseed' => 'application/vnd.fdsn.mseed', - 'mseq' => 'application/vnd.mseq', - 'msf' => 'application/vnd.epson.msf', - 'msh' => 'model/mesh', - 'msi' => 'application/x-msdownload', - 'msl' => 'application/vnd.mobius.msl', - 'msty' => 'application/vnd.muvee.style', - 'mts' => 'model/vnd.mts', - 'mus' => 'application/vnd.musician', - 'musicxml' => 'application/vnd.recordare.musicxml+xml', - 'mvb' => 'application/x-msmediaview', - 'mwf' => 'application/vnd.mfer', - 'mxf' => 'application/mxf', - 'mxl' => 'application/vnd.recordare.musicxml', - 'mxml' => 'application/xv+xml', - 'mxs' => 'application/vnd.triscape.mxs', - 'mxu' => 'video/vnd.mpegurl', - 'n-gage' => 'application/vnd.nokia.n-gage.symbian.install', - 'n3' => 'text/n3', - 'nb' => 'application/mathematica', - 'nbp' => 'application/vnd.wolfram.player', - 'nc' => 'application/x-netcdf', - 'ncx' => 'application/x-dtbncx+xml', - 'nfo' => 'text/x-nfo', - 'ngdat' => 'application/vnd.nokia.n-gage.data', - 'nitf' => 'application/vnd.nitf', - 'nlu' => 'application/vnd.neurolanguage.nlu', - 'nml' => 'application/vnd.enliven', - 'nnd' => 'application/vnd.noblenet-directory', - 'nns' => 'application/vnd.noblenet-sealer', - 'nnw' => 'application/vnd.noblenet-web', - 'npx' => 'image/vnd.net-fpx', - 'nsc' => 'application/x-conference', - 'nsf' => 'application/vnd.lotus-notes', - 'ntf' => 'application/vnd.nitf', - 'nzb' => 'application/x-nzb', - 'oa2' => 'application/vnd.fujitsu.oasys2', - 'oa3' => 'application/vnd.fujitsu.oasys3', - 'oas' => 'application/vnd.fujitsu.oasys', - 'obd' => 'application/x-msbinder', - 'obj' => 'application/x-tgif', - 'oda' => 'application/oda', - 'odb' => 'application/vnd.oasis.opendocument.database', - 'odc' => 'application/vnd.oasis.opendocument.chart', - 'odf' => 'application/vnd.oasis.opendocument.formula', - 'odft' => 'application/vnd.oasis.opendocument.formula-template', - 'odg' => 'application/vnd.oasis.opendocument.graphics', - 'odi' => 'application/vnd.oasis.opendocument.image', - 'odm' => 'application/vnd.oasis.opendocument.text-master', - 'odp' => 'application/vnd.oasis.opendocument.presentation', - 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', - 'odt' => 'application/vnd.oasis.opendocument.text', - 'oga' => 'audio/ogg', - 'ogg' => 'audio/ogg', - 'ogv' => 'video/ogg', - 'ogx' => 'application/ogg', - 'omdoc' => 'application/omdoc+xml', - 'onepkg' => 'application/onenote', - 'onetmp' => 'application/onenote', - 'onetoc' => 'application/onenote', - 'onetoc2' => 'application/onenote', - 'opf' => 'application/oebps-package+xml', - 'opml' => 'text/x-opml', - 'oprc' => 'application/vnd.palm', - 'org' => 'application/vnd.lotus-organizer', - 'osf' => 'application/vnd.yamaha.openscoreformat', - 'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml', - 'otc' => 'application/vnd.oasis.opendocument.chart-template', - 'otf' => 'application/x-font-otf', - 'otg' => 'application/vnd.oasis.opendocument.graphics-template', - 'oth' => 'application/vnd.oasis.opendocument.text-web', - 'oti' => 'application/vnd.oasis.opendocument.image-template', - 'otp' => 'application/vnd.oasis.opendocument.presentation-template', - 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template', - 'ott' => 'application/vnd.oasis.opendocument.text-template', - 'oxps' => 'application/oxps', - 'oxt' => 'application/vnd.openofficeorg.extension', - 'p' => 'text/x-pascal', - 'p10' => 'application/pkcs10', - 'p12' => 'application/x-pkcs12', - 'p7b' => 'application/x-pkcs7-certificates', - 'p7c' => 'application/pkcs7-mime', - 'p7m' => 'application/pkcs7-mime', - 'p7r' => 'application/x-pkcs7-certreqresp', - 'p7s' => 'application/pkcs7-signature', - 'p8' => 'application/pkcs8', - 'pas' => 'text/x-pascal', - 'paw' => 'application/vnd.pawaafile', - 'pbd' => 'application/vnd.powerbuilder6', - 'pbm' => 'image/x-portable-bitmap', - 'pcap' => 'application/vnd.tcpdump.pcap', - 'pcf' => 'application/x-font-pcf', - 'pcl' => 'application/vnd.hp-pcl', - 'pclxl' => 'application/vnd.hp-pclxl', - 'pct' => 'image/x-pict', - 'pcurl' => 'application/vnd.curl.pcurl', - 'pcx' => 'image/x-pcx', - 'pdb' => 'application/vnd.palm', - 'pdf' => 'application/pdf', - 'pfa' => 'application/x-font-type1', - 'pfb' => 'application/x-font-type1', - 'pfm' => 'application/x-font-type1', - 'pfr' => 'application/font-tdpfr', - 'pfx' => 'application/x-pkcs12', - 'pgm' => 'image/x-portable-graymap', - 'pgn' => 'application/x-chess-pgn', - 'pgp' => 'application/pgp-encrypted', - 'php' => 'application/x-php', - 'php3' => 'application/x-php', - 'php4' => 'application/x-php', - 'php5' => 'application/x-php', - 'pic' => 'image/x-pict', - 'pkg' => 'application/octet-stream', - 'pki' => 'application/pkixcmp', - 'pkipath' => 'application/pkix-pkipath', - 'plb' => 'application/vnd.3gpp.pic-bw-large', - 'plc' => 'application/vnd.mobius.plc', - 'plf' => 'application/vnd.pocketlearn', - 'pls' => 'application/pls+xml', - 'pml' => 'application/vnd.ctc-posml', - 'png' => 'image/png', - 'pnm' => 'image/x-portable-anymap', - 'portpkg' => 'application/vnd.macports.portpkg', - 'pot' => 'application/vnd.ms-powerpoint', - 'potm' => 'application/vnd.ms-powerpoint.template.macroenabled.12', - 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template', - 'ppam' => 'application/vnd.ms-powerpoint.addin.macroenabled.12', - 'ppd' => 'application/vnd.cups-ppd', - 'ppm' => 'image/x-portable-pixmap', - 'pps' => 'application/vnd.ms-powerpoint', - 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroenabled.12', - 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', - 'ppt' => 'application/vnd.ms-powerpoint', - 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroenabled.12', - 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', - 'pqa' => 'application/vnd.palm', - 'prc' => 'application/x-mobipocket-ebook', - 'pre' => 'application/vnd.lotus-freelance', - 'prf' => 'application/pics-rules', - 'ps' => 'application/postscript', - 'psb' => 'application/vnd.3gpp.pic-bw-small', - 'psd' => 'image/vnd.adobe.photoshop', - 'psf' => 'application/x-font-linux-psf', - 'pskcxml' => 'application/pskc+xml', - 'ptid' => 'application/vnd.pvi.ptid1', - 'pub' => 'application/x-mspublisher', - 'pvb' => 'application/vnd.3gpp.pic-bw-var', - 'pwn' => 'application/vnd.3m.post-it-notes', - 'pya' => 'audio/vnd.ms-playready.media.pya', - 'pyv' => 'video/vnd.ms-playready.media.pyv', - 'qam' => 'application/vnd.epson.quickanime', - 'qbo' => 'application/vnd.intu.qbo', - 'qfx' => 'application/vnd.intu.qfx', - 'qps' => 'application/vnd.publishare-delta-tree', - 'qt' => 'video/quicktime', - 'qwd' => 'application/vnd.quark.quarkxpress', - 'qwt' => 'application/vnd.quark.quarkxpress', - 'qxb' => 'application/vnd.quark.quarkxpress', - 'qxd' => 'application/vnd.quark.quarkxpress', - 'qxl' => 'application/vnd.quark.quarkxpress', - 'qxt' => 'application/vnd.quark.quarkxpress', - 'ra' => 'audio/x-pn-realaudio', - 'ram' => 'audio/x-pn-realaudio', - 'rar' => 'application/x-rar-compressed', - 'ras' => 'image/x-cmu-raster', - 'rcprofile' => 'application/vnd.ipunplugged.rcprofile', - 'rdf' => 'application/rdf+xml', - 'rdz' => 'application/vnd.data-vision.rdz', - 'rep' => 'application/vnd.businessobjects', - 'res' => 'application/x-dtbresource+xml', - 'rgb' => 'image/x-rgb', - 'rif' => 'application/reginfo+xml', - 'rip' => 'audio/vnd.rip', - 'ris' => 'application/x-research-info-systems', - 'rl' => 'application/resource-lists+xml', - 'rlc' => 'image/vnd.fujixerox.edmics-rlc', - 'rld' => 'application/resource-lists-diff+xml', - 'rm' => 'application/vnd.rn-realmedia', - 'rmi' => 'audio/midi', - 'rmp' => 'audio/x-pn-realaudio-plugin', - 'rms' => 'application/vnd.jcp.javame.midlet-rms', - 'rmvb' => 'application/vnd.rn-realmedia-vbr', - 'rnc' => 'application/relax-ng-compact-syntax', - 'roa' => 'application/rpki-roa', - 'roff' => 'text/troff', - 'rp9' => 'application/vnd.cloanto.rp9', - 'rpss' => 'application/vnd.nokia.radio-presets', - 'rpst' => 'application/vnd.nokia.radio-preset', - 'rq' => 'application/sparql-query', - 'rs' => 'application/rls-services+xml', - 'rsd' => 'application/rsd+xml', - 'rss' => 'application/rss+xml', - 'rtf' => 'application/rtf', - 'rtx' => 'text/richtext', - 's' => 'text/x-asm', - 's3m' => 'audio/s3m', - 'saf' => 'application/vnd.yamaha.smaf-audio', - 'sbml' => 'application/sbml+xml', - 'sc' => 'application/vnd.ibm.secure-container', - 'scd' => 'application/x-msschedule', - 'scm' => 'application/vnd.lotus-screencam', - 'scq' => 'application/scvp-cv-request', - 'scs' => 'application/scvp-cv-response', - 'scurl' => 'text/vnd.curl.scurl', - 'sda' => 'application/vnd.stardivision.draw', - 'sdc' => 'application/vnd.stardivision.calc', - 'sdd' => 'application/vnd.stardivision.impress', - 'sdkd' => 'application/vnd.solent.sdkm+xml', - 'sdkm' => 'application/vnd.solent.sdkm+xml', - 'sdp' => 'application/sdp', - 'sdw' => 'application/vnd.stardivision.writer', - 'see' => 'application/vnd.seemail', - 'seed' => 'application/vnd.fdsn.seed', - 'sema' => 'application/vnd.sema', - 'semd' => 'application/vnd.semd', - 'semf' => 'application/vnd.semf', - 'ser' => 'application/java-serialized-object', - 'setpay' => 'application/set-payment-initiation', - 'setreg' => 'application/set-registration-initiation', - 'sfd-hdstx' => 'application/vnd.hydrostatix.sof-data', - 'sfs' => 'application/vnd.spotfire.sfs', - 'sfv' => 'text/x-sfv', - 'sgi' => 'image/sgi', - 'sgl' => 'application/vnd.stardivision.writer-global', - 'sgm' => 'text/sgml', - 'sgml' => 'text/sgml', - 'sh' => 'application/x-sh', - 'shar' => 'application/x-shar', - 'shf' => 'application/shf+xml', - 'sid' => 'image/x-mrsid-image', - 'sig' => 'application/pgp-signature', - 'sil' => 'audio/silk', - 'silo' => 'model/mesh', - 'sis' => 'application/vnd.symbian.install', - 'sisx' => 'application/vnd.symbian.install', - 'sit' => 'application/x-stuffit', - 'sitx' => 'application/x-stuffitx', - 'skd' => 'application/vnd.koan', - 'skm' => 'application/vnd.koan', - 'skp' => 'application/vnd.koan', - 'skt' => 'application/vnd.koan', - 'sldm' => 'application/vnd.ms-powerpoint.slide.macroenabled.12', - 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide', - 'slt' => 'application/vnd.epson.salt', - 'sm' => 'application/vnd.stepmania.stepchart', - 'smf' => 'application/vnd.stardivision.math', - 'smi' => 'application/smil+xml', - 'smil' => 'application/smil+xml', - 'smv' => 'video/x-smv', - 'smzip' => 'application/vnd.stepmania.package', - 'snd' => 'audio/basic', - 'snf' => 'application/x-font-snf', - 'so' => 'application/octet-stream', - 'spc' => 'application/x-pkcs7-certificates', - 'spf' => 'application/vnd.yamaha.smaf-phrase', - 'spl' => 'application/x-futuresplash', - 'spot' => 'text/vnd.in3d.spot', - 'spp' => 'application/scvp-vp-response', - 'spq' => 'application/scvp-vp-request', - 'spx' => 'audio/ogg', - 'sql' => 'application/x-sql', - 'src' => 'application/x-wais-source', - 'srt' => 'application/x-subrip', - 'sru' => 'application/sru+xml', - 'srx' => 'application/sparql-results+xml', - 'ssdl' => 'application/ssdl+xml', - 'sse' => 'application/vnd.kodak-descriptor', - 'ssf' => 'application/vnd.epson.ssf', - 'ssml' => 'application/ssml+xml', - 'st' => 'application/vnd.sailingtracker.track', - 'stc' => 'application/vnd.sun.xml.calc.template', - 'std' => 'application/vnd.sun.xml.draw.template', - 'stf' => 'application/vnd.wt.stf', - 'sti' => 'application/vnd.sun.xml.impress.template', - 'stk' => 'application/hyperstudio', - 'stl' => 'application/vnd.ms-pki.stl', - 'str' => 'application/vnd.pg.format', - 'stw' => 'application/vnd.sun.xml.writer.template', - 'sub' => 'text/vnd.dvb.subtitle', - 'sus' => 'application/vnd.sus-calendar', - 'susp' => 'application/vnd.sus-calendar', - 'sv4cpio' => 'application/x-sv4cpio', - 'sv4crc' => 'application/x-sv4crc', - 'svc' => 'application/vnd.dvb.service', - 'svd' => 'application/vnd.svd', - 'svg' => 'image/svg+xml', - 'svgz' => 'image/svg+xml', - 'swa' => 'application/x-director', - 'swf' => 'application/x-shockwave-flash', - 'swi' => 'application/vnd.aristanetworks.swi', - 'sxc' => 'application/vnd.sun.xml.calc', - 'sxd' => 'application/vnd.sun.xml.draw', - 'sxg' => 'application/vnd.sun.xml.writer.global', - 'sxi' => 'application/vnd.sun.xml.impress', - 'sxm' => 'application/vnd.sun.xml.math', - 'sxw' => 'application/vnd.sun.xml.writer', - 't' => 'text/troff', - 't3' => 'application/x-t3vm-image', - 'taglet' => 'application/vnd.mynfc', - 'tao' => 'application/vnd.tao.intent-module-archive', - 'tar' => 'application/x-tar', - 'tcap' => 'application/vnd.3gpp2.tcap', - 'tcl' => 'application/x-tcl', - 'teacher' => 'application/vnd.smart.teacher', - 'tei' => 'application/tei+xml', - 'teicorpus' => 'application/tei+xml', - 'tex' => 'application/x-tex', - 'texi' => 'application/x-texinfo', - 'texinfo' => 'application/x-texinfo', - 'text' => 'text/plain', - 'tfi' => 'application/thraud+xml', - 'tfm' => 'application/x-tex-tfm', - 'tga' => 'image/x-tga', - 'thmx' => 'application/vnd.ms-officetheme', - 'tif' => 'image/tiff', - 'tiff' => 'image/tiff', - 'tmo' => 'application/vnd.tmobile-livetv', - 'torrent' => 'application/x-bittorrent', - 'tpl' => 'application/vnd.groove-tool-template', - 'tpt' => 'application/vnd.trid.tpt', - 'tr' => 'text/troff', - 'tra' => 'application/vnd.trueapp', - 'trm' => 'application/x-msterminal', - 'tsd' => 'application/timestamped-data', - 'tsv' => 'text/tab-separated-values', - 'ttc' => 'application/x-font-ttf', - 'ttf' => 'application/x-font-ttf', - 'ttl' => 'text/turtle', - 'twd' => 'application/vnd.simtech-mindmapper', - 'twds' => 'application/vnd.simtech-mindmapper', - 'txd' => 'application/vnd.genomatix.tuxedo', - 'txf' => 'application/vnd.mobius.txf', - 'txt' => 'text/plain', - 'u32' => 'application/x-authorware-bin', - 'udeb' => 'application/x-debian-package', - 'ufd' => 'application/vnd.ufdl', - 'ufdl' => 'application/vnd.ufdl', - 'ulx' => 'application/x-glulx', - 'umj' => 'application/vnd.umajin', - 'unityweb' => 'application/vnd.unity', - 'uoml' => 'application/vnd.uoml+xml', - 'uri' => 'text/uri-list', - 'uris' => 'text/uri-list', - 'urls' => 'text/uri-list', - 'ustar' => 'application/x-ustar', - 'utz' => 'application/vnd.uiq.theme', - 'uu' => 'text/x-uuencode', - 'uva' => 'audio/vnd.dece.audio', - 'uvd' => 'application/vnd.dece.data', - 'uvf' => 'application/vnd.dece.data', - 'uvg' => 'image/vnd.dece.graphic', - 'uvh' => 'video/vnd.dece.hd', - 'uvi' => 'image/vnd.dece.graphic', - 'uvm' => 'video/vnd.dece.mobile', - 'uvp' => 'video/vnd.dece.pd', - 'uvs' => 'video/vnd.dece.sd', - 'uvt' => 'application/vnd.dece.ttml+xml', - 'uvu' => 'video/vnd.uvvu.mp4', - 'uvv' => 'video/vnd.dece.video', - 'uvva' => 'audio/vnd.dece.audio', - 'uvvd' => 'application/vnd.dece.data', - 'uvvf' => 'application/vnd.dece.data', - 'uvvg' => 'image/vnd.dece.graphic', - 'uvvh' => 'video/vnd.dece.hd', - 'uvvi' => 'image/vnd.dece.graphic', - 'uvvm' => 'video/vnd.dece.mobile', - 'uvvp' => 'video/vnd.dece.pd', - 'uvvs' => 'video/vnd.dece.sd', - 'uvvt' => 'application/vnd.dece.ttml+xml', - 'uvvu' => 'video/vnd.uvvu.mp4', - 'uvvv' => 'video/vnd.dece.video', - 'uvvx' => 'application/vnd.dece.unspecified', - 'uvvz' => 'application/vnd.dece.zip', - 'uvx' => 'application/vnd.dece.unspecified', - 'uvz' => 'application/vnd.dece.zip', - 'vcard' => 'text/vcard', - 'vcd' => 'application/x-cdlink', - 'vcf' => 'text/x-vcard', - 'vcg' => 'application/vnd.groove-vcard', - 'vcs' => 'text/x-vcalendar', - 'vcx' => 'application/vnd.vcx', - 'vis' => 'application/vnd.visionary', - 'viv' => 'video/vnd.vivo', - 'vob' => 'video/x-ms-vob', - 'vor' => 'application/vnd.stardivision.writer', - 'vox' => 'application/x-authorware-bin', - 'vrml' => 'model/vrml', - 'vsd' => 'application/vnd.visio', - 'vsf' => 'application/vnd.vsf', - 'vss' => 'application/vnd.visio', - 'vst' => 'application/vnd.visio', - 'vsw' => 'application/vnd.visio', - 'vtu' => 'model/vnd.vtu', - 'vxml' => 'application/voicexml+xml', - 'w3d' => 'application/x-director', - 'wad' => 'application/x-doom', - 'wav' => 'audio/x-wav', - 'wax' => 'audio/x-ms-wax', - 'wbmp' => 'image/vnd.wap.wbmp', - 'wbs' => 'application/vnd.criticaltools.wbs+xml', - 'wbxml' => 'application/vnd.wap.wbxml', - 'wcm' => 'application/vnd.ms-works', - 'wdb' => 'application/vnd.ms-works', - 'wdp' => 'image/vnd.ms-photo', - 'weba' => 'audio/webm', - 'webm' => 'video/webm', - 'webp' => 'image/webp', - 'wg' => 'application/vnd.pmi.widget', - 'wgt' => 'application/widget', - 'wks' => 'application/vnd.ms-works', - 'wm' => 'video/x-ms-wm', - 'wma' => 'audio/x-ms-wma', - 'wmd' => 'application/x-ms-wmd', - 'wmf' => 'application/x-msmetafile', - 'wml' => 'text/vnd.wap.wml', - 'wmlc' => 'application/vnd.wap.wmlc', - 'wmls' => 'text/vnd.wap.wmlscript', - 'wmlsc' => 'application/vnd.wap.wmlscriptc', - 'wmv' => 'video/x-ms-wmv', - 'wmx' => 'video/x-ms-wmx', - 'wmz' => 'application/x-msmetafile', - 'woff' => 'application/font-woff', - 'wpd' => 'application/vnd.wordperfect', - 'wpl' => 'application/vnd.ms-wpl', - 'wps' => 'application/vnd.ms-works', - 'wqd' => 'application/vnd.wqd', - 'wri' => 'application/x-mswrite', - 'wrl' => 'model/vrml', - 'wsdl' => 'application/wsdl+xml', - 'wspolicy' => 'application/wspolicy+xml', - 'wtb' => 'application/vnd.webturbo', - 'wvx' => 'video/x-ms-wvx', - 'x32' => 'application/x-authorware-bin', - 'x3d' => 'model/x3d+xml', - 'x3db' => 'model/x3d+binary', - 'x3dbz' => 'model/x3d+binary', - 'x3dv' => 'model/x3d+vrml', - 'x3dvz' => 'model/x3d+vrml', - 'x3dz' => 'model/x3d+xml', - 'xaml' => 'application/xaml+xml', - 'xap' => 'application/x-silverlight-app', - 'xar' => 'application/vnd.xara', - 'xbap' => 'application/x-ms-xbap', - 'xbd' => 'application/vnd.fujixerox.docuworks.binder', - 'xbm' => 'image/x-xbitmap', - 'xdf' => 'application/xcap-diff+xml', - 'xdm' => 'application/vnd.syncml.dm+xml', - 'xdp' => 'application/vnd.adobe.xdp+xml', - 'xdssc' => 'application/dssc+xml', - 'xdw' => 'application/vnd.fujixerox.docuworks', - 'xenc' => 'application/xenc+xml', - 'xer' => 'application/patch-ops-error+xml', - 'xfdf' => 'application/vnd.adobe.xfdf', - 'xfdl' => 'application/vnd.xfdl', - 'xht' => 'application/xhtml+xml', - 'xhtml' => 'application/xhtml+xml', - 'xhvml' => 'application/xv+xml', - 'xif' => 'image/vnd.xiff', - 'xla' => 'application/vnd.ms-excel', - 'xlam' => 'application/vnd.ms-excel.addin.macroenabled.12', - 'xlc' => 'application/vnd.ms-excel', - 'xlf' => 'application/x-xliff+xml', - 'xlm' => 'application/vnd.ms-excel', - 'xls' => 'application/vnd.ms-excel', - 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroenabled.12', - 'xlsm' => 'application/vnd.ms-excel.sheet.macroenabled.12', - 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', - 'xlt' => 'application/vnd.ms-excel', - 'xltm' => 'application/vnd.ms-excel.template.macroenabled.12', - 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', - 'xlw' => 'application/vnd.ms-excel', - 'xm' => 'audio/xm', - 'xml' => 'application/xml', - 'xo' => 'application/vnd.olpc-sugar', - 'xop' => 'application/xop+xml', - 'xpi' => 'application/x-xpinstall', - 'xpl' => 'application/xproc+xml', - 'xpm' => 'image/x-xpixmap', - 'xpr' => 'application/vnd.is-xpr', - 'xps' => 'application/vnd.ms-xpsdocument', - 'xpw' => 'application/vnd.intercon.formnet', - 'xpx' => 'application/vnd.intercon.formnet', - 'xsl' => 'application/xml', - 'xslt' => 'application/xslt+xml', - 'xsm' => 'application/vnd.syncml+xml', - 'xspf' => 'application/xspf+xml', - 'xul' => 'application/vnd.mozilla.xul+xml', - 'xvm' => 'application/xv+xml', - 'xvml' => 'application/xv+xml', - 'xwd' => 'image/x-xwindowdump', - 'xyz' => 'chemical/x-xyz', - 'xz' => 'application/x-xz', - 'yang' => 'application/yang', - 'yin' => 'application/yin+xml', - 'z1' => 'application/x-zmachine', - 'z2' => 'application/x-zmachine', - 'z3' => 'application/x-zmachine', - 'z4' => 'application/x-zmachine', - 'z5' => 'application/x-zmachine', - 'z6' => 'application/x-zmachine', - 'z7' => 'application/x-zmachine', - 'z8' => 'application/x-zmachine', - 'zaz' => 'application/vnd.zzazz.deck+xml', - 'zip' => 'application/zip', - 'zir' => 'application/vnd.zul', - 'zirz' => 'application/vnd.zul', - 'zmm' => 'application/vnd.handheld-entertainment+xml', - '123' => 'application/vnd.lotus-1-2-3', + '3dml' => 'text/vnd.in3d.3dml', + '3ds' => 'image/x-3ds', + '3g2' => 'video/3gpp2', + '3gp' => 'video/3gpp', + '7z' => 'application/x-7z-compressed', + 'aab' => 'application/x-authorware-bin', + 'aac' => 'audio/x-aac', + 'aam' => 'application/x-authorware-map', + 'aas' => 'application/x-authorware-seg', + 'abw' => 'application/x-abiword', + 'ac' => 'application/pkix-attr-cert', + 'acc' => 'application/vnd.americandynamics.acc', + 'ace' => 'application/x-ace-compressed', + 'acu' => 'application/vnd.acucobol', + 'acutc' => 'application/vnd.acucorp', + 'adp' => 'audio/adpcm', + 'aep' => 'application/vnd.audiograph', + 'afm' => 'application/x-font-type1', + 'afp' => 'application/vnd.ibm.modcap', + 'ahead' => 'application/vnd.ahead.space', + 'ai' => 'application/postscript', + 'aif' => 'audio/x-aiff', + 'aifc' => 'audio/x-aiff', + 'aiff' => 'audio/x-aiff', + 'air' => 'application/vnd.adobe.air-application-installer-package+zip', + 'ait' => 'application/vnd.dvb.ait', + 'ami' => 'application/vnd.amiga.ami', + 'apk' => 'application/vnd.android.package-archive', + 'appcache' => 'text/cache-manifest', + 'apr' => 'application/vnd.lotus-approach', + 'aps' => 'application/postscript', + 'arc' => 'application/x-freearc', + 'asc' => 'application/pgp-signature', + 'asf' => 'video/x-ms-asf', + 'asm' => 'text/x-asm', + 'aso' => 'application/vnd.accpac.simply.aso', + 'asx' => 'video/x-ms-asf', + 'atc' => 'application/vnd.acucorp', + 'atom' => 'application/atom+xml', + 'atomcat' => 'application/atomcat+xml', + 'atomsvc' => 'application/atomsvc+xml', + 'atx' => 'application/vnd.antix.game-component', + 'au' => 'audio/basic', + 'avi' => 'video/x-msvideo', + 'aw' => 'application/applixware', + 'azf' => 'application/vnd.airzip.filesecure.azf', + 'azs' => 'application/vnd.airzip.filesecure.azs', + 'azw' => 'application/vnd.amazon.ebook', + 'bat' => 'application/x-msdownload', + 'bcpio' => 'application/x-bcpio', + 'bdf' => 'application/x-font-bdf', + 'bdm' => 'application/vnd.syncml.dm+wbxml', + 'bed' => 'application/vnd.realvnc.bed', + 'bh2' => 'application/vnd.fujitsu.oasysprs', + 'bin' => 'application/octet-stream', + 'blb' => 'application/x-blorb', + 'blorb' => 'application/x-blorb', + 'bmi' => 'application/vnd.bmi', + 'bmp' => 'image/bmp', + 'book' => 'application/vnd.framemaker', + 'box' => 'application/vnd.previewsystems.box', + 'boz' => 'application/x-bzip2', + 'bpk' => 'application/octet-stream', + 'btif' => 'image/prs.btif', + 'bz' => 'application/x-bzip', + 'bz2' => 'application/x-bzip2', + 'c' => 'text/x-c', + 'c11amc' => 'application/vnd.cluetrust.cartomobile-config', + 'c11amz' => 'application/vnd.cluetrust.cartomobile-config-pkg', + 'c4d' => 'application/vnd.clonk.c4group', + 'c4f' => 'application/vnd.clonk.c4group', + 'c4g' => 'application/vnd.clonk.c4group', + 'c4p' => 'application/vnd.clonk.c4group', + 'c4u' => 'application/vnd.clonk.c4group', + 'cab' => 'application/vnd.ms-cab-compressed', + 'caf' => 'audio/x-caf', + 'cap' => 'application/vnd.tcpdump.pcap', + 'car' => 'application/vnd.curl.car', + 'cat' => 'application/vnd.ms-pki.seccat', + 'cb7' => 'application/x-cbr', + 'cba' => 'application/x-cbr', + 'cbr' => 'application/x-cbr', + 'cbt' => 'application/x-cbr', + 'cbz' => 'application/x-cbr', + 'cc' => 'text/x-c', + 'cct' => 'application/x-director', + 'ccxml' => 'application/ccxml+xml', + 'cdbcmsg' => 'application/vnd.contact.cmsg', + 'cdf' => 'application/x-netcdf', + 'cdkey' => 'application/vnd.mediastation.cdkey', + 'cdmia' => 'application/cdmi-capability', + 'cdmic' => 'application/cdmi-container', + 'cdmid' => 'application/cdmi-domain', + 'cdmio' => 'application/cdmi-object', + 'cdmiq' => 'application/cdmi-queue', + 'cdx' => 'chemical/x-cdx', + 'cdxml' => 'application/vnd.chemdraw+xml', + 'cdy' => 'application/vnd.cinderella', + 'cer' => 'application/pkix-cert', + 'cfs' => 'application/x-cfs-compressed', + 'cgm' => 'image/cgm', + 'chat' => 'application/x-chat', + 'chm' => 'application/vnd.ms-htmlhelp', + 'chrt' => 'application/vnd.kde.kchart', + 'cif' => 'chemical/x-cif', + 'cii' => 'application/vnd.anser-web-certificate-issue-initiation', + 'cil' => 'application/vnd.ms-artgalry', + 'cla' => 'application/vnd.claymore', + 'class' => 'application/java-vm', + 'clkk' => 'application/vnd.crick.clicker.keyboard', + 'clkp' => 'application/vnd.crick.clicker.palette', + 'clkt' => 'application/vnd.crick.clicker.template', + 'clkw' => 'application/vnd.crick.clicker.wordbank', + 'clkx' => 'application/vnd.crick.clicker', + 'clp' => 'application/x-msclip', + 'cmc' => 'application/vnd.cosmocaller', + 'cmdf' => 'chemical/x-cmdf', + 'cml' => 'chemical/x-cml', + 'cmp' => 'application/vnd.yellowriver-custom-menu', + 'cmx' => 'image/x-cmx', + 'cod' => 'application/vnd.rim.cod', + 'com' => 'application/x-msdownload', + 'conf' => 'text/plain', + 'cpio' => 'application/x-cpio', + 'cpp' => 'text/x-c', + 'cpt' => 'application/mac-compactpro', + 'crd' => 'application/x-mscardfile', + 'crl' => 'application/pkix-crl', + 'crt' => 'application/x-x509-ca-cert', + 'csh' => 'application/x-csh', + 'csml' => 'chemical/x-csml', + 'csp' => 'application/vnd.commonspace', + 'css' => 'text/css', + 'cst' => 'application/x-director', + 'csv' => 'text/csv', + 'cu' => 'application/cu-seeme', + 'curl' => 'text/vnd.curl', + 'cww' => 'application/prs.cww', + 'cxt' => 'application/x-director', + 'cxx' => 'text/x-c', + 'dae' => 'model/vnd.collada+xml', + 'daf' => 'application/vnd.mobius.daf', + 'dart' => 'application/vnd.dart', + 'dataless' => 'application/vnd.fdsn.seed', + 'davmount' => 'application/davmount+xml', + 'dbk' => 'application/docbook+xml', + 'dcr' => 'application/x-director', + 'dcurl' => 'text/vnd.curl.dcurl', + 'dd2' => 'application/vnd.oma.dd2+xml', + 'ddd' => 'application/vnd.fujixerox.ddd', + 'deb' => 'application/x-debian-package', + 'def' => 'text/plain', + 'deploy' => 'application/octet-stream', + 'der' => 'application/x-x509-ca-cert', + 'dfac' => 'application/vnd.dreamfactory', + 'dgc' => 'application/x-dgc-compressed', + 'dic' => 'text/x-c', + 'dir' => 'application/x-director', + 'dis' => 'application/vnd.mobius.dis', + 'dist' => 'application/octet-stream', + 'distz' => 'application/octet-stream', + 'djv' => 'image/vnd.djvu', + 'djvu' => 'image/vnd.djvu', + 'dll' => 'application/x-msdownload', + 'dmg' => 'application/x-apple-diskimage', + 'dmp' => 'application/vnd.tcpdump.pcap', + 'dms' => 'application/octet-stream', + 'dna' => 'application/vnd.dna', + 'doc' => 'application/msword', + 'docm' => 'application/vnd.ms-word.document.macroenabled.12', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'dot' => 'application/msword', + 'dotm' => 'application/vnd.ms-word.template.macroenabled.12', + 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', + 'dp' => 'application/vnd.osgi.dp', + 'dpg' => 'application/vnd.dpgraph', + 'dra' => 'audio/vnd.dra', + 'dsc' => 'text/prs.lines.tag', + 'dssc' => 'application/dssc+der', + 'dtb' => 'application/x-dtbook+xml', + 'dtd' => 'application/xml-dtd', + 'dts' => 'audio/vnd.dts', + 'dtshd' => 'audio/vnd.dts.hd', + 'dump' => 'application/octet-stream', + 'dvb' => 'video/vnd.dvb.file', + 'dvi' => 'application/x-dvi', + 'dwf' => 'model/vnd.dwf', + 'dwg' => 'image/vnd.dwg', + 'dxf' => 'image/vnd.dxf', + 'dxp' => 'application/vnd.spotfire.dxp', + 'dxr' => 'application/x-director', + 'ecelp4800' => 'audio/vnd.nuera.ecelp4800', + 'ecelp7470' => 'audio/vnd.nuera.ecelp7470', + 'ecelp9600' => 'audio/vnd.nuera.ecelp9600', + 'ecma' => 'application/ecmascript', + 'edm' => 'application/vnd.novadigm.edm', + 'edx' => 'application/vnd.novadigm.edx', + 'efif' => 'application/vnd.picsel', + 'ei6' => 'application/vnd.pg.osasli', + 'elc' => 'application/octet-stream', + 'emf' => 'application/x-msmetafile', + 'eml' => 'message/rfc822', + 'emma' => 'application/emma+xml', + 'emz' => 'application/x-msmetafile', + 'eol' => 'audio/vnd.digital-winds', + 'eot' => 'application/vnd.ms-fontobject', + 'eps' => 'application/postscript', + 'epub' => 'application/epub+zip', + 'es3' => 'application/vnd.eszigno3+xml', + 'esa' => 'application/vnd.osgi.subsystem', + 'esf' => 'application/vnd.epson.esf', + 'et3' => 'application/vnd.eszigno3+xml', + 'etx' => 'text/x-setext', + 'eva' => 'application/x-eva', + 'evy' => 'application/x-envoy', + 'exe' => 'application/x-msdownload', + 'exi' => 'application/exi', + 'ext' => 'application/vnd.novadigm.ext', + 'ez' => 'application/andrew-inset', + 'ez2' => 'application/vnd.ezpix-album', + 'ez3' => 'application/vnd.ezpix-package', + 'f' => 'text/x-fortran', + 'f4v' => 'video/x-f4v', + 'f77' => 'text/x-fortran', + 'f90' => 'text/x-fortran', + 'fbs' => 'image/vnd.fastbidsheet', + 'fcdt' => 'application/vnd.adobe.formscentral.fcdt', + 'fcs' => 'application/vnd.isac.fcs', + 'fdf' => 'application/vnd.fdf', + 'fe_launch' => 'application/vnd.denovo.fcselayout-link', + 'fg5' => 'application/vnd.fujitsu.oasysgp', + 'fgd' => 'application/x-director', + 'fh' => 'image/x-freehand', + 'fh4' => 'image/x-freehand', + 'fh5' => 'image/x-freehand', + 'fh7' => 'image/x-freehand', + 'fhc' => 'image/x-freehand', + 'fig' => 'application/x-xfig', + 'flac' => 'audio/x-flac', + 'fli' => 'video/x-fli', + 'flo' => 'application/vnd.micrografx.flo', + 'flv' => 'video/x-flv', + 'flw' => 'application/vnd.kde.kivio', + 'flx' => 'text/vnd.fmi.flexstor', + 'fly' => 'text/vnd.fly', + 'fm' => 'application/vnd.framemaker', + 'fnc' => 'application/vnd.frogans.fnc', + 'for' => 'text/x-fortran', + 'fpx' => 'image/vnd.fpx', + 'frame' => 'application/vnd.framemaker', + 'fsc' => 'application/vnd.fsc.weblaunch', + 'fst' => 'image/vnd.fst', + 'ftc' => 'application/vnd.fluxtime.clip', + 'fti' => 'application/vnd.anser-web-funds-transfer-initiation', + 'fvt' => 'video/vnd.fvt', + 'fxp' => 'application/vnd.adobe.fxp', + 'fxpl' => 'application/vnd.adobe.fxp', + 'fzs' => 'application/vnd.fuzzysheet', + 'g2w' => 'application/vnd.geoplan', + 'g3' => 'image/g3fax', + 'g3w' => 'application/vnd.geospace', + 'gac' => 'application/vnd.groove-account', + 'gam' => 'application/x-tads', + 'gbr' => 'application/rpki-ghostbusters', + 'gca' => 'application/x-gca-compressed', + 'gdl' => 'model/vnd.gdl', + 'geo' => 'application/vnd.dynageo', + 'gex' => 'application/vnd.geometry-explorer', + 'ggb' => 'application/vnd.geogebra.file', + 'ggt' => 'application/vnd.geogebra.tool', + 'ghf' => 'application/vnd.groove-help', + 'gif' => 'image/gif', + 'gim' => 'application/vnd.groove-identity-message', + 'gml' => 'application/gml+xml', + 'gmx' => 'application/vnd.gmx', + 'gnumeric' => 'application/x-gnumeric', + 'gph' => 'application/vnd.flographit', + 'gpx' => 'application/gpx+xml', + 'gqf' => 'application/vnd.grafeq', + 'gqs' => 'application/vnd.grafeq', + 'gram' => 'application/srgs', + 'gramps' => 'application/x-gramps-xml', + 'gre' => 'application/vnd.geometry-explorer', + 'grv' => 'application/vnd.groove-injector', + 'grxml' => 'application/srgs+xml', + 'gsf' => 'application/x-font-ghostscript', + 'gtar' => 'application/x-gtar', + 'gtm' => 'application/vnd.groove-tool-message', + 'gtw' => 'model/vnd.gtw', + 'gv' => 'text/vnd.graphviz', + 'gxf' => 'application/gxf', + 'gxt' => 'application/vnd.geonext', + 'gz' => 'application/x-gzip', + 'h' => 'text/x-c', + 'h261' => 'video/h261', + 'h263' => 'video/h263', + 'h264' => 'video/h264', + 'hal' => 'application/vnd.hal+xml', + 'hbci' => 'application/vnd.hbci', + 'hdf' => 'application/x-hdf', + 'hh' => 'text/x-c', + 'hlp' => 'application/winhlp', + 'hpgl' => 'application/vnd.hp-hpgl', + 'hpid' => 'application/vnd.hp-hpid', + 'hps' => 'application/vnd.hp-hps', + 'hqx' => 'application/mac-binhex40', + 'htke' => 'application/vnd.kenameaapp', + 'htm' => 'text/html', + 'html' => 'text/html', + 'hvd' => 'application/vnd.yamaha.hv-dic', + 'hvp' => 'application/vnd.yamaha.hv-voice', + 'hvs' => 'application/vnd.yamaha.hv-script', + 'i2g' => 'application/vnd.intergeo', + 'icc' => 'application/vnd.iccprofile', + 'ice' => 'x-conference/x-cooltalk', + 'icm' => 'application/vnd.iccprofile', + 'ico' => 'image/x-icon', + 'ics' => 'text/calendar', + 'ief' => 'image/ief', + 'ifb' => 'text/calendar', + 'ifm' => 'application/vnd.shana.informed.formdata', + 'iges' => 'model/iges', + 'igl' => 'application/vnd.igloader', + 'igm' => 'application/vnd.insors.igm', + 'igs' => 'model/iges', + 'igx' => 'application/vnd.micrografx.igx', + 'iif' => 'application/vnd.shana.informed.interchange', + 'imp' => 'application/vnd.accpac.simply.imp', + 'ims' => 'application/vnd.ms-ims', + 'in' => 'text/plain', + 'ink' => 'application/inkml+xml', + 'inkml' => 'application/inkml+xml', + 'install' => 'application/x-install-instructions', + 'iota' => 'application/vnd.astraea-software.iota', + 'ipfix' => 'application/ipfix', + 'ipk' => 'application/vnd.shana.informed.package', + 'irm' => 'application/vnd.ibm.rights-management', + 'irp' => 'application/vnd.irepository.package+xml', + 'iso' => 'application/x-iso9660-image', + 'itp' => 'application/vnd.shana.informed.formtemplate', + 'ivp' => 'application/vnd.immervision-ivp', + 'ivu' => 'application/vnd.immervision-ivu', + 'jad' => 'text/vnd.sun.j2me.app-descriptor', + 'jam' => 'application/vnd.jam', + 'jar' => 'application/java-archive', + 'java' => 'text/x-java-source', + 'jisp' => 'application/vnd.jisp', + 'jlt' => 'application/vnd.hp-jlyt', + 'jnlp' => 'application/x-java-jnlp-file', + 'joda' => 'application/vnd.joost.joda-archive', + 'jpe' => 'image/jpeg', + 'jpeg' => 'image/jpeg', + 'jpg' => 'image/jpeg', + 'jpgm' => 'video/jpm', + 'jpgv' => 'video/jpeg', + 'jpm' => 'video/jpm', + 'js' => 'application/javascript', + 'json' => 'application/json', + 'jsonml' => 'application/jsonml+json', + 'kar' => 'audio/midi', + 'karbon' => 'application/vnd.kde.karbon', + 'kfo' => 'application/vnd.kde.kformula', + 'kia' => 'application/vnd.kidspiration', + 'kml' => 'application/vnd.google-earth.kml+xml', + 'kmz' => 'application/vnd.google-earth.kmz', + 'kne' => 'application/vnd.kinar', + 'knp' => 'application/vnd.kinar', + 'kon' => 'application/vnd.kde.kontour', + 'kpr' => 'application/vnd.kde.kpresenter', + 'kpt' => 'application/vnd.kde.kpresenter', + 'kpxx' => 'application/vnd.ds-keypoint', + 'ksp' => 'application/vnd.kde.kspread', + 'ktr' => 'application/vnd.kahootz', + 'ktx' => 'image/ktx', + 'ktz' => 'application/vnd.kahootz', + 'kwd' => 'application/vnd.kde.kword', + 'kwt' => 'application/vnd.kde.kword', + 'lasxml' => 'application/vnd.las.las+xml', + 'latex' => 'application/x-latex', + 'lbd' => 'application/vnd.llamagraphics.life-balance.desktop', + 'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml', + 'les' => 'application/vnd.hhe.lesson-player', + 'lha' => 'application/x-lzh-compressed', + 'link66' => 'application/vnd.route66.link66+xml', + 'list' => 'text/plain', + 'list3820' => 'application/vnd.ibm.modcap', + 'listafp' => 'application/vnd.ibm.modcap', + 'lnk' => 'application/x-ms-shortcut', + 'log' => 'text/plain', + 'lostxml' => 'application/lost+xml', + 'lrf' => 'application/octet-stream', + 'lrm' => 'application/vnd.ms-lrm', + 'ltf' => 'application/vnd.frogans.ltf', + 'lvp' => 'audio/vnd.lucent.voice', + 'lwp' => 'application/vnd.lotus-wordpro', + 'lzh' => 'application/x-lzh-compressed', + 'm13' => 'application/x-msmediaview', + 'm14' => 'application/x-msmediaview', + 'm1v' => 'video/mpeg', + 'm21' => 'application/mp21', + 'm2a' => 'audio/mpeg', + 'm2v' => 'video/mpeg', + 'm3a' => 'audio/mpeg', + 'm3u' => 'audio/x-mpegurl', + 'm3u8' => 'application/vnd.apple.mpegurl', + 'm4a' => 'audio/mp4', + 'm4u' => 'video/vnd.mpegurl', + 'm4v' => 'video/x-m4v', + 'ma' => 'application/mathematica', + 'mads' => 'application/mads+xml', + 'mag' => 'application/vnd.ecowin.chart', + 'maker' => 'application/vnd.framemaker', + 'man' => 'text/troff', + 'mar' => 'application/octet-stream', + 'mathml' => 'application/mathml+xml', + 'mb' => 'application/mathematica', + 'mbk' => 'application/vnd.mobius.mbk', + 'mbox' => 'application/mbox', + 'mc1' => 'application/vnd.medcalcdata', + 'mcd' => 'application/vnd.mcd', + 'mcurl' => 'text/vnd.curl.mcurl', + 'mdb' => 'application/x-msaccess', + 'mdi' => 'image/vnd.ms-modi', + 'me' => 'text/troff', + 'mesh' => 'model/mesh', + 'meta4' => 'application/metalink4+xml', + 'metalink' => 'application/metalink+xml', + 'mets' => 'application/mets+xml', + 'mfm' => 'application/vnd.mfmp', + 'mft' => 'application/rpki-manifest', + 'mgp' => 'application/vnd.osgeo.mapguide.package', + 'mgz' => 'application/vnd.proteus.magazine', + 'mid' => 'audio/midi', + 'midi' => 'audio/midi', + 'mie' => 'application/x-mie', + 'mif' => 'application/vnd.mif', + 'mime' => 'message/rfc822', + 'mj2' => 'video/mj2', + 'mjp2' => 'video/mj2', + 'mk3d' => 'video/x-matroska', + 'mka' => 'audio/x-matroska', + 'mks' => 'video/x-matroska', + 'mkv' => 'video/x-matroska', + 'mlp' => 'application/vnd.dolby.mlp', + 'mmd' => 'application/vnd.chipnuts.karaoke-mmd', + 'mmf' => 'application/vnd.smaf', + 'mmr' => 'image/vnd.fujixerox.edmics-mmr', + 'mng' => 'video/x-mng', + 'mny' => 'application/x-msmoney', + 'mobi' => 'application/x-mobipocket-ebook', + 'mods' => 'application/mods+xml', + 'mov' => 'video/quicktime', + 'movie' => 'video/x-sgi-movie', + 'mp2' => 'audio/mpeg', + 'mp21' => 'application/mp21', + 'mp2a' => 'audio/mpeg', + 'mp3' => 'audio/mpeg', + 'mp4' => 'video/mp4', + 'mp4a' => 'audio/mp4', + 'mp4s' => 'application/mp4', + 'mp4v' => 'video/mp4', + 'mpc' => 'application/vnd.mophun.certificate', + 'mpe' => 'video/mpeg', + 'mpeg' => 'video/mpeg', + 'mpg' => 'video/mpeg', + 'mpg4' => 'video/mp4', + 'mpga' => 'audio/mpeg', + 'mpkg' => 'application/vnd.apple.installer+xml', + 'mpm' => 'application/vnd.blueice.multipass', + 'mpn' => 'application/vnd.mophun.application', + 'mpp' => 'application/vnd.ms-project', + 'mpt' => 'application/vnd.ms-project', + 'mpy' => 'application/vnd.ibm.minipay', + 'mqy' => 'application/vnd.mobius.mqy', + 'mrc' => 'application/marc', + 'mrcx' => 'application/marcxml+xml', + 'ms' => 'text/troff', + 'mscml' => 'application/mediaservercontrol+xml', + 'mseed' => 'application/vnd.fdsn.mseed', + 'mseq' => 'application/vnd.mseq', + 'msf' => 'application/vnd.epson.msf', + 'msh' => 'model/mesh', + 'msi' => 'application/x-msdownload', + 'msl' => 'application/vnd.mobius.msl', + 'msty' => 'application/vnd.muvee.style', + 'mts' => 'model/vnd.mts', + 'mus' => 'application/vnd.musician', + 'musicxml' => 'application/vnd.recordare.musicxml+xml', + 'mvb' => 'application/x-msmediaview', + 'mwf' => 'application/vnd.mfer', + 'mxf' => 'application/mxf', + 'mxl' => 'application/vnd.recordare.musicxml', + 'mxml' => 'application/xv+xml', + 'mxs' => 'application/vnd.triscape.mxs', + 'mxu' => 'video/vnd.mpegurl', + 'n-gage' => 'application/vnd.nokia.n-gage.symbian.install', + 'n3' => 'text/n3', + 'nb' => 'application/mathematica', + 'nbp' => 'application/vnd.wolfram.player', + 'nc' => 'application/x-netcdf', + 'ncx' => 'application/x-dtbncx+xml', + 'nfo' => 'text/x-nfo', + 'ngdat' => 'application/vnd.nokia.n-gage.data', + 'nitf' => 'application/vnd.nitf', + 'nlu' => 'application/vnd.neurolanguage.nlu', + 'nml' => 'application/vnd.enliven', + 'nnd' => 'application/vnd.noblenet-directory', + 'nns' => 'application/vnd.noblenet-sealer', + 'nnw' => 'application/vnd.noblenet-web', + 'npx' => 'image/vnd.net-fpx', + 'nsc' => 'application/x-conference', + 'nsf' => 'application/vnd.lotus-notes', + 'ntf' => 'application/vnd.nitf', + 'nzb' => 'application/x-nzb', + 'oa2' => 'application/vnd.fujitsu.oasys2', + 'oa3' => 'application/vnd.fujitsu.oasys3', + 'oas' => 'application/vnd.fujitsu.oasys', + 'obd' => 'application/x-msbinder', + 'obj' => 'application/x-tgif', + 'oda' => 'application/oda', + 'odb' => 'application/vnd.oasis.opendocument.database', + 'odc' => 'application/vnd.oasis.opendocument.chart', + 'odf' => 'application/vnd.oasis.opendocument.formula', + 'odft' => 'application/vnd.oasis.opendocument.formula-template', + 'odg' => 'application/vnd.oasis.opendocument.graphics', + 'odi' => 'application/vnd.oasis.opendocument.image', + 'odm' => 'application/vnd.oasis.opendocument.text-master', + 'odp' => 'application/vnd.oasis.opendocument.presentation', + 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', + 'odt' => 'application/vnd.oasis.opendocument.text', + 'oga' => 'audio/ogg', + 'ogg' => 'audio/ogg', + 'ogv' => 'video/ogg', + 'ogx' => 'application/ogg', + 'omdoc' => 'application/omdoc+xml', + 'onepkg' => 'application/onenote', + 'onetmp' => 'application/onenote', + 'onetoc' => 'application/onenote', + 'onetoc2' => 'application/onenote', + 'opf' => 'application/oebps-package+xml', + 'opml' => 'text/x-opml', + 'oprc' => 'application/vnd.palm', + 'org' => 'application/vnd.lotus-organizer', + 'osf' => 'application/vnd.yamaha.openscoreformat', + 'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml', + 'otc' => 'application/vnd.oasis.opendocument.chart-template', + 'otf' => 'application/x-font-otf', + 'otg' => 'application/vnd.oasis.opendocument.graphics-template', + 'oth' => 'application/vnd.oasis.opendocument.text-web', + 'oti' => 'application/vnd.oasis.opendocument.image-template', + 'otp' => 'application/vnd.oasis.opendocument.presentation-template', + 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template', + 'ott' => 'application/vnd.oasis.opendocument.text-template', + 'oxps' => 'application/oxps', + 'oxt' => 'application/vnd.openofficeorg.extension', + 'p' => 'text/x-pascal', + 'p10' => 'application/pkcs10', + 'p12' => 'application/x-pkcs12', + 'p7b' => 'application/x-pkcs7-certificates', + 'p7c' => 'application/pkcs7-mime', + 'p7m' => 'application/pkcs7-mime', + 'p7r' => 'application/x-pkcs7-certreqresp', + 'p7s' => 'application/pkcs7-signature', + 'p8' => 'application/pkcs8', + 'pas' => 'text/x-pascal', + 'paw' => 'application/vnd.pawaafile', + 'pbd' => 'application/vnd.powerbuilder6', + 'pbm' => 'image/x-portable-bitmap', + 'pcap' => 'application/vnd.tcpdump.pcap', + 'pcf' => 'application/x-font-pcf', + 'pcl' => 'application/vnd.hp-pcl', + 'pclxl' => 'application/vnd.hp-pclxl', + 'pct' => 'image/x-pict', + 'pcurl' => 'application/vnd.curl.pcurl', + 'pcx' => 'image/x-pcx', + 'pdb' => 'application/vnd.palm', + 'pdf' => 'application/pdf', + 'pfa' => 'application/x-font-type1', + 'pfb' => 'application/x-font-type1', + 'pfm' => 'application/x-font-type1', + 'pfr' => 'application/font-tdpfr', + 'pfx' => 'application/x-pkcs12', + 'pgm' => 'image/x-portable-graymap', + 'pgn' => 'application/x-chess-pgn', + 'pgp' => 'application/pgp-encrypted', + 'php' => 'application/x-php', + 'php3' => 'application/x-php', + 'php4' => 'application/x-php', + 'php5' => 'application/x-php', + 'pic' => 'image/x-pict', + 'pkg' => 'application/octet-stream', + 'pki' => 'application/pkixcmp', + 'pkipath' => 'application/pkix-pkipath', + 'plb' => 'application/vnd.3gpp.pic-bw-large', + 'plc' => 'application/vnd.mobius.plc', + 'plf' => 'application/vnd.pocketlearn', + 'pls' => 'application/pls+xml', + 'pml' => 'application/vnd.ctc-posml', + 'png' => 'image/png', + 'pnm' => 'image/x-portable-anymap', + 'portpkg' => 'application/vnd.macports.portpkg', + 'pot' => 'application/vnd.ms-powerpoint', + 'potm' => 'application/vnd.ms-powerpoint.template.macroenabled.12', + 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template', + 'ppam' => 'application/vnd.ms-powerpoint.addin.macroenabled.12', + 'ppd' => 'application/vnd.cups-ppd', + 'ppm' => 'image/x-portable-pixmap', + 'pps' => 'application/vnd.ms-powerpoint', + 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroenabled.12', + 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', + 'ppt' => 'application/vnd.ms-powerpoint', + 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroenabled.12', + 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'pqa' => 'application/vnd.palm', + 'prc' => 'application/x-mobipocket-ebook', + 'pre' => 'application/vnd.lotus-freelance', + 'prf' => 'application/pics-rules', + 'ps' => 'application/postscript', + 'psb' => 'application/vnd.3gpp.pic-bw-small', + 'psd' => 'image/vnd.adobe.photoshop', + 'psf' => 'application/x-font-linux-psf', + 'pskcxml' => 'application/pskc+xml', + 'ptid' => 'application/vnd.pvi.ptid1', + 'pub' => 'application/x-mspublisher', + 'pvb' => 'application/vnd.3gpp.pic-bw-var', + 'pwn' => 'application/vnd.3m.post-it-notes', + 'pya' => 'audio/vnd.ms-playready.media.pya', + 'pyv' => 'video/vnd.ms-playready.media.pyv', + 'qam' => 'application/vnd.epson.quickanime', + 'qbo' => 'application/vnd.intu.qbo', + 'qfx' => 'application/vnd.intu.qfx', + 'qps' => 'application/vnd.publishare-delta-tree', + 'qt' => 'video/quicktime', + 'qwd' => 'application/vnd.quark.quarkxpress', + 'qwt' => 'application/vnd.quark.quarkxpress', + 'qxb' => 'application/vnd.quark.quarkxpress', + 'qxd' => 'application/vnd.quark.quarkxpress', + 'qxl' => 'application/vnd.quark.quarkxpress', + 'qxt' => 'application/vnd.quark.quarkxpress', + 'ra' => 'audio/x-pn-realaudio', + 'ram' => 'audio/x-pn-realaudio', + 'rar' => 'application/x-rar-compressed', + 'ras' => 'image/x-cmu-raster', + 'rcprofile' => 'application/vnd.ipunplugged.rcprofile', + 'rdf' => 'application/rdf+xml', + 'rdz' => 'application/vnd.data-vision.rdz', + 'rep' => 'application/vnd.businessobjects', + 'res' => 'application/x-dtbresource+xml', + 'rgb' => 'image/x-rgb', + 'rif' => 'application/reginfo+xml', + 'rip' => 'audio/vnd.rip', + 'ris' => 'application/x-research-info-systems', + 'rl' => 'application/resource-lists+xml', + 'rlc' => 'image/vnd.fujixerox.edmics-rlc', + 'rld' => 'application/resource-lists-diff+xml', + 'rm' => 'application/vnd.rn-realmedia', + 'rmi' => 'audio/midi', + 'rmp' => 'audio/x-pn-realaudio-plugin', + 'rms' => 'application/vnd.jcp.javame.midlet-rms', + 'rmvb' => 'application/vnd.rn-realmedia-vbr', + 'rnc' => 'application/relax-ng-compact-syntax', + 'roa' => 'application/rpki-roa', + 'roff' => 'text/troff', + 'rp9' => 'application/vnd.cloanto.rp9', + 'rpss' => 'application/vnd.nokia.radio-presets', + 'rpst' => 'application/vnd.nokia.radio-preset', + 'rq' => 'application/sparql-query', + 'rs' => 'application/rls-services+xml', + 'rsd' => 'application/rsd+xml', + 'rss' => 'application/rss+xml', + 'rtf' => 'application/rtf', + 'rtx' => 'text/richtext', + 's' => 'text/x-asm', + 's3m' => 'audio/s3m', + 'saf' => 'application/vnd.yamaha.smaf-audio', + 'sbml' => 'application/sbml+xml', + 'sc' => 'application/vnd.ibm.secure-container', + 'scd' => 'application/x-msschedule', + 'scm' => 'application/vnd.lotus-screencam', + 'scq' => 'application/scvp-cv-request', + 'scs' => 'application/scvp-cv-response', + 'scurl' => 'text/vnd.curl.scurl', + 'sda' => 'application/vnd.stardivision.draw', + 'sdc' => 'application/vnd.stardivision.calc', + 'sdd' => 'application/vnd.stardivision.impress', + 'sdkd' => 'application/vnd.solent.sdkm+xml', + 'sdkm' => 'application/vnd.solent.sdkm+xml', + 'sdp' => 'application/sdp', + 'sdw' => 'application/vnd.stardivision.writer', + 'see' => 'application/vnd.seemail', + 'seed' => 'application/vnd.fdsn.seed', + 'sema' => 'application/vnd.sema', + 'semd' => 'application/vnd.semd', + 'semf' => 'application/vnd.semf', + 'ser' => 'application/java-serialized-object', + 'setpay' => 'application/set-payment-initiation', + 'setreg' => 'application/set-registration-initiation', + 'sfd-hdstx' => 'application/vnd.hydrostatix.sof-data', + 'sfs' => 'application/vnd.spotfire.sfs', + 'sfv' => 'text/x-sfv', + 'sgi' => 'image/sgi', + 'sgl' => 'application/vnd.stardivision.writer-global', + 'sgm' => 'text/sgml', + 'sgml' => 'text/sgml', + 'sh' => 'application/x-sh', + 'shar' => 'application/x-shar', + 'shf' => 'application/shf+xml', + 'sid' => 'image/x-mrsid-image', + 'sig' => 'application/pgp-signature', + 'sil' => 'audio/silk', + 'silo' => 'model/mesh', + 'sis' => 'application/vnd.symbian.install', + 'sisx' => 'application/vnd.symbian.install', + 'sit' => 'application/x-stuffit', + 'sitx' => 'application/x-stuffitx', + 'skd' => 'application/vnd.koan', + 'skm' => 'application/vnd.koan', + 'skp' => 'application/vnd.koan', + 'skt' => 'application/vnd.koan', + 'sldm' => 'application/vnd.ms-powerpoint.slide.macroenabled.12', + 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide', + 'slt' => 'application/vnd.epson.salt', + 'sm' => 'application/vnd.stepmania.stepchart', + 'smf' => 'application/vnd.stardivision.math', + 'smi' => 'application/smil+xml', + 'smil' => 'application/smil+xml', + 'smv' => 'video/x-smv', + 'smzip' => 'application/vnd.stepmania.package', + 'snd' => 'audio/basic', + 'snf' => 'application/x-font-snf', + 'so' => 'application/octet-stream', + 'spc' => 'application/x-pkcs7-certificates', + 'spf' => 'application/vnd.yamaha.smaf-phrase', + 'spl' => 'application/x-futuresplash', + 'spot' => 'text/vnd.in3d.spot', + 'spp' => 'application/scvp-vp-response', + 'spq' => 'application/scvp-vp-request', + 'spx' => 'audio/ogg', + 'sql' => 'application/x-sql', + 'src' => 'application/x-wais-source', + 'srt' => 'application/x-subrip', + 'sru' => 'application/sru+xml', + 'srx' => 'application/sparql-results+xml', + 'ssdl' => 'application/ssdl+xml', + 'sse' => 'application/vnd.kodak-descriptor', + 'ssf' => 'application/vnd.epson.ssf', + 'ssml' => 'application/ssml+xml', + 'st' => 'application/vnd.sailingtracker.track', + 'stc' => 'application/vnd.sun.xml.calc.template', + 'std' => 'application/vnd.sun.xml.draw.template', + 'stf' => 'application/vnd.wt.stf', + 'sti' => 'application/vnd.sun.xml.impress.template', + 'stk' => 'application/hyperstudio', + 'stl' => 'application/vnd.ms-pki.stl', + 'str' => 'application/vnd.pg.format', + 'stw' => 'application/vnd.sun.xml.writer.template', + 'sub' => 'text/vnd.dvb.subtitle', + 'sus' => 'application/vnd.sus-calendar', + 'susp' => 'application/vnd.sus-calendar', + 'sv4cpio' => 'application/x-sv4cpio', + 'sv4crc' => 'application/x-sv4crc', + 'svc' => 'application/vnd.dvb.service', + 'svd' => 'application/vnd.svd', + 'svg' => 'image/svg+xml', + 'svgz' => 'image/svg+xml', + 'swa' => 'application/x-director', + 'swf' => 'application/x-shockwave-flash', + 'swi' => 'application/vnd.aristanetworks.swi', + 'sxc' => 'application/vnd.sun.xml.calc', + 'sxd' => 'application/vnd.sun.xml.draw', + 'sxg' => 'application/vnd.sun.xml.writer.global', + 'sxi' => 'application/vnd.sun.xml.impress', + 'sxm' => 'application/vnd.sun.xml.math', + 'sxw' => 'application/vnd.sun.xml.writer', + 't' => 'text/troff', + 't3' => 'application/x-t3vm-image', + 'taglet' => 'application/vnd.mynfc', + 'tao' => 'application/vnd.tao.intent-module-archive', + 'tar' => 'application/x-tar', + 'tcap' => 'application/vnd.3gpp2.tcap', + 'tcl' => 'application/x-tcl', + 'teacher' => 'application/vnd.smart.teacher', + 'tei' => 'application/tei+xml', + 'teicorpus' => 'application/tei+xml', + 'tex' => 'application/x-tex', + 'texi' => 'application/x-texinfo', + 'texinfo' => 'application/x-texinfo', + 'text' => 'text/plain', + 'tfi' => 'application/thraud+xml', + 'tfm' => 'application/x-tex-tfm', + 'tga' => 'image/x-tga', + 'thmx' => 'application/vnd.ms-officetheme', + 'tif' => 'image/tiff', + 'tiff' => 'image/tiff', + 'tmo' => 'application/vnd.tmobile-livetv', + 'torrent' => 'application/x-bittorrent', + 'tpl' => 'application/vnd.groove-tool-template', + 'tpt' => 'application/vnd.trid.tpt', + 'tr' => 'text/troff', + 'tra' => 'application/vnd.trueapp', + 'trm' => 'application/x-msterminal', + 'tsd' => 'application/timestamped-data', + 'tsv' => 'text/tab-separated-values', + 'ttc' => 'application/x-font-ttf', + 'ttf' => 'application/x-font-ttf', + 'ttl' => 'text/turtle', + 'twd' => 'application/vnd.simtech-mindmapper', + 'twds' => 'application/vnd.simtech-mindmapper', + 'txd' => 'application/vnd.genomatix.tuxedo', + 'txf' => 'application/vnd.mobius.txf', + 'txt' => 'text/plain', + 'u32' => 'application/x-authorware-bin', + 'udeb' => 'application/x-debian-package', + 'ufd' => 'application/vnd.ufdl', + 'ufdl' => 'application/vnd.ufdl', + 'ulx' => 'application/x-glulx', + 'umj' => 'application/vnd.umajin', + 'unityweb' => 'application/vnd.unity', + 'uoml' => 'application/vnd.uoml+xml', + 'uri' => 'text/uri-list', + 'uris' => 'text/uri-list', + 'urls' => 'text/uri-list', + 'ustar' => 'application/x-ustar', + 'utz' => 'application/vnd.uiq.theme', + 'uu' => 'text/x-uuencode', + 'uva' => 'audio/vnd.dece.audio', + 'uvd' => 'application/vnd.dece.data', + 'uvf' => 'application/vnd.dece.data', + 'uvg' => 'image/vnd.dece.graphic', + 'uvh' => 'video/vnd.dece.hd', + 'uvi' => 'image/vnd.dece.graphic', + 'uvm' => 'video/vnd.dece.mobile', + 'uvp' => 'video/vnd.dece.pd', + 'uvs' => 'video/vnd.dece.sd', + 'uvt' => 'application/vnd.dece.ttml+xml', + 'uvu' => 'video/vnd.uvvu.mp4', + 'uvv' => 'video/vnd.dece.video', + 'uvva' => 'audio/vnd.dece.audio', + 'uvvd' => 'application/vnd.dece.data', + 'uvvf' => 'application/vnd.dece.data', + 'uvvg' => 'image/vnd.dece.graphic', + 'uvvh' => 'video/vnd.dece.hd', + 'uvvi' => 'image/vnd.dece.graphic', + 'uvvm' => 'video/vnd.dece.mobile', + 'uvvp' => 'video/vnd.dece.pd', + 'uvvs' => 'video/vnd.dece.sd', + 'uvvt' => 'application/vnd.dece.ttml+xml', + 'uvvu' => 'video/vnd.uvvu.mp4', + 'uvvv' => 'video/vnd.dece.video', + 'uvvx' => 'application/vnd.dece.unspecified', + 'uvvz' => 'application/vnd.dece.zip', + 'uvx' => 'application/vnd.dece.unspecified', + 'uvz' => 'application/vnd.dece.zip', + 'vcard' => 'text/vcard', + 'vcd' => 'application/x-cdlink', + 'vcf' => 'text/x-vcard', + 'vcg' => 'application/vnd.groove-vcard', + 'vcs' => 'text/x-vcalendar', + 'vcx' => 'application/vnd.vcx', + 'vis' => 'application/vnd.visionary', + 'viv' => 'video/vnd.vivo', + 'vob' => 'video/x-ms-vob', + 'vor' => 'application/vnd.stardivision.writer', + 'vox' => 'application/x-authorware-bin', + 'vrml' => 'model/vrml', + 'vsd' => 'application/vnd.visio', + 'vsf' => 'application/vnd.vsf', + 'vss' => 'application/vnd.visio', + 'vst' => 'application/vnd.visio', + 'vsw' => 'application/vnd.visio', + 'vtu' => 'model/vnd.vtu', + 'vxml' => 'application/voicexml+xml', + 'w3d' => 'application/x-director', + 'wad' => 'application/x-doom', + 'wav' => 'audio/x-wav', + 'wax' => 'audio/x-ms-wax', + 'wbmp' => 'image/vnd.wap.wbmp', + 'wbs' => 'application/vnd.criticaltools.wbs+xml', + 'wbxml' => 'application/vnd.wap.wbxml', + 'wcm' => 'application/vnd.ms-works', + 'wdb' => 'application/vnd.ms-works', + 'wdp' => 'image/vnd.ms-photo', + 'weba' => 'audio/webm', + 'webm' => 'video/webm', + 'webp' => 'image/webp', + 'wg' => 'application/vnd.pmi.widget', + 'wgt' => 'application/widget', + 'wks' => 'application/vnd.ms-works', + 'wm' => 'video/x-ms-wm', + 'wma' => 'audio/x-ms-wma', + 'wmd' => 'application/x-ms-wmd', + 'wmf' => 'application/x-msmetafile', + 'wml' => 'text/vnd.wap.wml', + 'wmlc' => 'application/vnd.wap.wmlc', + 'wmls' => 'text/vnd.wap.wmlscript', + 'wmlsc' => 'application/vnd.wap.wmlscriptc', + 'wmv' => 'video/x-ms-wmv', + 'wmx' => 'video/x-ms-wmx', + 'wmz' => 'application/x-msmetafile', + 'woff' => 'application/font-woff', + 'wpd' => 'application/vnd.wordperfect', + 'wpl' => 'application/vnd.ms-wpl', + 'wps' => 'application/vnd.ms-works', + 'wqd' => 'application/vnd.wqd', + 'wri' => 'application/x-mswrite', + 'wrl' => 'model/vrml', + 'wsdl' => 'application/wsdl+xml', + 'wspolicy' => 'application/wspolicy+xml', + 'wtb' => 'application/vnd.webturbo', + 'wvx' => 'video/x-ms-wvx', + 'x32' => 'application/x-authorware-bin', + 'x3d' => 'model/x3d+xml', + 'x3db' => 'model/x3d+binary', + 'x3dbz' => 'model/x3d+binary', + 'x3dv' => 'model/x3d+vrml', + 'x3dvz' => 'model/x3d+vrml', + 'x3dz' => 'model/x3d+xml', + 'xaml' => 'application/xaml+xml', + 'xap' => 'application/x-silverlight-app', + 'xar' => 'application/vnd.xara', + 'xbap' => 'application/x-ms-xbap', + 'xbd' => 'application/vnd.fujixerox.docuworks.binder', + 'xbm' => 'image/x-xbitmap', + 'xdf' => 'application/xcap-diff+xml', + 'xdm' => 'application/vnd.syncml.dm+xml', + 'xdp' => 'application/vnd.adobe.xdp+xml', + 'xdssc' => 'application/dssc+xml', + 'xdw' => 'application/vnd.fujixerox.docuworks', + 'xenc' => 'application/xenc+xml', + 'xer' => 'application/patch-ops-error+xml', + 'xfdf' => 'application/vnd.adobe.xfdf', + 'xfdl' => 'application/vnd.xfdl', + 'xht' => 'application/xhtml+xml', + 'xhtml' => 'application/xhtml+xml', + 'xhvml' => 'application/xv+xml', + 'xif' => 'image/vnd.xiff', + 'xla' => 'application/vnd.ms-excel', + 'xlam' => 'application/vnd.ms-excel.addin.macroenabled.12', + 'xlc' => 'application/vnd.ms-excel', + 'xlf' => 'application/x-xliff+xml', + 'xlm' => 'application/vnd.ms-excel', + 'xls' => 'application/vnd.ms-excel', + 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroenabled.12', + 'xlsm' => 'application/vnd.ms-excel.sheet.macroenabled.12', + 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'xlt' => 'application/vnd.ms-excel', + 'xltm' => 'application/vnd.ms-excel.template.macroenabled.12', + 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', + 'xlw' => 'application/vnd.ms-excel', + 'xm' => 'audio/xm', + 'xml' => 'application/xml', + 'xo' => 'application/vnd.olpc-sugar', + 'xop' => 'application/xop+xml', + 'xpi' => 'application/x-xpinstall', + 'xpl' => 'application/xproc+xml', + 'xpm' => 'image/x-xpixmap', + 'xpr' => 'application/vnd.is-xpr', + 'xps' => 'application/vnd.ms-xpsdocument', + 'xpw' => 'application/vnd.intercon.formnet', + 'xpx' => 'application/vnd.intercon.formnet', + 'xsl' => 'application/xml', + 'xslt' => 'application/xslt+xml', + 'xsm' => 'application/vnd.syncml+xml', + 'xspf' => 'application/xspf+xml', + 'xul' => 'application/vnd.mozilla.xul+xml', + 'xvm' => 'application/xv+xml', + 'xvml' => 'application/xv+xml', + 'xwd' => 'image/x-xwindowdump', + 'xyz' => 'chemical/x-xyz', + 'xz' => 'application/x-xz', + 'yang' => 'application/yang', + 'yin' => 'application/yin+xml', + 'z1' => 'application/x-zmachine', + 'z2' => 'application/x-zmachine', + 'z3' => 'application/x-zmachine', + 'z4' => 'application/x-zmachine', + 'z5' => 'application/x-zmachine', + 'z6' => 'application/x-zmachine', + 'z7' => 'application/x-zmachine', + 'z8' => 'application/x-zmachine', + 'zaz' => 'application/vnd.zzazz.deck+xml', + 'zip' => 'application/zip', + 'zir' => 'application/vnd.zul', + 'zirz' => 'application/vnd.zul', + 'zmm' => 'application/vnd.handheld-entertainment+xml', + '123' => 'application/vnd.lotus-1-2-3', ]; diff --git a/htdocs/includes/swiftmailer/lib/swiftmailer_generate_mimes_config.php b/htdocs/includes/swiftmailer/lib/swiftmailer_generate_mimes_config.php index b3febce4802..ad8fd2aa0d5 100644 --- a/htdocs/includes/swiftmailer/lib/swiftmailer_generate_mimes_config.php +++ b/htdocs/includes/swiftmailer/lib/swiftmailer_generate_mimes_config.php @@ -6,177 +6,177 @@ function generateUpToDateMimeArray() { - $preamble = " 'application/x-php', - 'php3' => 'application/x-php', - 'php4' => 'application/x-php', - 'php5' => 'application/x-php', - 'zip' => 'application/zip', - 'gif' => 'image/gif', - 'png' => 'image/png', - 'css' => 'text/css', - 'js' => 'text/javascript', - 'txt' => 'text/plain', - 'aif' => 'audio/x-aiff', - 'aiff' => 'audio/x-aiff', - 'avi' => 'video/avi', - 'bmp' => 'image/bmp', - 'bz2' => 'application/x-bz2', - 'csv' => 'text/csv', - 'dmg' => 'application/x-apple-diskimage', - 'doc' => 'application/msword', - 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', - 'eml' => 'message/rfc822', - 'aps' => 'application/postscript', - 'exe' => 'application/x-ms-dos-executable', - 'flv' => 'video/x-flv', - 'gz' => 'application/x-gzip', - 'hqx' => 'application/stuffit', - 'htm' => 'text/html', - 'html' => 'text/html', - 'jar' => 'application/x-java-archive', - 'jpeg' => 'image/jpeg', - 'jpg' => 'image/jpeg', - 'm3u' => 'audio/x-mpegurl', - 'm4a' => 'audio/mp4', - 'mdb' => 'application/x-msaccess', - 'mid' => 'audio/midi', - 'midi' => 'audio/midi', - 'mov' => 'video/quicktime', - 'mp3' => 'audio/mpeg', - 'mp4' => 'video/mp4', - 'mpeg' => 'video/mpeg', - 'mpg' => 'video/mpeg', - 'odg' => 'vnd.oasis.opendocument.graphics', - 'odp' => 'vnd.oasis.opendocument.presentation', - 'odt' => 'vnd.oasis.opendocument.text', - 'ods' => 'vnd.oasis.opendocument.spreadsheet', - 'ogg' => 'audio/ogg', - 'pdf' => 'application/pdf', - 'ppt' => 'application/vnd.ms-powerpoint', - 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', - 'ps' => 'application/postscript', - 'rar' => 'application/x-rar-compressed', - 'rtf' => 'application/rtf', - 'tar' => 'application/x-tar', - 'sit' => 'application/x-stuffit', - 'svg' => 'image/svg+xml', - 'tif' => 'image/tiff', - 'tiff' => 'image/tiff', - 'ttf' => 'application/x-font-truetype', - 'vcf' => 'text/x-vcard', - 'wav' => 'audio/wav', - 'wma' => 'audio/x-ms-wma', - 'wmv' => 'audio/x-ms-wmv', - 'xls' => 'application/vnd.ms-excel', - 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', - 'xml' => 'application/xml', - ]; + // split mime type and extensions eg. "video/x-matroska mkv mk3d mks" + if (false !== preg_match_all('/^#?([a-z0-9\-\+\/\.]+)[\t]+(.*)$/miu', $mime_types, $matches)) { + // collection of predefined mimetypes (bugfix for wrong resolved or missing mime types) + $valid_mime_types_preset = [ + 'php' => 'application/x-php', + 'php3' => 'application/x-php', + 'php4' => 'application/x-php', + 'php5' => 'application/x-php', + 'zip' => 'application/zip', + 'gif' => 'image/gif', + 'png' => 'image/png', + 'css' => 'text/css', + 'js' => 'text/javascript', + 'txt' => 'text/plain', + 'aif' => 'audio/x-aiff', + 'aiff' => 'audio/x-aiff', + 'avi' => 'video/avi', + 'bmp' => 'image/bmp', + 'bz2' => 'application/x-bz2', + 'csv' => 'text/csv', + 'dmg' => 'application/x-apple-diskimage', + 'doc' => 'application/msword', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'eml' => 'message/rfc822', + 'aps' => 'application/postscript', + 'exe' => 'application/x-ms-dos-executable', + 'flv' => 'video/x-flv', + 'gz' => 'application/x-gzip', + 'hqx' => 'application/stuffit', + 'htm' => 'text/html', + 'html' => 'text/html', + 'jar' => 'application/x-java-archive', + 'jpeg' => 'image/jpeg', + 'jpg' => 'image/jpeg', + 'm3u' => 'audio/x-mpegurl', + 'm4a' => 'audio/mp4', + 'mdb' => 'application/x-msaccess', + 'mid' => 'audio/midi', + 'midi' => 'audio/midi', + 'mov' => 'video/quicktime', + 'mp3' => 'audio/mpeg', + 'mp4' => 'video/mp4', + 'mpeg' => 'video/mpeg', + 'mpg' => 'video/mpeg', + 'odg' => 'vnd.oasis.opendocument.graphics', + 'odp' => 'vnd.oasis.opendocument.presentation', + 'odt' => 'vnd.oasis.opendocument.text', + 'ods' => 'vnd.oasis.opendocument.spreadsheet', + 'ogg' => 'audio/ogg', + 'pdf' => 'application/pdf', + 'ppt' => 'application/vnd.ms-powerpoint', + 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'ps' => 'application/postscript', + 'rar' => 'application/x-rar-compressed', + 'rtf' => 'application/rtf', + 'tar' => 'application/x-tar', + 'sit' => 'application/x-stuffit', + 'svg' => 'image/svg+xml', + 'tif' => 'image/tiff', + 'tiff' => 'image/tiff', + 'ttf' => 'application/x-font-truetype', + 'vcf' => 'text/x-vcard', + 'wav' => 'audio/wav', + 'wma' => 'audio/x-ms-wma', + 'wmv' => 'audio/x-ms-wmv', + 'xls' => 'application/vnd.ms-excel', + 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'xml' => 'application/xml', + ]; - // wrap array for generating file - foreach ($valid_mime_types_preset as $extension => $mime_type) { - // generate array for mimetype to extension resolver (only first match) - $valid_mime_types[$extension] = "'{$extension}' => '{$mime_type}'"; - } + // wrap array for generating file + foreach ($valid_mime_types_preset as $extension => $mime_type) { + // generate array for mimetype to extension resolver (only first match) + $valid_mime_types[$extension] = "'{$extension}' => '{$mime_type}'"; + } - // all extensions from second match - foreach ($matches[2] as $i => $extensions) { - // explode multiple extensions from string - $extensions = explode(' ', strtolower($extensions ?? '')); + // all extensions from second match + foreach ($matches[2] as $i => $extensions) { + // explode multiple extensions from string + $extensions = explode(' ', strtolower($extensions ?? '')); - // force array for foreach - if (!\is_array($extensions)) { - $extensions = [$extensions]; - } + // force array for foreach + if (!\is_array($extensions)) { + $extensions = [$extensions]; + } - foreach ($extensions as $extension) { - // get mime type - $mime_type = $matches[1][$i]; + foreach ($extensions as $extension) { + // get mime type + $mime_type = $matches[1][$i]; - // check if string length lower than 10 - if (\strlen($extension) < 10) { - if (!isset($valid_mime_types[$mime_type])) { - // generate array for mimetype to extension resolver (only first match) - $valid_mime_types[$extension] = "'{$extension}' => '{$mime_type}'"; - } - } - } - } - } + // check if string length lower than 10 + if (\strlen($extension) < 10) { + if (!isset($valid_mime_types[$mime_type])) { + // generate array for mimetype to extension resolver (only first match) + $valid_mime_types[$extension] = "'{$extension}' => '{$mime_type}'"; + } + } + } + } + } - $xml = simplexml_load_string($mime_xml); + $xml = simplexml_load_string($mime_xml); - foreach ($xml as $node) { - // check if there is no pattern - if (!isset($node->glob['pattern'])) { - continue; - } + foreach ($xml as $node) { + // check if there is no pattern + if (!isset($node->glob['pattern'])) { + continue; + } - // get all matching extensions from match - foreach ((array) $node->glob['pattern'] as $extension) { - // skip none glob extensions - if (false === strpos($extension ?? '', '.')) { - continue; - } + // get all matching extensions from match + foreach ((array) $node->glob['pattern'] as $extension) { + // skip none glob extensions + if (false === strpos($extension ?? '', '.')) { + continue; + } - // remove get only last part - $extension = explode('.', strtolower($extension ?? '')); - $extension = end($extension); - } + // remove get only last part + $extension = explode('.', strtolower($extension ?? '')); + $extension = end($extension); + } - if (isset($node->glob['pattern'][0])) { - // mime type - $mime_type = strtolower((string) $node['type'] ?? ''); + if (isset($node->glob['pattern'][0])) { + // mime type + $mime_type = strtolower((string) $node['type'] ?? ''); - // get first extension - $extension = strtolower(trim($node->glob['ddpattern'][0] ?? '', '*.')); + // get first extension + $extension = strtolower(trim($node->glob['ddpattern'][0] ?? '', '*.')); - // skip none glob extensions and check if string length between 1 and 10 - if (false !== strpos($extension, '.') || \strlen($extension) < 1 || \strlen($extension) > 9) { - continue; - } + // skip none glob extensions and check if string length between 1 and 10 + if (false !== strpos($extension, '.') || \strlen($extension) < 1 || \strlen($extension) > 9) { + continue; + } - // check if string length lower than 10 - if (!isset($valid_mime_types[$mime_type])) { - // generate array for mimetype to extension resolver (only first match) - $valid_mime_types[$extension] = "'{$extension}' => '{$mime_type}'"; - } - } - } + // check if string length lower than 10 + if (!isset($valid_mime_types[$mime_type])) { + // generate array for mimetype to extension resolver (only first match) + $valid_mime_types[$extension] = "'{$extension}' => '{$mime_type}'"; + } + } + } - // full list of valid extensions only - $valid_mime_types = array_unique($valid_mime_types); - ksort($valid_mime_types); + // full list of valid extensions only + $valid_mime_types = array_unique($valid_mime_types); + ksort($valid_mime_types); - // combine mime types and extensions array - $output = "$preamble\$swift_mime_types = array(\n ".implode(",\n ", $valid_mime_types)."\n);"; + // combine mime types and extensions array + $output = "$preamble\$swift_mime_types = array(\n ".implode(",\n ", $valid_mime_types)."\n);"; - // write mime_types.php config file - @file_put_contents('./mime_types.php', $output); + // write mime_types.php config file + @file_put_contents('./mime_types.php', $output); } generateUpToDateMimeArray(); diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index a17e7c2e6be..e4ad83e8129 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -285,6 +285,7 @@ if (($action == 'updateline' || $action == 'updatesplitline') && !$cancel && $us } $result = $object->addTimeSpent($user); + } else { $object->fetch($id, $ref); @@ -1793,6 +1794,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser if ($resultFetch < 0) { setEventMessages($product->error, $product->errors, 'errors'); } else { + print $product->getNomUrl(1); } } From ebda8d52f016c2d8db259d8e89dbcdd5d805d92b Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Mon, 24 Jan 2022 22:30:25 +0000 Subject: [PATCH 010/826] Fixing style errors. --- htdocs/projet/tasks/time.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index e4ad83e8129..a17e7c2e6be 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -285,7 +285,6 @@ if (($action == 'updateline' || $action == 'updatesplitline') && !$cancel && $us } $result = $object->addTimeSpent($user); - } else { $object->fetch($id, $ref); @@ -1794,7 +1793,6 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser if ($resultFetch < 0) { setEventMessages($product->error, $product->errors, 'errors'); } else { - print $product->getNomUrl(1); } } From bb5f5bc18c361637ce037bb66aec892414d27d91 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Mon, 24 Jan 2022 23:30:41 +0100 Subject: [PATCH 011/826] merge --- htdocs/projet/tasks/time.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index e4ad83e8129..d82f0d6ac66 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -285,7 +285,6 @@ if (($action == 'updateline' || $action == 'updatesplitline') && !$cancel && $us } $result = $object->addTimeSpent($user); - } else { $object->fetch($id, $ref); @@ -391,7 +390,6 @@ if ($action == 'confirm_generateinvoice') { $fuser = new User($db); $db->begin(); - //TODO produit du temps passé ou produt id $idprod = GETPOST('productid', 'int'); $generateinvoicemode = GETPOST('generateinvoicemode', 'string'); $invoiceToUse = GETPOST('invoiceid', 'int'); @@ -1196,7 +1194,6 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser $form->select_produits('', 'productid', '1', 0, $projectstatic->thirdparty->price_level, 1, 2, '', 0, array(), $projectstatic->thirdparty->id, 'None', 0, 'maxwidth500'); print ''; print ''; - //TODO : Use product of time affect } print ''; @@ -1794,7 +1791,6 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser if ($resultFetch < 0) { setEventMessages($product->error, $product->errors, 'errors'); } else { - print $product->getNomUrl(1); } } From 7880d8f0400fd56fadc917ddc971c93f2b7d4785 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Fri, 4 Mar 2022 10:04:41 +0100 Subject: [PATCH 012/826] fix double call --- htdocs/projet/tasks/time.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index b0ba6b1f24f..153683442e9 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -283,8 +283,6 @@ if (($action == 'updateline' || $action == 'updatesplitline') && !$cancel && $us $error++; } } - - $result = $object->addTimeSpent($user); } else { $object->fetch($id, $ref); From 6c3ea310dca2d935e87e3bd3c0da974abc07e23f Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Fri, 18 Mar 2022 09:12:34 +0100 Subject: [PATCH 013/826] align css --- htdocs/projet/tasks/time.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index 153683442e9..de1c1455002 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -1603,7 +1603,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser print_liste_field_titre($arrayfields['t.task_duration']['label'], $_SERVER['PHP_SELF'], 't.task_duration', '', $param, '', $sortfield, $sortorder, 'right '); } if (!empty($arrayfields['t.fk_product']['checked'])) { - print_liste_field_titre($arrayfields['t.fk_product']['label'], $_SERVER['PHP_SELF'], 't.fk_product', '', $param, '', $sortfield, $sortorder, 'right '); + print_liste_field_titre($arrayfields['t.fk_product']['label'], $_SERVER['PHP_SELF'], 't.fk_product', '', $param, '', $sortfield, $sortorder); } if (!empty($arrayfields['value']['checked'])) { From 8152a728a866c568baf769db56ff09ef36b8a9e3 Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Tue, 22 Mar 2022 11:42:15 +0100 Subject: [PATCH 014/826] Fix : filemanagement in ecm and medias --- htdocs/core/class/html.formfile.class.php | 8 ++++---- htdocs/core/tpl/filemanager.tpl.php | 18 ++++++++++++++++-- htdocs/ecm/class/htmlecm.form.class.php | 4 ++-- htdocs/ecm/dir_add_card.php | 2 +- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/htdocs/core/class/html.formfile.class.php b/htdocs/core/class/html.formfile.class.php index 6c4ff6e30f1..7117b2b8a2a 100644 --- a/htdocs/core/class/html.formfile.class.php +++ b/htdocs/core/class/html.formfile.class.php @@ -1328,7 +1328,7 @@ class FormFile if ($file['name'] != '.' && $file['name'] != '..' && !preg_match('/\.meta$/i', $file['name'])) { - if ($filearray[$key]['rowid'] > 0) { + if (!empty($filearray[$key]['rowid']) && $filearray[$key]['rowid'] > 0) { $lastrowid = $filearray[$key]['rowid']; } $filepath = $relativepath.$file['name']; @@ -1337,8 +1337,8 @@ class FormFile $nboflines++; print ''."\n"; // Do we have entry into database ? - print ''."\n"; - print ''; + print ''."\n"; + print ''; // File name print ''; @@ -1481,7 +1481,7 @@ class FormFile if ($permtoeditline) { // Link to resize $moreparaminurl = ''; - if ($object->id > 0) { + if (!empty($object->id) && $object->id > 0) { $moreparaminurl = '&id='.$object->id; } elseif (GETPOST('website', 'alpha')) { $moreparaminurl = '&website='.GETPOST('website', 'alpha'); diff --git a/htdocs/core/tpl/filemanager.tpl.php b/htdocs/core/tpl/filemanager.tpl.php index e776388ac53..5c40e56ff10 100644 --- a/htdocs/core/tpl/filemanager.tpl.php +++ b/htdocs/core/tpl/filemanager.tpl.php @@ -51,7 +51,7 @@ if ($module == 'medias') { $permtoupload = ($user->rights->mailing->creer || $user->rights->website->write); $showroot = 1; } - +$section = 0; // Confirm remove file (for non javascript users) @@ -102,12 +102,26 @@ $('#acreatedir').on('click', function() { try{ section_dir = $('.directory.expanded')[$('.directory.expanded').length-1].children[0].rel; section = $('.directory.expanded')[$('.directory.expanded').length-1].children[0].id.split('_')[2]; + catParent = "; +if ($module == 'ecm') { + print "section;"; +} else { + print "section_dir.substring(0, section_dir.length - 1);"; +} +print " } catch{ section_dir = '/'; section = 0; + catParent = "; +if ($module == 'ecm') { + print "section;"; +} else { + print "section_dir;"; +} +print " } console.log('We click to create a new directory, we set current section_dir='+section_dir+' into href url of button acreatedir'); - $('#acreatedir').attr('href', $('#acreatedir').attr('href')+'§ion_dir='+encodeURI(section_dir)+'§ion='+encodeURI(section)); + $('#acreatedir').attr('href', $('#acreatedir').attr('href')+'%26section_dir%3D'+encodeURI(section_dir)+'%26section%3D'+encodeURI(section)+'§ion_dir='+encodeURI(section_dir)+'§ion='+encodeURI(section)+'&catParent='+encodeURI(catParent)); console.log($('#acreatedir').attr('href')); }); $('#agenerateimgwebp').on('click', function() { diff --git a/htdocs/ecm/class/htmlecm.form.class.php b/htdocs/ecm/class/htmlecm.form.class.php index 623d626935d..b93d3d563fb 100644 --- a/htdocs/ecm/class/htmlecm.form.class.php +++ b/htdocs/ecm/class/htmlecm.form.class.php @@ -80,7 +80,7 @@ class FormEcm $cate_arbo = dol_dir_list($path, 'directories', 1, '', array('(\.meta|_preview.*\.png)$', '^\.'), 'relativename', SORT_ASC); } - $output = ''; if (is_array($cate_arbo)) { if (!count($cate_arbo)) { $output .= ''; @@ -100,7 +100,7 @@ class FormEcm } } $output .= ''; - $output .= ajax_combobox($select_name); + //$output .= ajax_combobox($select_name); $output .= "\n"; return $output; } diff --git a/htdocs/ecm/dir_add_card.php b/htdocs/ecm/dir_add_card.php index d7de6acc727..a6c980e5908 100644 --- a/htdocs/ecm/dir_add_card.php +++ b/htdocs/ecm/dir_add_card.php @@ -230,7 +230,7 @@ if ($action == 'create') { print ''; // Label - print ''."\n"; + print ''."\n"; print ''; print ''; - //auto APPROVAL ON CREATE + //auto validation ON CREATE print ''."\n"; From bf10e8f68771f9e125b76d09a248bd6a6244b98f Mon Sep 17 00:00:00 2001 From: jpb Date: Wed, 8 Jun 2022 17:08:05 +0200 Subject: [PATCH 040/826] add js behaviour on auvalidation and automail remove todo --- htdocs/holiday/card_group.php | 95 +++++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 37 deletions(-) diff --git a/htdocs/holiday/card_group.php b/htdocs/holiday/card_group.php index 8ffe0f3e1fc..898d9f53be8 100644 --- a/htdocs/holiday/card_group.php +++ b/htdocs/holiday/card_group.php @@ -318,8 +318,8 @@ if (empty($reshook)) { setEventMessages($object->error, $object->errors, 'errors'); $error++; } else { - // AUTO APPROUVAL /VALIDATED - //@TODO changer le nom si approuved / validated + + //@TODO changer le nom si validated if ($autoValidation) { $htemp = new Holiday($db); $htemp->fetch($result); @@ -332,10 +332,11 @@ if (empty($reshook)) { $error++; } // we can auto send mail if we are in auto validation behavior - //@todo jquery disable if checkbox autovalidation unchecked + if ($AutoSendMail && !$error) { // send a mail to the user - sendMail($result, $cancreate, $now, $autoValidation); + $returnSendMail = sendMail($result, $cancreate, $now, $autoValidation); + if (!empty($returnSendMail->msg)) setEventMessage($returnSendMail->msg,$returnSendMail->style); } } } @@ -413,6 +414,13 @@ if ((empty($id) && empty($ref)) || $action == 'create' || $action == 'add') { print ''."\n"; @@ -448,12 +465,8 @@ if ((empty($id) && empty($ref)) || $action == 'create' || $action == 'add') { print ''."\n"; print ''."\n"; - - print dol_get_fiche_head(); - //print ''.$langs->trans('DelayToRequestCP',$object->getConfCP('delayForRequest')).'

'; - print '
'.$langs->trans("Label").'
'.$langs->trans("Label").'
'.$langs->trans("AddIn").''; print $formecm->selectAllSections((GETPOST("catParent", 'alpha') ? GETPOST("catParent", 'alpha') : $ecmdir->fk_parent), 'catParent', $module); From b18eac6c75708e6d1e2869cd3c99936440225932 Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Tue, 22 Mar 2022 14:44:11 +0100 Subject: [PATCH 015/826] remove tests lines --- htdocs/ecm/class/htmlecm.form.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/ecm/class/htmlecm.form.class.php b/htdocs/ecm/class/htmlecm.form.class.php index b93d3d563fb..623d626935d 100644 --- a/htdocs/ecm/class/htmlecm.form.class.php +++ b/htdocs/ecm/class/htmlecm.form.class.php @@ -80,7 +80,7 @@ class FormEcm $cate_arbo = dol_dir_list($path, 'directories', 1, '', array('(\.meta|_preview.*\.png)$', '^\.'), 'relativename', SORT_ASC); } - $output = ''; if (is_array($cate_arbo)) { if (!count($cate_arbo)) { $output .= ''; @@ -100,7 +100,7 @@ class FormEcm } } $output .= ''; - //$output .= ajax_combobox($select_name); + $output .= ajax_combobox($select_name); $output .= "\n"; return $output; } From f17d09743ff2e9d5d88492671f091f56e49b515e Mon Sep 17 00:00:00 2001 From: lvessiller Date: Tue, 12 Apr 2022 16:40:59 +0200 Subject: [PATCH 016/826] NEW product categories filter on inventory list --- htdocs/product/inventory/list.php | 69 +++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/htdocs/product/inventory/list.php b/htdocs/product/inventory/list.php index c4548b3aa66..a2b9fdfa194 100644 --- a/htdocs/product/inventory/list.php +++ b/htdocs/product/inventory/list.php @@ -27,6 +27,9 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; require_once DOL_DOCUMENT_ROOT.'/product/inventory/class/inventory.class.php'; +if (!empty($conf->categorie->enabled)) { + require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; +} // Load translation files required by the page $langs->loadLangs(array("stocks", "other")); @@ -88,6 +91,13 @@ foreach ($object->fields as $key => $val) { $search[$key.'_dtend'] = dol_mktime(23, 59, 59, GETPOST('search_'.$key.'_dtendmonth', 'int'), GETPOST('search_'.$key.'_dtendday', 'int'), GETPOST('search_'.$key.'_dtendyear', 'int')); } } +$searchCategoryProductOperator = 0; +if (GETPOSTISSET('formfilteraction')) { + $searchCategoryProductOperator = GETPOST('search_category_product_operator', 'int'); +} elseif (!empty($conf->global->MAIN_SEARCH_CAT_OR_BY_DEFAULT)) { + $searchCategoryProductOperator = $conf->global->MAIN_SEARCH_CAT_OR_BY_DEFAULT; +} +$searchCategoryProductList = GETPOST('search_category_product_list', 'array'); // List of fields to search into when doing a "search in all" $fieldstosearchall = array(); @@ -166,6 +176,7 @@ if (empty($reshook)) { $search[$key.'_dtend'] = ''; } } + $searchCategoryProductList = array(); $toselect = array(); $search_array_options = array(); } @@ -259,6 +270,50 @@ foreach ($search as $key => $val) { if ($search_all) { $sql .= natural_search(array_keys($fieldstosearchall), $search_all); } +$searchCategoryProductSqlList = array(); +if ($searchCategoryProductOperator == 1) { + $existsCategoryProductList = array(); + foreach ($searchCategoryProductList as $searchCategoryProduct) { + if (intval($searchCategoryProduct) == -2) { + $sqlCategoryProductNotExists = " NOT EXISTS ("; + $sqlCategoryProductNotExists .= " SELECT cp.fk_product"; + $sqlCategoryProductNotExists .= " FROM ".$db->prefix()."categorie_product AS cp"; + $sqlCategoryProductNotExists .= " WHERE cp.fk_product = t.fk_product"; + $sqlCategoryProductNotExists .= " )"; + $searchCategoryProductSqlList[] = $sqlCategoryProductNotExists; + } elseif (intval($searchCategoryProduct) > 0) { + $existsCategoryProductList[] = $db->escape($searchCategoryProduct); + } + } + if (!empty($existsCategoryProductList)) { + $sqlCategoryProductExists = " EXISTS ("; + $sqlCategoryProductExists .= " SELECT cp.fk_product"; + $sqlCategoryProductExists .= " FROM ".$db->prefix()."categorie_product AS cp"; + $sqlCategoryProductExists .= " WHERE cp.fk_product = t.fk_product"; + $sqlCategoryProductExists .= " AND cp.fk_categorie IN (".implode(",", $existsCategoryProductList).")"; + $sqlCategoryProductExists .= " )"; + $searchCategoryProductSqlList[] = $sqlCategoryProductExists; + } + if (!empty($searchCategoryProductSqlList)) { + $sql .= " AND (".implode(' OR ', $searchCategoryProductSqlList).")"; + } +} else { + foreach ($searchCategoryProductList as $searchCategoryProduct) { + if (intval($searchCategoryProduct) == -2) { + $sqlCategoryProductNotExists = " NOT EXISTS ("; + $sqlCategoryProductNotExists .= " SELECT cp.fk_product"; + $sqlCategoryProductNotExists .= " FROM ".$db->prefix()."categorie_product AS cp"; + $sqlCategoryProductNotExists .= " WHERE cp.fk_product = t.fk_product"; + $sqlCategoryProductNotExists .= " )"; + $searchCategoryProductSqlList[] = $sqlCategoryProductNotExists; + } elseif (intval($searchCategoryProduct) > 0) { + $searchCategoryProductSqlList[] = "t.fk_product IN (SELECT fk_product FROM ".$db->prefix()."categorie_product WHERE fk_categorie = ".((int) $searchCategoryProduct).")"; + } + } + if (!empty($searchCategoryProductSqlList)) { + $sql .= " AND (".implode(' AND ', $searchCategoryProductSqlList).")"; + } +} //$sql.= dolSqlDateFilter("t.field", $search_xxxday, $search_xxxmonth, $search_xxxyear); // Add where from extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; @@ -348,6 +403,9 @@ foreach ($search as $key => $val) { if ($optioncss != '') { $param .= '&optioncss='.urlencode($optioncss); } +foreach ($searchCategoryProductList as $searchCategoryProduct) { + $param .= "&search_category_product_list[]=".urlencode($searchCategoryProduct); +} // Add $param from extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; // Add $param from hooks @@ -405,6 +463,17 @@ $moreforfilter = ''; $moreforfilter.= $langs->trans('MyFilter') . ': '; $moreforfilter.= '';*/ +// Filter on categories +if (!empty($conf->categorie->enabled) && $user->rights->categorie->lire) { + $moreforfilter .= '
'; + $moreforfilter .= img_picto($langs->trans('Categories'), 'category', 'class="pictofixedwidth"'); + $categoriesProductArr = $form->select_all_categories(Categorie::TYPE_PRODUCT, '', '', 64, 0, 1); + $categoriesProductArr[-2] = '- '.$langs->trans('NotCategorized').' -'; + $moreforfilter .= Form::multiselectarray('search_category_product_list', $categoriesProductArr, $searchCategoryProductList, 0, 0, 'minwidth300'); + $moreforfilter .= ' '; + $moreforfilter .= '
'; +} + $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook if (empty($reshook)) { From 4510af67478628bd7b36ac69a5a91ac785944596 Mon Sep 17 00:00:00 2001 From: lvessiller Date: Tue, 12 Apr 2022 16:59:46 +0200 Subject: [PATCH 017/826] FIX travis SQL syntax --- htdocs/product/inventory/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/product/inventory/list.php b/htdocs/product/inventory/list.php index a2b9fdfa194..7e795d821bf 100644 --- a/htdocs/product/inventory/list.php +++ b/htdocs/product/inventory/list.php @@ -290,7 +290,7 @@ if ($searchCategoryProductOperator == 1) { $sqlCategoryProductExists .= " SELECT cp.fk_product"; $sqlCategoryProductExists .= " FROM ".$db->prefix()."categorie_product AS cp"; $sqlCategoryProductExists .= " WHERE cp.fk_product = t.fk_product"; - $sqlCategoryProductExists .= " AND cp.fk_categorie IN (".implode(",", $existsCategoryProductList).")"; + $sqlCategoryProductExists .= " AND cp.fk_categorie IN (".$db->sanitize(implode(',', $existsCategoryProductList)).")"; $sqlCategoryProductExists .= " )"; $searchCategoryProductSqlList[] = $sqlCategoryProductExists; } From 1435e2666e8d698b9b7f1cbabc75306e2b62bea8 Mon Sep 17 00:00:00 2001 From: lvessiller Date: Tue, 12 Apr 2022 17:18:39 +0200 Subject: [PATCH 018/826] FIX reload travis From 902301659b47c827b76da586d9de48f9d14684da Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Wed, 13 Apr 2022 09:31:30 +0200 Subject: [PATCH 019/826] finish invoice per product per line --- htdocs/compta/facture/class/facture.class.php | 1 + htdocs/langs/en_US/projects.lang | 3 +- htdocs/product/class/product.class.php | 37 ++++++++ htdocs/projet/tasks/time.php | 87 +++++++++++++------ 4 files changed, 99 insertions(+), 29 deletions(-) diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 7ad0a8ed4bc..d0089e6f1e7 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -3500,6 +3500,7 @@ class Facture extends CommonInvoice return -2; } } else { + $this->errors[]='status of invoice must be Draft to allow use of ->addline()'; dol_syslog(get_class($this)."::addline status of invoice must be Draft to allow use of ->addline()", LOG_ERR); return -3; } diff --git a/htdocs/langs/en_US/projects.lang b/htdocs/langs/en_US/projects.lang index 1e0ed42d3e3..645171e8ac7 100644 --- a/htdocs/langs/en_US/projects.lang +++ b/htdocs/langs/en_US/projects.lang @@ -259,7 +259,7 @@ TimeSpentInvoiced=Time spent billed TimeSpentForIntervention=Time spent TimeSpentForInvoice=Time spent OneLinePerUser=One line per user -ServiceToUseOnLines=Service to use on lines +ServiceToUseOnLines=Service to use on lines by default InvoiceGeneratedFromTimeSpent=Invoice %s has been generated from time spent on project InterventionGeneratedFromTimeSpent=Intervention %s has been generated from time spent on project ProjectBillTimeDescription=Check if you enter timesheet on tasks of project AND you plan to generate invoice(s) from the timesheet to bill the customer of the project (do not check if you plan to create invoice that is not based on entered timesheets). Note: To generate invoice, go on tab 'Time spent' of the project and select lines to include. @@ -276,6 +276,7 @@ NewInter=New intervention OneLinePerTask=One line per task OneLinePerPeriod=One line per period OneLinePerTimeSpentLine=One line for each time spent declaration +OneLinePerTimeSpentLineProduct=One line for each time spent declaration with product defined AddDetailDateAndDuration=With date and duration into line description RefTaskParent=Ref. Parent Task ProfitIsCalculatedWith=Profit is calculated using diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 365b5e90916..fb42b6887f2 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -6058,6 +6058,43 @@ class Product extends CommonObject dol_print_error($this->db); } } + + + /** + * Return the duration in Hours of a service base on duration fields + * @return int -1 KO, >= 0 is the duration in hours + */ + public function getProductDurationHours() + { + global $langs; + + if (empty($this->duration_value)) { + $this->errors[]='ErrorDurationForServiceNotDefinedCantCalculateHourlyPrice'; + return -1; + } + + if ($this->duration_unit == 'i') { + $prodDurationHours = 1. / 60; + } + if ($this->duration_unit == 'h') { + $prodDurationHours = 1.; + } + if ($this->duration_unit == 'd') { + $prodDurationHours = 24.; + } + if ($this->duration_unit == 'w') { + $prodDurationHours = 24. * 7; + } + if ($this->duration_unit == 'm') { + $prodDurationHours = 24. * 30; + } + if ($this->duration_unit == 'y') { + $prodDurationHours = 24. * 365; + } + $prodDurationHours *= $this->duration_value; + + return $prodDurationHours; + } } diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index 34333b91632..b201feef622 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -392,36 +392,21 @@ if ($action == 'confirm_generateinvoice') { $generateinvoicemode = GETPOST('generateinvoicemode', 'string'); $invoiceToUse = GETPOST('invoiceid', 'int'); - $prodDurationHours = 1.0; + $prodDurationHoursBase = 1.0; if ($idprod > 0) { $tmpproduct->fetch($idprod); + if ($result<0) { + $error++; + setEventMessages($tmpproduct->error, $tmpproduct->errors, 'errors'); + } - if (empty($tmpproduct->duration_value)) { + $prodDurationHoursBase=$tmpproduct->getProductDurationHours(); + if ($prodDurationHoursBase<0) { $error++; $langs->load("errors"); - setEventMessages($langs->trans("ErrorDurationForServiceNotDefinedCantCalculateHourlyPrice"), null, 'errors'); + setEventMessages(null, $tmpproduct->errors, 'errors'); } - if ($tmpproduct->duration_unit == 'i') { - $prodDurationHours = 1. / 60; - } - if ($tmpproduct->duration_unit == 'h') { - $prodDurationHours = 1.; - } - if ($tmpproduct->duration_unit == 'd') { - $prodDurationHours = 24.; - } - if ($tmpproduct->duration_unit == 'w') { - $prodDurationHours = 24. * 7; - } - if ($tmpproduct->duration_unit == 'm') { - $prodDurationHours = 24. * 30; - } - if ($tmpproduct->duration_unit == 'y') { - $prodDurationHours = 24. * 365; - } - $prodDurationHours *= $tmpproduct->duration_value; - $dataforprice = $tmpproduct->getSellPrice($mysoc, $projectstatic->thirdparty, 0); $pu_ht = empty($dataforprice['pu_ht']) ? 0 : $dataforprice['pu_ht']; @@ -429,7 +414,7 @@ if ($action == 'confirm_generateinvoice') { $localtax1 = $dataforprice['localtax1']; $localtax2 = $dataforprice['localtax2']; } else { - $prodDurationHours = 1; + $prodDurationHoursBase = 1; $pu_ht = 0; $txtva = get_default_tva($mysoc, $projectstatic->thirdparty); @@ -476,7 +461,7 @@ if ($action == 'confirm_generateinvoice') { } // Add lines - $lineid = $tmpinvoice->addline($langs->trans("TimeSpentForInvoice", $username).' : '.$qtyhourtext, $pu_ht, round($qtyhour / $prodDurationHours, 2), $txtva, $localtax1, $localtax2, ($idprod > 0 ? $idprod : 0)); + $lineid = $tmpinvoice->addline($langs->trans("TimeSpentForInvoice", $username).' : '.$qtyhourtext, $pu_ht, round($qtyhour / $prodDurationHoursBase, 2), $txtva, $localtax1, $localtax2, ($idprod > 0 ? $idprod : 0)); // Update lineid into line of timespent $sql = 'UPDATE '.MAIN_DB_PREFIX.'projet_task_time SET invoice_line_id = '.((int) $lineid).', invoice_id = '.((int) $tmpinvoice->id); @@ -488,8 +473,9 @@ if ($action == 'confirm_generateinvoice') { break; } } - } elseif ($generateinvoicemode == 'onelineperperiod') { // One line for each time spent line + } elseif ($generateinvoicemode == 'onelineperperiod' || $generateinvoicemode == 'onelineperperiodproduct') { // One line for each time spent line $arrayoftasks = array(); + $product_data_cache = array(); $withdetail=GETPOST('detail_time_duration', 'alpha'); foreach ($toselect as $key => $value) { // Get userid, timepent @@ -519,6 +505,7 @@ if ($action == 'confirm_generateinvoice') { $arrayoftasks[$object->timespent_id]['note'] .= ' - '.$langs->trans("Duration").': '.convertSecondToTime($object->timespent_duration, 'all', $conf->global->MAIN_DURATION_OF_WORKDAY); } $arrayoftasks[$object->timespent_id]['user'] = $object->timespent_fk_user; + $arrayoftasks[$object->timespent_id]['fk_product'] = $object->timespent_fk_product; } foreach ($arrayoftasks as $timespent_id => $value) { @@ -534,7 +521,50 @@ if ($action == 'confirm_generateinvoice') { } // Add lines - $lineid = $tmpinvoice->addline($value['note'], $pu_ht, round($qtyhour / $prodDurationHours, 2), $txtva, $localtax1, $localtax2, ($idprod > 0 ? $idprod : 0)); + $prodDurationHours = $prodDurationHoursBase; + $idprodline=$idprod; + $pu_htline = $pu_ht; + $txtvaline = $txtva; + $localtax1line = $localtax1; + $localtax2line = $localtax2; + + + if ($generateinvoicemode == 'onelineperperiodproduct' && !empty($value['fk_product']) && $value['fk_product']!==$idprod) { + if (!array_key_exists($value['fk_product'], $product_data_cache)) { + $result = $tmpproduct->fetch($value['fk_product']); + if ($result < 0) { + $error++; + setEventMessages($tmpproduct->error, $tmpproduct->errors, 'errors'); + } + $prodDurationHours = $tmpproduct->getProductDurationHours(); + if ($prodDurationHours < 0) { + $error++; + $langs->load("errors"); + setEventMessages(null, $tmpproduct->errors, 'errors'); + } + + $dataforprice = $tmpproduct->getSellPrice($mysoc, $projectstatic->thirdparty, 0); + + $pu_htline = empty($dataforprice['pu_ht']) ? 0 : $dataforprice['pu_ht']; + $txtvaline = $dataforprice['tva_tx']; + $localtax1line = $dataforprice['localtax1']; + $localtax2line = $dataforprice['localtax2']; + + $product_data_cache[$value['fk_product']] = array('duration'=>$prodDurationHours,'dataforprice'=>$dataforprice); + } else { + $prodDurationHours = $product_data_cache[$value['fk_product']]['duration']; + $pu_htline = empty($product_data_cache[$value['fk_product']]['dataforprice']['pu_ht']) ? 0 : $product_data_cache[$value['fk_product']]['dataforprice']['pu_ht']; + $txtvaline = $product_data_cache[$value['fk_product']]['dataforprice']['tva_tx']; + $localtax1line = $product_data_cache[$value['fk_product']]['dataforprice']['localtax1']; + $localtax2line = $product_data_cache[$value['fk_product']]['dataforprice']['localtax2']; + } + $idprodline=$value['fk_product']; + } + $lineid = $tmpinvoice->addline($value['note'], $pu_htline, round($qtyhour / $prodDurationHours, 2), $txtvaline, $localtax1line, $localtax2line, ($idprodline > 0 ? $idprodline : 0)); + if ($lineid<0) { + $error++; + setEventMessages(null, $tmpinvoice->errors, 'errors'); + } //var_dump($lineid);exit; // Update lineid into line of timespent @@ -1178,6 +1208,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser 'onelineperuser'=>'OneLinePerUser', 'onelinepertask'=>'OneLinePerTask', 'onelineperperiod'=>'OneLinePerTimeSpentLine', + 'onelineperperiodproduct'=>'OneLinePerTimeSpentLineProduct', ); print $form->selectarray('generateinvoicemode', $tmparray, 'onelineperuser', 0, 0, 0, '', 1); print "\n".''."\n"; + + + // Formulaire de demande + print '
'."\n"; + print ''."\n"; + print ''."\n"; + + + + print dol_get_fiche_head(); + + //print ''.$langs->trans('DelayToRequestCP',$object->getConfCP('delayForRequest')).'

'; + + print ''; + print ''; + + // groupe + print ''; + print ''; + + print ''; + + // users + print ''; + print ''; + print ''; + + + + // Type + print ''; + print ''; + print ''; + print ''; + + // Date start + print ''; + print ''; + print ''; + print ''; + + // Date end + print ''; + print ''; + print ''; + print ''; + + // Approver + print ''; + print ''; + print ''; + print ''; + + //auto APPROVAL ON CREATE + print ''."\n"; + + + //no auto SEND MAIL + print ''."\n"; + + // Description + print ''; + print ''; + print ''; + + // Other attributes + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_add.tpl.php'; + + print ''; + print '
'.$langs->trans("groups"); + + print ''; + //@todo ajouter entity ! + $sql =' SELECT rowid, nom from '.MAIN_DB_PREFIX.'usergroup '; + + $resql = $db->query($sql); + $Tgroup = array(); + while ($obj = $db->fetch_object($resql)){ + $Tgroup[$obj->rowid] = $obj->nom; + } + print $form->multiselectarray('groups', $Tgroup, GETPOST('groups', 'array'), '', 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0); + + print '
'.$langs->trans("users").''; + + $sql = ' SELECT DISTINCT u.rowid,u.lastname,u.firstname from '.MAIN_DB_PREFIX.'user as u'; + $sql .= ' WHERE 1=1 '; + $sql .= !empty($morefilter) ? $morefilter : ''; + + + if ($cancreate && !$cancreateall) { + + }else{ + //$sql .= ' AND u.fk_user = '.$user->id; + //$sql .= ' OR u.rowid ='.$user->id; + } + + $resql = $db->query($sql); + if ($resql){ + while ($obj = $db->fetch_object($resql)){ + $userlist[$obj->rowid] = $obj->firstname . ' '. $obj->lastname; + } + } + + print img_picto('', 'users') . $form->multiselectarray('users', $userlist, GETPOST('users', 'array'), '', 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0); + print '
'.$langs->trans("Type").''; + $typeleaves = $object->getTypes(1, -1); + $arraytypeleaves = array(); + foreach ($typeleaves as $key => $val) { + $labeltoshow = ($langs->trans($val['code']) != $val['code'] ? $langs->trans($val['code']) : $val['label']); + $labeltoshow .= ($val['delay'] > 0 ? ' ('.$langs->trans("NoticePeriod").': '.$val['delay'].' '.$langs->trans("days").')' : ''); + $arraytypeleaves[$val['rowid']] = $labeltoshow; + } + print $form->selectarray('type', $arraytypeleaves, (GETPOST('type', 'alpha') ?GETPOST('type', 'alpha') : ''), 1, 0, 0, '', 0, 0, 0, '', '', true); + if ($user->admin) { + print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); + } + print '
'; + print $form->textwithpicto($langs->trans("DateDebCP"), $langs->trans("FirstDayOfHoliday")); + print ''; + // Si la demande ne vient pas de l'agenda + if (!GETPOST('date_debut_')) { + print $form->selectDate(-1, 'date_debut_', 0, 0, 0, '', 1, 1); + } else { + $tmpdate = dol_mktime(0, 0, 0, GETPOST('date_debut_month', 'int'), GETPOST('date_debut_day', 'int'), GETPOST('date_debut_year', 'int')); + print $form->selectDate($tmpdate, 'date_debut_', 0, 0, 0, '', 1, 1); + } + print '     '; + print $form->selectarray('starthalfday', $listhalfday, (GETPOST('starthalfday', 'alpha') ?GETPOST('starthalfday', 'alpha') : 'morning')); + print '
'; + print $form->textwithpicto($langs->trans("DateFinCP"), $langs->trans("LastDayOfHoliday")); + print ''; + if (!GETPOST('date_fin_')) { + print $form->selectDate(-1, 'date_fin_', 0, 0, 0, '', 1, 1); + } else { + $tmpdate = dol_mktime(0, 0, 0, GETPOST('date_fin_month', 'int'), GETPOST('date_fin_day', 'int'), GETPOST('date_fin_year', 'int')); + print $form->selectDate($tmpdate, 'date_fin_', 0, 0, 0, '', 1, 1); + } + print '     '; + print $form->selectarray('endhalfday', $listhalfday, (GETPOST('endhalfday', 'alpha') ?GETPOST('endhalfday', 'alpha') : 'afternoon')); + print '
'.$langs->trans("ReviewedByCP").''; + + $object = new Holiday($db); + $include_users = $object->fetch_users_approver_holiday(); + if (empty($include_users)) { + print img_warning().' '.$langs->trans("NobodyHasPermissionToValidateHolidays"); + } else { + // Defined default approver (the forced approved of user or the supervisor if no forced value defined) + // Note: This use will be set only if the deinfed approvr has permission to approve so is inside include_users + $defaultselectuser = (empty($user->fk_user_holiday_validator) ? $user->fk_user : $user->fk_user_holiday_validator); + if (!empty($conf->global->HOLIDAY_DEFAULT_VALIDATOR)) { + $defaultselectuser = $conf->global->HOLIDAY_DEFAULT_VALIDATOR; // Can force default approver + } + if (GETPOST('valideur', 'int') > 0) { + $defaultselectuser = GETPOST('valideur', 'int'); + } + $s = $form->select_dolusers($defaultselectuser, "valideur", 1, '', 0, $include_users, '', '0,'.$conf->entity, 0, 0, '', 0, '', 'minwidth200 maxwidth500'); + print img_picto('', 'user').$form->textwithpicto($s, $langs->trans("AnyOtherInThisListCanValidate")); + } + + + print '
'.$langs->trans("AutoApprovalOnCreate").''; + print ''; + print '
'.$langs->trans("AutoSendMail").''; + print ''; + print '
'.$langs->trans("DescCP").''; + $doleditor = new DolEditor('description', GETPOST('description', 'restricthtml'), '', 80, 'dolibarr_notes', 'In', 0, false, empty($conf->fckeditor->enabled) ? false : $conf->fckeditor->enabled, ROWS_3, '90%'); + print $doleditor->Create(1); + print '
'; + + print dol_get_fiche_end(); + + print $form->buttonsSaveCancel("SendRequestCollectiveCP"); + + print ''."\n"; + } +} else { + if ($error) { + print '
'; + print $error; + print '

'; + print '
'; + } +} + +// End of page +llxFooter(); + +if (is_object($db)) { + $db->close(); +} + +// automatic send mail +function sendMail ($id, $cancreate, $now){ + + global $db, $user, $conf, $langs; + + $object = new Holiday($db); + + $result = $object->fetch($id); + + if ($result){ + // If draft and owner of leave + if ($object->statut == Holiday::STATUS_DRAFT && $cancreate) { + $object->oldcopy = dol_clone($object); + + $object->statut = Holiday::STATUS_VALIDATED; + + $verif = $object->validate($user); + + // If no SQL error, we redirect to the request form + if ($verif > 0) { + // To + $destinataire = new User($db); + $destinataire->fetch($object->fk_validator); + $emailTo = $destinataire->email; + + if (!$emailTo) { + dol_syslog("Expected validator has no email, so we redirect directly to finished page without sending email"); + header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); + exit; + } + + // From + $expediteur = new User($db); + $expediteur->fetch($object->fk_user); + //$emailFrom = $expediteur->email; Email of user can be an email into another company. Sending will fails, we must use the generic email. + $emailFrom = $conf->global->MAIN_MAIL_EMAIL_FROM; + + // Subject + $societeName = $conf->global->MAIN_INFO_SOCIETE_NOM; + if (!empty($conf->global->MAIN_APPLICATION_TITLE)) { + $societeName = $conf->global->MAIN_APPLICATION_TITLE; + } + + $subject = $societeName." - ".$langs->transnoentitiesnoconv("HolidaysToValidate"); + + // Content + $message = "

".$langs->transnoentitiesnoconv("Hello")." ".$destinataire->firstname.",

\n"; + + $message .= "

".$langs->transnoentities("HolidaysToValidateBody")."

\n"; + + + // option to warn the validator in case of too short delay + if (empty($conf->global->HOLIDAY_HIDE_APPROVER_ABOUT_TOO_LOW_DELAY)) { + $delayForRequest = 0; // TODO Set delay depending of holiday leave type + if ($delayForRequest) { + $nowplusdelay = dol_time_plus_duree($now, $delayForRequest, 'd'); + + if ($object->date_debut < $nowplusdelay) { + $message = "

".$langs->transnoentities("HolidaysToValidateDelay", $delayForRequest)."

\n"; + } + } + } + + // option to notify the validator if the balance is less than the request + if (empty($conf->global->HOLIDAY_HIDE_APPROVER_ABOUT_NEGATIVE_BALANCE)) { + $nbopenedday = num_open_day($object->date_debut_gmt, $object->date_fin_gmt, 0, 1, $object->halfday); + + if ($nbopenedday > $object->getCPforUser($object->fk_user, $object->fk_type)) { + $message .= "

".$langs->transnoentities("HolidaysToValidateAlertSolde")."

\n"; + } + } + + $link = dol_buildpath("/holiday/card.php", 3) . '?id='.$object->id; + + $message .= "
    "; + $message .= "
  • ".$langs->transnoentitiesnoconv("Name")." : ".dolGetFirstLastname($expediteur->firstname, $expediteur->lastname)."
  • \n"; + $message .= "
  • ".$langs->transnoentitiesnoconv("Period")." : ".dol_print_date($object->date_debut, 'day')." ".$langs->transnoentitiesnoconv("To")." ".dol_print_date($object->date_fin, 'day')."
  • \n"; + $message .= "
  • ".$langs->transnoentitiesnoconv("Link").' : '.$link."
  • \n"; + $message .= "
\n"; + + $trackid = 'leav'.$object->id; + + $mail = new CMailFile($subject, $emailTo, $emailFrom, $message, array(), array(), array(), '', '', 0, 1, '', '', $trackid); + + // Sending the email + $result = $mail->sendfile(); + + if (!$result) { + setEventMessages($mail->error, $mail->errors, 'warnings'); + $action = ''; + } else { + header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); + exit; + } + } else { + setEventMessages($object->error, $object->errors, 'errors'); + $action = ''; + } + } + }else{ + setEventMessage($langs->trans('ErrorloadUserOnSendingMail'),'warning'); + } + + +} diff --git a/htdocs/holiday/class/holiday.class.php b/htdocs/holiday/class/holiday.class.php index bef89f4462e..1f6dbb6b44d 100644 --- a/htdocs/holiday/class/holiday.class.php +++ b/htdocs/holiday/class/holiday.class.php @@ -1111,11 +1111,11 @@ class Holiday extends CommonObject $this->fetchByUser($fk_user, '', ''); foreach ($this->holiday as $infos_CP) { - if ($infos_CP['statut'] == 4) { + if ($infos_CP['statut'] == Holiday::STATUS_CANCELED) { continue; // ignore not validated holidays } - if ($infos_CP['statut'] == 5) { - continue; // ignore not validated holidays + if ($infos_CP['statut'] == Holiday::STATUS_REFUSED) { + continue; // ignore refused holidays } //var_dump("--"); //var_dump("old: ".dol_print_date($infos_CP['date_debut'],'dayhour').' '.dol_print_date($infos_CP['date_fin'],'dayhour').' '.$infos_CP['halfday']); diff --git a/htdocs/langs/en_US/holiday.lang b/htdocs/langs/en_US/holiday.lang index 3d0ae64be0f..944b0b54db8 100644 --- a/htdocs/langs/en_US/holiday.lang +++ b/htdocs/langs/en_US/holiday.lang @@ -4,6 +4,7 @@ Holidays=Leave CPTitreMenu=Leave MenuReportMonth=Monthly statement MenuAddCP=New leave request +MenuCollectiveAddCP=New collective leave request NotActiveModCP=You must enable the module Leave to view this page. AddCP=Make a leave request DateDebCP=Start date @@ -86,6 +87,13 @@ UserUpdateCP=Updated for PrevSoldeCP=Previous Balance NewSoldeCP=New Balance alreadyCPexist=A leave request has already been done on this period. +UseralreadyCPexist=A leave request has already been done on this period for %s. +groups=Groups +users=Users +AutoSendMail=Automatic mailing +NewHolidayForGroup=Collective leaves +SendRequestCollectiveCP=Send collective leave request +AutoApprovalOnCreate=Automatic approval FirstDayOfHoliday=Beginning day of leave request LastDayOfHoliday=Ending day of leave request BoxTitleLastLeaveRequests=Latest %s modified leave requests From 02a4e10fd3e6ba1edc0d2daa5c1861ef11986296 Mon Sep 17 00:00:00 2001 From: jpb Date: Tue, 7 Jun 2022 19:12:40 +0200 Subject: [PATCH 035/826] add todo for some jquery --- htdocs/holiday/card_group.php | 35 ++++++++++++++++++++------------- htdocs/langs/en_US/holiday.lang | 2 +- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/htdocs/holiday/card_group.php b/htdocs/holiday/card_group.php index 05694934589..5d96bbbbc21 100644 --- a/htdocs/holiday/card_group.php +++ b/htdocs/holiday/card_group.php @@ -51,7 +51,7 @@ $fuserid = (GETPOST('fuserid', 'int') ?GETPOST('fuserid', 'int') : $user->id); $users = (GETPOST('users', 'array') ?GETPOST('users', 'array') : array($user->id)); $groups = GETPOST('groups', 'array') ; $socid = GETPOST('socid', 'int'); -$autoApproval = GETPOST('autoApproval','int'); +$autoValidation = GETPOST('autoValidation','int'); $AutoSendMail = GETPOST('AutoSendMail','int'); // Load translation files required by the page $langs->loadLangs(array("other", "holiday", "mails", "trips")); @@ -323,26 +323,26 @@ if (empty($reshook)) { }else{ // AUTO APPROUVAL /VALIDATED //@TODO changer le nom si approuved / validated - if ($autoApproval){ + if ($autoValidation){ $htemp = new Holiday($db); $htemp->fetch ($result); - // must set the status before approve call ... - $htemp->statut = Holiday::STATUS_VALIDATED; - // $resultApproved = $htemp->approve($approverid); - //@todo à voir avec nico validated ou approuved ? + $htemp->statut = Holiday::STATUS_VALIDATED; $resultValidated = $htemp->update($approverid); if ($resultValidated < 0 ){ setEventMessages($object->error, $object->errors, 'errors'); $error++; } + // we can auto send mail if we are in auto validation behavior + //@todo jquery disable if checkbox autovalidation unchecked + if ($AutoSendMail && !$error){ + // send a mail to the user + sendMail($result, $cancreate, $now, $autoValidation); + } } - if ($AutoSendMail && !$error){ - // send a mail to the user - sendMail($result, $cancreate, $now); - } + } } @@ -985,9 +985,16 @@ llxFooter(); if (is_object($db)) { $db->close(); } - -// automatic send mail -function sendMail ($id, $cancreate, $now){ +/** + * we send email to validator for current leave request (id) + * @param $id + * @param $cancreate + * @param $now + * @param $autoValidation + * @return void + * @throws Exception + */ +function sendMail ($id, $cancreate, $now, $autoValidation){ global $db, $user, $conf, $langs; @@ -1000,7 +1007,7 @@ function sendMail ($id, $cancreate, $now){ if ($object->statut == Holiday::STATUS_DRAFT && $cancreate) { $object->oldcopy = dol_clone($object); - $object->statut = Holiday::STATUS_VALIDATED; + if ($autoValidation) $object->statut = Holiday::STATUS_VALIDATED; $verif = $object->validate($user); diff --git a/htdocs/langs/en_US/holiday.lang b/htdocs/langs/en_US/holiday.lang index 944b0b54db8..2005d7e613c 100644 --- a/htdocs/langs/en_US/holiday.lang +++ b/htdocs/langs/en_US/holiday.lang @@ -93,7 +93,7 @@ users=Users AutoSendMail=Automatic mailing NewHolidayForGroup=Collective leaves SendRequestCollectiveCP=Send collective leave request -AutoApprovalOnCreate=Automatic approval +AutoValidationOnCreate=Automatic validation FirstDayOfHoliday=Beginning day of leave request LastDayOfHoliday=Ending day of leave request BoxTitleLastLeaveRequests=Latest %s modified leave requests From bf0650900d339c8b11459f0bfc9574648e4d18df Mon Sep 17 00:00:00 2001 From: jpb Date: Tue, 7 Jun 2022 19:16:57 +0200 Subject: [PATCH 036/826] remove useless code --- htdocs/holiday/card_group.php | 348 ---------------------------------- 1 file changed, 348 deletions(-) diff --git a/htdocs/holiday/card_group.php b/htdocs/holiday/card_group.php index 5d96bbbbc21..06157ee3e94 100644 --- a/htdocs/holiday/card_group.php +++ b/htdocs/holiday/card_group.php @@ -358,354 +358,6 @@ if (empty($reshook)) { } } } - - - if ($action == 'update_extras') { - $object->oldcopy = dol_clone($object); - - // Fill array 'array_options' with data from update form - $ret = $extrafields->setOptionalsFromPost(null, $object, GETPOST('attribute', 'restricthtml')); - if ($ret < 0) { - $error++; - } - - if (!$error) { - // Actions on extra fields - $result = $object->insertExtraFields('HOLIDAY_MODIFY'); - if ($result < 0) { - setEventMessages($object->error, $object->errors, 'errors'); - $error++; - } - } - - if ($error) { - $action = 'edit_extras'; - } - } - - // Approve leave request - if ($action == 'confirm_valid') { - $object->fetch($id); - - // If status is waiting approval and approver is also user - if ($object->statut == Holiday::STATUS_VALIDATED && $user->id == $object->fk_validator) { - $object->oldcopy = dol_clone($object); - - $object->date_valid = dol_now(); - $object->fk_user_valid = $user->id; - $object->statut = Holiday::STATUS_APPROVED; - - $db->begin(); - - $verif = $object->approve($user); - if ($verif <= 0) { - setEventMessages($object->error, $object->errors, 'errors'); - $error++; - } - - // If no SQL error, we redirect to the request form - if (!$error) { - // Calculcate number of days consummed - $nbopenedday = num_open_day($object->date_debut_gmt, $object->date_fin_gmt, 0, 1, $object->halfday); - $soldeActuel = $object->getCpforUser($object->fk_user, $object->fk_type); - $newSolde = ($soldeActuel - $nbopenedday); - $label = $langs->transnoentitiesnoconv("Holidays").' - '.$object->ref; - - // The modification is added to the LOG - $result = $object->addLogCP($user->id, $object->fk_user, $label, $newSolde, $object->fk_type); - if ($result < 0) { - $error++; - setEventMessages(null, $object->errors, 'errors'); - } - - // Update balance - $result = $object->updateSoldeCP($object->fk_user, $newSolde, $object->fk_type); - if ($result < 0) { - $error++; - setEventMessages(null, $object->errors, 'errors'); - } - } - - if (!$error) { - // To - $destinataire = new User($db); - $destinataire->fetch($object->fk_user); - $emailTo = $destinataire->email; - - if (!$emailTo) { - dol_syslog("User that request leave has no email, so we redirect directly to finished page without sending email"); - } else { - // From - $expediteur = new User($db); - $expediteur->fetch($object->fk_validator); - //$emailFrom = $expediteur->email; Email of user can be an email into another company. Sending will fails, we must use the generic email. - $emailFrom = $conf->global->MAIN_MAIL_EMAIL_FROM; - - // Subject - $societeName = $conf->global->MAIN_INFO_SOCIETE_NOM; - if (!empty($conf->global->MAIN_APPLICATION_TITLE)) { - $societeName = $conf->global->MAIN_APPLICATION_TITLE; - } - - $subject = $societeName." - ".$langs->transnoentitiesnoconv("HolidaysValidated"); - - // Content - $message = "

".$langs->transnoentitiesnoconv("Hello")." ".$destinataire->firstname.",

\n"; - - $message .= "

".$langs->transnoentities("HolidaysValidatedBody", dol_print_date($object->date_debut, 'day'), dol_print_date($object->date_fin, 'day'))."

\n"; - - $link = dol_buildpath('/holiday/card.php', 3).'?id='.$object->id; - - $message .= "
    \n"; - $message .= "
  • ".$langs->transnoentitiesnoconv("ValidatedBy")." : ".dolGetFirstLastname($expediteur->firstname, $expediteur->lastname)."
  • \n"; - $message .= "
  • ".$langs->transnoentitiesnoconv("Link").' : '.$link."
  • \n"; - $message .= "
\n"; - - $trackid = 'leav'.$object->id; - - $mail = new CMailFile($subject, $emailTo, $emailFrom, $message, array(), array(), array(), '', '', 0, 1, '', '', $trackid); - - // Sending email - $result = $mail->sendfile(); - - if (!$result) { - setEventMessages($mail->error, $mail->errors, 'warnings'); // Show error, but do no make rollback, so $error is not set to 1 - $action = ''; - } - } - } - - if (!$error) { - $db->commit(); - - header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); - exit; - } else { - $db->rollback(); - $action = ''; - } - } - } - - if ($action == 'confirm_refuse' && GETPOST('confirm', 'alpha') == 'yes') { - if (GETPOST('detail_refuse')) { - $object->fetch($id); - - // If status pending validation and validator = user - if ($object->statut == Holiday::STATUS_VALIDATED && $user->id == $object->fk_validator) { - $object->date_refuse = dol_print_date('dayhour', dol_now()); - $object->fk_user_refuse = $user->id; - $object->statut = Holiday::STATUS_REFUSED; - $object->detail_refuse = GETPOST('detail_refuse', 'alphanohtml'); - - $db->begin(); - - $verif = $object->update($user); - if ($verif <= 0) { - $error++; - setEventMessages($object->error, $object->errors, 'errors'); - } - - // If no SQL error, we redirect to the request form - if (!$error) { - // To - $destinataire = new User($db); - $destinataire->fetch($object->fk_user); - $emailTo = $destinataire->email; - - if (!$emailTo) { - dol_syslog("User that request leave has no email, so we redirect directly to finished page without sending email"); - } else { - // From - $expediteur = new User($db); - $expediteur->fetch($object->fk_validator); - //$emailFrom = $expediteur->email; Email of user can be an email into another company. Sending will fails, we must use the generic email. - $emailFrom = $conf->global->MAIN_MAIL_EMAIL_FROM; - - // Subject - $societeName = $conf->global->MAIN_INFO_SOCIETE_NOM; - if (!empty($conf->global->MAIN_APPLICATION_TITLE)) { - $societeName = $conf->global->MAIN_APPLICATION_TITLE; - } - - $subject = $societeName." - ".$langs->transnoentitiesnoconv("HolidaysRefused"); - - // Content - $message = "

".$langs->transnoentitiesnoconv("Hello")." ".$destinataire->firstname.",

\n"; - - $message .= "

".$langs->transnoentities("HolidaysRefusedBody", dol_print_date($object->date_debut, 'day'), dol_print_date($object->date_fin, 'day'))."

\n"; - $message .= "

".GETPOST('detail_refuse', 'alpha')."

"; - - $link = dol_buildpath('/holiday/card.php', 3).'?id='.$object->id; - - $message .= "
    \n"; - $message .= "
  • ".$langs->transnoentitiesnoconv("ModifiedBy")." : ".dolGetFirstLastname($expediteur->firstname, $expediteur->lastname)."
  • \n"; - $message .= "
  • ".$langs->transnoentitiesnoconv("Link").' : '.$link."
  • \n"; - $message .= "
"; - - $trackid = 'leav'.$object->id; - - $mail = new CMailFile($subject, $emailTo, $emailFrom, $message, array(), array(), array(), '', '', 0, 1, '', '', $trackid); - - // sending email - $result = $mail->sendfile(); - - if (!$result) { - setEventMessages($mail->error, $mail->errors, 'warnings'); // Show error, but do no make rollback, so $error is not set to 1 - $action = ''; - } - } - } else { - $action = ''; - } - - if (!$error) { - $db->commit(); - - header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); - exit; - } else { - $db->rollback(); - $action = ''; - } - } - } else { - setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("DetailRefusCP")), null, 'errors'); - $action = 'refuse'; - } - } - - - // If the request is validated - if ($action == 'confirm_draft' && GETPOST('confirm') == 'yes') { - $error = 0; - - $object->fetch($id); - - $oldstatus = $object->statut; - $object->statut = Holiday::STATUS_DRAFT; - - $result = $object->update($user); - if ($result < 0) { - $error++; - setEventMessages($langs->trans('ErrorBackToDraft').' '.$object->error, $object->errors, 'errors'); - } - - if (!$error) { - $db->commit(); - - header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); - exit; - } else { - $db->rollback(); - } - } - - // If confirmation of cancellation - if ($action == 'confirm_cancel' && GETPOST('confirm') == 'yes') { - $error = 0; - - $object->fetch($id); - - // If status pending validation and validator = validator or user, or rights to do for others - if (($object->statut == Holiday::STATUS_VALIDATED || $object->statut == Holiday::STATUS_APPROVED) && - (!empty($user->admin) || $user->id == $object->fk_validator || $cancreate || $cancreateall)) { - $db->begin(); - - $oldstatus = $object->statut; - $object->date_cancel = dol_now(); - $object->fk_user_cancel = $user->id; - $object->statut = Holiday::STATUS_CANCELED; - - $result = $object->update($user); - - if ($result >= 0 && $oldstatus == Holiday::STATUS_APPROVED) { // holiday was already validated, status 3, so we must increase back the balance - // Call trigger - $result = $object->call_trigger('HOLIDAY_CANCEL', $user); - if ($result < 0) { - $error++; - } - - // Calculcate number of days consummed - $nbopenedday = num_open_day($object->date_debut_gmt, $object->date_fin_gmt, 0, 1, $object->halfday); - - $soldeActuel = $object->getCpforUser($object->fk_user, $object->fk_type); - $newSolde = ($soldeActuel + $nbopenedday); - - // The modification is added to the LOG - $result1 = $object->addLogCP($user->id, $object->fk_user, $langs->transnoentitiesnoconv("HolidaysCancelation"), $newSolde, $object->fk_type); - - // Update of the balance - $result2 = $object->updateSoldeCP($object->fk_user, $newSolde, $object->fk_type); - - if ($result1 < 0 || $result2 < 0) { - $error++; - setEventMessages($langs->trans('ErrorCantDeleteCP').' '.$object->error, $object->errors, 'errors'); - } - } - - if (!$error) { - $db->commit(); - } else { - $db->rollback(); - } - - // If no SQL error, we redirect to the request form - if (!$error && $result > 0) { - // To - $destinataire = new User($db); - $destinataire->fetch($object->fk_user); - $emailTo = $destinataire->email; - - if (!$emailTo) { - header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); - exit; - } - - // From - $expediteur = new User($db); - $expediteur->fetch($object->fk_user_cancel); - //$emailFrom = $expediteur->email; Email of user can be an email into another company. Sending will fails, we must use the generic email. - $emailFrom = $conf->global->MAIN_MAIL_EMAIL_FROM; - - // Subject - $societeName = $conf->global->MAIN_INFO_SOCIETE_NOM; - if (!empty($conf->global->MAIN_APPLICATION_TITLE)) { - $societeName = $conf->global->MAIN_APPLICATION_TITLE; - } - - $subject = $societeName." - ".$langs->transnoentitiesnoconv("HolidaysCanceled"); - - // Content - $message = "

".$langs->transnoentitiesnoconv("Hello")." ".$destinataire->firstname.",

\n"; - - $message .= "

".$langs->transnoentities("HolidaysCanceledBody", dol_print_date($object->date_debut, 'day'), dol_print_date($object->date_fin, 'day'))."

\n"; - - $link = dol_buildpath('/holiday/card.php', 3).'?id='.$object->id; - - $message .= "
    \n"; - $message .= "
  • ".$langs->transnoentitiesnoconv("ModifiedBy")." : ".dolGetFirstLastname($expediteur->firstname, $expediteur->lastname)."
  • \n"; - $message .= "
  • ".$langs->transnoentitiesnoconv("Link").' : '.$link."
  • \n"; - $message .= "
\n"; - - $trackid = 'leav'.$object->id; - - $mail = new CMailFile($subject, $emailTo, $emailFrom, $message, array(), array(), array(), '', '', 0, 1, '', '', $trackid); - - // sending email - $result = $mail->sendfile(); - - if (!$result) { - setEventMessages($mail->error, $mail->errors, 'warnings'); - $action = ''; - } else { - header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); - exit; - } - } - } - } - } From 8c607b8101a580736259420a50694ecbeca4e5e6 Mon Sep 17 00:00:00 2001 From: jpb Date: Tue, 7 Jun 2022 19:20:53 +0200 Subject: [PATCH 037/826] add todo --- htdocs/holiday/card_group.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/htdocs/holiday/card_group.php b/htdocs/holiday/card_group.php index 06157ee3e94..a51f9c6ab20 100644 --- a/htdocs/holiday/card_group.php +++ b/htdocs/holiday/card_group.php @@ -638,12 +638,12 @@ if (is_object($db)) { $db->close(); } /** - * we send email to validator for current leave request (id) + * send email to validator for current leave represented by (id) * @param $id * @param $cancreate * @param $now * @param $autoValidation - * @return void + * @return string|void * @throws Exception */ function sendMail ($id, $cancreate, $now, $autoValidation){ @@ -670,6 +670,8 @@ function sendMail ($id, $cancreate, $now, $autoValidation){ $destinataire->fetch($object->fk_validator); $emailTo = $destinataire->email; + //@todo make object return errors + //@todo remove redisrection here ! if (!$emailTo) { dol_syslog("Expected validator has no email, so we redirect directly to finished page without sending email"); header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); @@ -736,17 +738,23 @@ function sendMail ($id, $cancreate, $now, $autoValidation){ setEventMessages($mail->error, $mail->errors, 'warnings'); $action = ''; } else { + //@todo make object return errors + //@todo remove redisrection here ! header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); exit; } } else { + //@todo make object return errors + //@todo remove redisrection here ! setEventMessages($object->error, $object->errors, 'errors'); $action = ''; } } }else{ + //@todo make object return errors + //@todo remove redisrection here ! setEventMessage($langs->trans('ErrorloadUserOnSendingMail'),'warning'); } - + return 'objerrors'; } From c87c6ad042b2881018a59fabed7f5a9a43da13a9 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Wed, 8 Jun 2022 07:26:00 +0000 Subject: [PATCH 038/826] Fixing style errors. --- htdocs/core/menus/standard/eldy.lib.php | 3 +- htdocs/holiday/card_group.php | 54 +++++++++++-------------- 2 files changed, 25 insertions(+), 32 deletions(-) diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index 6427c0b07d7..3e0ac2d371d 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -2270,7 +2270,7 @@ function get_left_menu_hrm($mainmenu, &$newmenu, $usemenuhider = 1, $leftmenu = $newmenu->add("/holiday/list.php?mainmenu=hrm&leftmenu=holiday", $langs->trans("CPTitreMenu"), 0, $user->rights->holiday->read, '', $mainmenu, 'holiday', 0, '', '', '', img_picto('', 'holiday', 'class="pictofixedwidth"')); $newmenu->add("/holiday/card.php?mainmenu=hrm&leftmenu=holiday&action=create", $langs->trans("New"), 1, $user->rights->holiday->write, '', $mainmenu); - $newmenu->add("/holiday/card_group.php?mainmenu=hrm&leftmenu=holiday&action=request", $langs->trans("NewHolidayForGroup"), 1, ($user->rights->holiday->writeall && $user->rights->holiday->readall) , '', $mainmenu, 'holiday_sm'); + $newmenu->add("/holiday/card_group.php?mainmenu=hrm&leftmenu=holiday&action=request", $langs->trans("NewHolidayForGroup"), 1, ($user->rights->holiday->writeall && $user->rights->holiday->readall), '', $mainmenu, 'holiday_sm'); $newmenu->add("/holiday/list.php?mainmenu=hrm&leftmenu=holiday", $langs->trans("List"), 1, $user->rights->holiday->read, '', $mainmenu); if ($usemenuhider || empty($leftmenu) || $leftmenu == "holiday") { $newmenu->add("/holiday/list.php?search_status=1&mainmenu=hrm&leftmenu=holiday", $langs->trans("DraftCP"), 2, $user->rights->holiday->read, '', $mainmenu, 'holiday_sm'); @@ -2282,7 +2282,6 @@ function get_left_menu_hrm($mainmenu, &$newmenu, $usemenuhider = 1, $leftmenu = $newmenu->add("/holiday/define_holiday.php?mainmenu=hrm&action=request", $langs->trans("MenuConfCP"), 1, $user->rights->holiday->read, '', $mainmenu, 'holiday_sm'); $newmenu->add("/holiday/month_report.php?mainmenu=hrm&leftmenu=holiday", $langs->trans("MenuReportMonth"), 1, $user->rights->holiday->readall, '', $mainmenu, 'holiday_sm'); $newmenu->add("/holiday/view_log.php?mainmenu=hrm&leftmenu=holiday&action=request", $langs->trans("MenuLogCP"), 1, $user->rights->holiday->define_holiday, '', $mainmenu, 'holiday_sm'); - } // Trips and expenses (old module) diff --git a/htdocs/holiday/card_group.php b/htdocs/holiday/card_group.php index a51f9c6ab20..a786191acd1 100644 --- a/htdocs/holiday/card_group.php +++ b/htdocs/holiday/card_group.php @@ -49,10 +49,10 @@ $id = GETPOST('id', 'int'); $ref = GETPOST('ref', 'alpha'); $fuserid = (GETPOST('fuserid', 'int') ?GETPOST('fuserid', 'int') : $user->id); $users = (GETPOST('users', 'array') ?GETPOST('users', 'array') : array($user->id)); -$groups = GETPOST('groups', 'array') ; +$groups = GETPOST('groups', 'array'); $socid = GETPOST('socid', 'int'); -$autoValidation = GETPOST('autoValidation','int'); -$AutoSendMail = GETPOST('AutoSendMail','int'); +$autoValidation = GETPOST('autoValidation', 'int'); +$AutoSendMail = GETPOST('AutoSendMail', 'int'); // Load translation files required by the page $langs->loadLangs(array("other", "holiday", "mails", "trips")); @@ -162,9 +162,8 @@ if (empty($reshook)) { } if (!$error) { - $users = GETPOST('users', 'array'); - $groups = GETPOST('groups', 'array') ; + $groups = GETPOST('groups', 'array'); $date_debut = dol_mktime(0, 0, 0, GETPOST('date_debut_month'), GETPOST('date_debut_day'), GETPOST('date_debut_year')); $date_fin = dol_mktime(0, 0, 0, GETPOST('date_fin_month'), GETPOST('date_fin_day'), GETPOST('date_fin_year')); @@ -209,7 +208,7 @@ if (empty($reshook)) { } } // If no groups and no users - if (empty($groups) && empty($users)){ + if (empty($groups) && empty($users)) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("User")), null, 'errors'); setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Group")), null, 'errors'); $error++; @@ -259,7 +258,6 @@ if (empty($reshook)) { if (!$error) { - $TusersToProcess = array(); /** GROUPS */ @@ -290,10 +288,10 @@ if (empty($reshook)) { $userError = new User($db); $result = $userError->fetch($u); - if ($result){ - setEventMessages($langs->trans("UseralreadyCPexist",$userError->firstname . ' '. $userError->lastname), null, 'errors'); - }else{ - setEventMessages($langs->trans("ErrorUserFetch",$u), null, 'errors'); + if ($result) { + setEventMessages($langs->trans("UseralreadyCPexist", $userError->firstname . ' '. $userError->lastname), null, 'errors'); + } else { + setEventMessages($langs->trans("ErrorUserFetch", $u), null, 'errors'); } $error++; @@ -305,7 +303,6 @@ if (empty($reshook)) { $db->begin(); // non errors we can insert all foreach ($TusersToProcess as $u) { - $object = new Holiday($db); $object->fk_user = $u; $object->description = $description; @@ -320,30 +317,27 @@ if (empty($reshook)) { if ($result <= 0) { setEventMessages($object->error, $object->errors, 'errors'); $error++; - }else{ + } else { // AUTO APPROUVAL /VALIDATED //@TODO changer le nom si approuved / validated - if ($autoValidation){ + if ($autoValidation) { $htemp = new Holiday($db); - $htemp->fetch ($result); + $htemp->fetch($result); $htemp->statut = Holiday::STATUS_VALIDATED; $resultValidated = $htemp->update($approverid); - if ($resultValidated < 0 ){ + if ($resultValidated < 0 ) { setEventMessages($object->error, $object->errors, 'errors'); $error++; } // we can auto send mail if we are in auto validation behavior //@todo jquery disable if checkbox autovalidation unchecked - if ($AutoSendMail && !$error){ + if ($AutoSendMail && !$error) { // send a mail to the user sendMail($result, $cancreate, $now, $autoValidation); } } - - - } } } @@ -475,7 +469,7 @@ if ((empty($id) && empty($ref)) || $action == 'create' || $action == 'add') { $resql = $db->query($sql); $Tgroup = array(); - while ($obj = $db->fetch_object($resql)){ + while ($obj = $db->fetch_object($resql)) { $Tgroup[$obj->rowid] = $obj->nom; } print $form->multiselectarray('groups', $Tgroup, GETPOST('groups', 'array'), '', 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0); @@ -493,15 +487,14 @@ if ((empty($id) && empty($ref)) || $action == 'create' || $action == 'add') { if ($cancreate && !$cancreateall) { - - }else{ + } else { //$sql .= ' AND u.fk_user = '.$user->id; //$sql .= ' OR u.rowid ='.$user->id; } $resql = $db->query($sql); - if ($resql){ - while ($obj = $db->fetch_object($resql)){ + if ($resql) { + while ($obj = $db->fetch_object($resql)) { $userlist[$obj->rowid] = $obj->firstname . ' '. $obj->lastname; } } @@ -646,7 +639,8 @@ if (is_object($db)) { * @return string|void * @throws Exception */ -function sendMail ($id, $cancreate, $now, $autoValidation){ +function sendMail($id, $cancreate, $now, $autoValidation) +{ global $db, $user, $conf, $langs; @@ -654,7 +648,7 @@ function sendMail ($id, $cancreate, $now, $autoValidation){ $result = $object->fetch($id); - if ($result){ + if ($result) { // If draft and owner of leave if ($object->statut == Holiday::STATUS_DRAFT && $cancreate) { $object->oldcopy = dol_clone($object); @@ -750,11 +744,11 @@ function sendMail ($id, $cancreate, $now, $autoValidation){ $action = ''; } } - }else{ + } else { //@todo make object return errors //@todo remove redisrection here ! - setEventMessage($langs->trans('ErrorloadUserOnSendingMail'),'warning'); + setEventMessage($langs->trans('ErrorloadUserOnSendingMail'), 'warning'); } - return 'objerrors'; + return 'objerrors'; } From 7df97d1f3dad1ec19fa5b0dcd3b7220af1fe04c0 Mon Sep 17 00:00:00 2001 From: jpb Date: Wed, 8 Jun 2022 10:09:30 +0200 Subject: [PATCH 039/826] rename autovalidation --- htdocs/holiday/card_group.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/holiday/card_group.php b/htdocs/holiday/card_group.php index a51f9c6ab20..49605a69511 100644 --- a/htdocs/holiday/card_group.php +++ b/htdocs/holiday/card_group.php @@ -591,9 +591,9 @@ if ((empty($id) && empty($ref)) || $action == 'create' || $action == 'add') { print '
'.$langs->trans("AutoApprovalOnCreate").''; - print ''; + print ''; print '
'; print ''; @@ -485,13 +498,6 @@ if ((empty($id) && empty($ref)) || $action == 'create' || $action == 'add') { $sql .= ' WHERE 1=1 '; $sql .= !empty($morefilter) ? $morefilter : ''; - - if ($cancreate && !$cancreateall) { - } else { - //$sql .= ' AND u.fk_user = '.$user->id; - //$sql .= ' OR u.rowid ='.$user->id; - } - $resql = $db->query($sql); if ($resql) { while ($obj = $db->fetch_object($resql)) { @@ -586,13 +592,13 @@ if ((empty($id) && empty($ref)) || $action == 'create' || $action == 'add') { //auto validation ON CREATE print ''."\n"; //no auto SEND MAIL print ''."\n"; // Description @@ -641,6 +647,11 @@ if (is_object($db)) { */ function sendMail($id, $cancreate, $now, $autoValidation) { + $objStd = new stdClass(); + $objStd->msg = ''; + $objStd->status = 'success'; + $objStd->error = 0; + $objStd->style = ''; global $db, $user, $conf, $langs; @@ -657,19 +668,21 @@ function sendMail($id, $cancreate, $now, $autoValidation) $verif = $object->validate($user); - // If no SQL error, we redirect to the request form if ($verif > 0) { // To $destinataire = new User($db); $destinataire->fetch($object->fk_validator); $emailTo = $destinataire->email; - //@todo make object return errors - //@todo remove redisrection here ! + if (!$emailTo) { dol_syslog("Expected validator has no email, so we redirect directly to finished page without sending email"); - header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); - exit; + + $objStd->error++; + $objStd->msg = $langs->trans('ErroremailTo'); + $objStd->status = 'error'; + $objStd->style="warnings"; + return $objStd; } // From @@ -729,26 +742,34 @@ function sendMail($id, $cancreate, $now, $autoValidation) $result = $mail->sendfile(); if (!$result) { - setEventMessages($mail->error, $mail->errors, 'warnings'); - $action = ''; + + $objStd->error++; + $objStd->msg = $langs->trans('ErroreSendmail'); + $objStd->style="warnings"; + $objStd->status = 'error'; } else { - //@todo make object return errors - //@todo remove redisrection here ! - header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); - exit; + + $objStd->msg = $langs->trans('mailSended'); } + + return $objStd; } else { - //@todo make object return errors - //@todo remove redisrection here ! - setEventMessages($object->error, $object->errors, 'errors'); - $action = ''; + + $objStd->error++; + $objStd->msg = $langs->trans('ErroreVerif'); + $objStd->status = 'error'; + $objStd->style="errors"; + return $objStd; } } } else { - //@todo make object return errors - //@todo remove redisrection here ! - setEventMessage($langs->trans('ErrorloadUserOnSendingMail'), 'warning'); + + $objStd->error++; + $objStd->msg = $langs->trans('ErrorloadUserOnSendingMail'); + $objStd->status = 'error'; + $objStd->style="warnings"; + return $objStd; } - return 'objerrors'; + return $objStd; } From 189d918181f906e0caf7083d287481079f9b8e94 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Wed, 8 Jun 2022 15:14:18 +0000 Subject: [PATCH 041/826] Fixing style errors. --- htdocs/holiday/card_group.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/htdocs/holiday/card_group.php b/htdocs/holiday/card_group.php index 898d9f53be8..19f5e1a5fd8 100644 --- a/htdocs/holiday/card_group.php +++ b/htdocs/holiday/card_group.php @@ -318,7 +318,6 @@ if (empty($reshook)) { setEventMessages($object->error, $object->errors, 'errors'); $error++; } else { - //@TODO changer le nom si validated if ($autoValidation) { $htemp = new Holiday($db); @@ -336,7 +335,7 @@ if (empty($reshook)) { if ($AutoSendMail && !$error) { // send a mail to the user $returnSendMail = sendMail($result, $cancreate, $now, $autoValidation); - if (!empty($returnSendMail->msg)) setEventMessage($returnSendMail->msg,$returnSendMail->style); + if (!empty($returnSendMail->msg)) setEventMessage($returnSendMail->msg, $returnSendMail->style); } } } @@ -742,19 +741,16 @@ function sendMail($id, $cancreate, $now, $autoValidation) $result = $mail->sendfile(); if (!$result) { - $objStd->error++; $objStd->msg = $langs->trans('ErroreSendmail'); $objStd->style="warnings"; $objStd->status = 'error'; } else { - $objStd->msg = $langs->trans('mailSended'); } return $objStd; } else { - $objStd->error++; $objStd->msg = $langs->trans('ErroreVerif'); $objStd->status = 'error'; @@ -763,7 +759,6 @@ function sendMail($id, $cancreate, $now, $autoValidation) } } } else { - $objStd->error++; $objStd->msg = $langs->trans('ErrorloadUserOnSendingMail'); $objStd->status = 'error'; From 9ad5553c47b064fa4e3b30fe6824d101a52f38c7 Mon Sep 17 00:00:00 2001 From: melina Date: Wed, 8 Jun 2022 17:56:11 +0200 Subject: [PATCH 042/826] Add setup parameters --- htdocs/langs/en_US/cashdesk.lang | 8 +++++- htdocs/langs/fr_FR/cashdesk.lang | 6 ++++ htdocs/takepos/admin/appearance.php | 43 +++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/htdocs/langs/en_US/cashdesk.lang b/htdocs/langs/en_US/cashdesk.lang index b53eb235c29..07b91316771 100644 --- a/htdocs/langs/en_US/cashdesk.lang +++ b/htdocs/langs/en_US/cashdesk.lang @@ -136,4 +136,10 @@ PrintWithoutDetails=Print without details YearNotDefined=Year is not defined TakeposBarcodeRuleToInsertProduct=Barcode rule to insert product TakeposBarcodeRuleToInsertProductDesc=Rule to extract the product reference + a quantity from a scanned barcode.
If empty (default value), application will use the full barcode scanned to find the product.

If defined, syntax must be:
ref:NB+qu:NB+qd:NB+other:NB
where NB is the number of characters to use to extract data from the scanned barcode with:
  • ref : product reference
  • qu : quantity to set when inserting item (units)
  • qd : quantity to set when inserting item (decimals)
  • other : others characters
-AlreadyPrinted=Already printed \ No newline at end of file +AlreadyPrinted=Already printed +HideCategories=Hide categories +HideStockOnLine=Hide stock on line +ShowOnlyProductInStock=Show the products in stock +ShowCategoryDescription=Show category description +ShowProductReference=Show reference of products +UsePriceHT=Use price excl. taxes and not price incl. taxes \ No newline at end of file diff --git a/htdocs/langs/fr_FR/cashdesk.lang b/htdocs/langs/fr_FR/cashdesk.lang index 24d35d56a06..5ce6fb98a5d 100644 --- a/htdocs/langs/fr_FR/cashdesk.lang +++ b/htdocs/langs/fr_FR/cashdesk.lang @@ -136,3 +136,9 @@ PrintWithoutDetails=Générer sans les détails YearNotDefined=L'année n'est pas définie TakeposBarcodeRuleToInsertProduct=Règle de lecture du code barre des produits TakeposBarcodeRuleToInsertProductDesc=Règle pour extraire la référence produit + une quantité d'un code barre scanné.
Si vide (valeur par défaut), l'application utilisera le code-barres complet scanné pour trouver le produit.

Si elle est définie, la syntaxe doit être:
ref: NB + Qu: NB + QD: NB + autres: NB
où NB est le nombre de caractères à utiliser pour extraire les données du code à barres scannés avec:
  • ref : référence produit
  • qu : quantité de jeu lors de l'insertion article (unités)
  • qd: quantité de jeu lors de l'insertion article (décimaux)
  • autre : autres caractères
+HideCategories=Masquer les catégories +HideStockOnLine=Masquer le stock en ligne +ShowOnlyProductInStock=Affficher les produits en stock +ShowCategoryDescription=Afficher la description des catégories +ShowProductReference=Afficher la référence des produits +UsePriceHT= Utiliser le prix HT et non en TTC \ No newline at end of file diff --git a/htdocs/takepos/admin/appearance.php b/htdocs/takepos/admin/appearance.php index 135a3b2a9e7..060c955728d 100644 --- a/htdocs/takepos/admin/appearance.php +++ b/htdocs/takepos/admin/appearance.php @@ -117,6 +117,49 @@ $array = array(1=>"1", 2=>"2", 3=>"3", 4=>"4", 5=>"5", 6=>"6"); print $form->selectarray('TAKEPOS_LINES_TO_SHOW', $array, (empty($conf->global->TAKEPOS_LINES_TO_SHOW) ? '2' : $conf->global->TAKEPOS_LINES_TO_SHOW), 0); print "\n"; +// D'ont display category +print '
\n"; + +// Hide stock on line +print '\n"; + +// Only the products in stock +print '\n"; + +// View description of the categories +print '\n"; + +// View reference of products +print '\n"; + +// Use price excl. taxes (HT) and not price incl. taxes (TTC) +print '\n"; + + print '
'.$langs->trans("AutoApprovalOnCreate").''; - print ''; + print ''; print '
'.$langs->trans("AutoSendMail").''; - print ''; + print ''; print '
'; +print $langs->trans('HideCategories'); +print ''; +print ajax_constantonoff("TAKEPOS_HIDE_CATEGORIES", array(), $conf->entity, 0, 0, 1, 0); +print "
'; +print $langs->trans('HideStockOnLine'); +print ''; +print ajax_constantonoff("TAKEPOS_HIDE_STOCK_ON_LINE", array(), $conf->entity, 0, 0, 1, 0); +print "
'; +print $langs->trans('ShowOnlyProductInStock'); +print ''; +print ajax_constantonoff("TAKEPOS_PRODUCT_IN_STOCK", array(), $conf->entity, 0, 0, 1, 0); +print "
'; +print $langs->trans('ShowCategoryDescription'); +print ''; +print ajax_constantonoff("TAKEPOS_SHOW_CATEGORY_DESCRIPTION", array(), $conf->entity, 0, 0, 1, 0); +print "
'; +print $langs->trans('ShowProductReference'); +print ''; +print ajax_constantonoff("TAKEPOS_SHOW_PRODUCT_REFERENCE", array(), $conf->entity, 0, 0, 1, 0); +print "
'; +print $langs->trans('UsePriceHT'); +print ''; +print ajax_constantonoff("TAKEPOS_CHANGE_PRICE_HT", array(), $conf->entity, 0, 0, 1, 0); +print "
'; print $form->buttonsSaveCancel("Save", ''); From fb3f2698ae6c58b4340b4061626f55176f60aaec Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Thu, 9 Jun 2022 08:46:46 +0000 Subject: [PATCH 043/826] Fixing style errors. --- htdocs/takepos/admin/appearance.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/takepos/admin/appearance.php b/htdocs/takepos/admin/appearance.php index 060c955728d..9198b03bb63 100644 --- a/htdocs/takepos/admin/appearance.php +++ b/htdocs/takepos/admin/appearance.php @@ -124,7 +124,7 @@ print ''; print ajax_constantonoff("TAKEPOS_HIDE_CATEGORIES", array(), $conf->entity, 0, 0, 1, 0); print "\n"; -// Hide stock on line +// Hide stock on line print ''; print $langs->trans('HideStockOnLine'); print ''; From 50ae1b1f7693f53cc687c681a4cd716bb8822db0 Mon Sep 17 00:00:00 2001 From: kamel Date: Fri, 10 Jun 2022 10:19:56 +0200 Subject: [PATCH 044/826] NEW: Add new hook for show virtual stock details on product stock card --- htdocs/product/stock/product.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/htdocs/product/stock/product.php b/htdocs/product/stock/product.php index b9fc1a201e5..e8622781a3f 100644 --- a/htdocs/product/stock/product.php +++ b/htdocs/product/stock/product.php @@ -734,6 +734,15 @@ if ($id > 0 || $ref) { $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER) ? '- '.$langs->trans("ReStockOnValidateOrder").'
' : ''); $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER) ? '- '.$langs->trans("ReStockOnDispatchOrder").'
' : ''); $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_RECEPTION) || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE) ? '- '.$langs->trans("StockOnReception").'
' : ''); + $parameters = array(); + $reshook = $hookmanager->executeHooks('physicalStockTextStockOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if ($reshook > 0) { + $text_stock_options = $hookmanager->resPrint; + } elseif ($reshook == 0) { + $text_stock_options .= $hookmanager->resPrint; + } else { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } print ''; print $form->textwithpicto($langs->trans("PhysicalStock"), $text_stock_options, 1); @@ -820,6 +829,15 @@ if ($id > 0 || $ref) { $helpondiff .= $langs->trans("ProductQtyToConsumeByMO").': '.$object->stats_mrptoconsume['qty'].'
'; $helpondiff .= $langs->trans("ProductQtyToProduceByMO").': '.$object->stats_mrptoproduce['qty']; } + $parameters = array('found' => &$found, 'id' => $object->id, 'includedraftpoforvirtual' => null); + $reshook = $hookmanager->executeHooks('virtualStockHelpOnDiff', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if ($reshook > 0) { + $helpondiff = $hookmanager->resPrint; + } elseif ($reshook == 0) { + $helpondiff .= $hookmanager->resPrint; + } else { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } // Calculating a theorical value From 19cb81e3ea3247ded71b35c58bbab6e4e35d1070 Mon Sep 17 00:00:00 2001 From: jpb Date: Sat, 11 Jun 2022 10:16:04 +0200 Subject: [PATCH 045/826] change filter array method on users selection from groups --- htdocs/holiday/card_group.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/htdocs/holiday/card_group.php b/htdocs/holiday/card_group.php index 898d9f53be8..07beaeeb678 100644 --- a/htdocs/holiday/card_group.php +++ b/htdocs/holiday/card_group.php @@ -259,7 +259,7 @@ if (empty($reshook)) { if (!$error) { $TusersToProcess = array(); - + // usergroup select /** GROUPS */ $sql = ' SELECT DISTINCT u.rowid,u.lastname,u.firstname from ' . MAIN_DB_PREFIX . 'user as u'; $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'usergroup_user as ug on ug.fk_user = u.rowid '; @@ -268,15 +268,13 @@ if (empty($reshook)) { if ($resql) { while ($obj = $db->fetch_object($resql)) { - if (!array_key_exists($obj->rowid, $TusersToProcess)) - $TusersToProcess[] = $obj->rowid; + $TusersToProcess[$obj->rowid] = $obj->rowid; } } /** USERS */ if (is_array($users) && count($users) > 0) { foreach ($users as $u) { - if (!array_key_exists($u, $TusersToProcess)) - $TusersToProcess[] = $u; + $TusersToProcess[$u] = $u; } } foreach ($TusersToProcess as $u) { From 1af3b6ccbddd6ba5fdc3c12ba36babb281ebcc94 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Sat, 11 Jun 2022 08:23:08 +0000 Subject: [PATCH 046/826] Fixing style errors. --- htdocs/holiday/card_group.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/holiday/card_group.php b/htdocs/holiday/card_group.php index 93560b9bb7c..c52ea39681d 100644 --- a/htdocs/holiday/card_group.php +++ b/htdocs/holiday/card_group.php @@ -259,7 +259,7 @@ if (empty($reshook)) { if (!$error) { $TusersToProcess = array(); - // usergroup select + // usergroup select /** GROUPS */ $sql = ' SELECT DISTINCT u.rowid,u.lastname,u.firstname from ' . MAIN_DB_PREFIX . 'user as u'; $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'usergroup_user as ug on ug.fk_user = u.rowid '; From 74d23cccd8c6e84efb87d4be862c82bd8e8b91ec Mon Sep 17 00:00:00 2001 From: jpb Date: Sat, 11 Jun 2022 14:01:54 +0200 Subject: [PATCH 047/826] remove seteventMessage * precheck automail on selected auto validation --- htdocs/holiday/card_group.php | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/htdocs/holiday/card_group.php b/htdocs/holiday/card_group.php index 93560b9bb7c..57fe16ea23e 100644 --- a/htdocs/holiday/card_group.php +++ b/htdocs/holiday/card_group.php @@ -281,7 +281,7 @@ if (empty($reshook)) { // Check if there is already holiday for this period pour chaque user $verifCP = $object->verifDateHolidayCP($u, $date_debut, $date_fin, $halfday); if (!$verifCP) { - setEventMessages($langs->trans("alreadyCPexist"), null, 'errors'); + //setEventMessages($langs->trans("alreadyCPexist"), null, 'errors'); $userError = new User($db); $result = $userError->fetch($u); @@ -342,7 +342,7 @@ if (empty($reshook)) { // If no SQL error we redirect to the request card if (!$error) { $db->commit(); - header('Location: '.DOL_URL_ROOT.'/holiday/list.php?restore_lastsearch_values=1'); + header('Location: '.DOL_URL_ROOT.'/holiday/list.php'); exit; } else { $db->rollback(); @@ -414,10 +414,27 @@ if ((empty($id) && empty($ref)) || $action == 'create' || $action == 'add') { if( $("input[name=autoValidation]").is(":checked") ){ $("#AutoSendMail").prop("disabled", false); + $("#AutoSendMail").prop("checked", true); + } else { $("#AutoSendMail").prop("disabled", true); + $("#AutoSendMail").prop("checked", false); } + $("input[name=autoValidation]").click( function(e) { + console.log("chang") + + if( $("input[name=autoValidation]").is(":checked") ){ + $("#AutoSendMail").prop("disabled", false); + $("#AutoSendMail").prop("checked", true); + } else { + $("#AutoSendMail").prop("disabled", true); + $("#AutoSendMail").prop("checked", false); + } + }); + + + $("input.button-save").click("submit", function(e) { console.log("Call valider()"); if (document.demandeCP.date_debut_.value != "") @@ -588,7 +605,7 @@ if ((empty($id) && empty($ref)) || $action == 'create' || $action == 'add') { print ''; //auto validation ON CREATE - print ''.$langs->trans("AutoApprovalOnCreate").''; + print ''.$langs->trans("AutoValidationOnCreate").''; print ''; print ''."\n"; @@ -658,10 +675,10 @@ function sendMail($id, $cancreate, $now, $autoValidation) if ($result) { // If draft and owner of leave - if ($object->statut == Holiday::STATUS_DRAFT && $cancreate) { + if ($object->statut == Holiday::STATUS_VALIDATED && $cancreate) { $object->oldcopy = dol_clone($object); - if ($autoValidation) $object->statut = Holiday::STATUS_VALIDATED; + //if ($autoValidation) $object->statut = Holiday::STATUS_VALIDATED; $verif = $object->validate($user); From 348fb8e9f23e1001cfa7afda0543b144827f9128 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sun, 12 Jun 2022 21:34:35 +0200 Subject: [PATCH 048/826] Stripe Terminal --- htdocs/stripe/admin/stripe.php | 54 +++++++ htdocs/stripe/ajax/ajax.php | 124 +++++++++++++++ htdocs/stripe/class/stripe.class.php | 41 ++++- htdocs/takepos/admin/terminal.php | 43 +++++ htdocs/takepos/pay.php | 229 ++++++++++++++++++++++++++- 5 files changed, 486 insertions(+), 5 deletions(-) create mode 100644 htdocs/stripe/ajax/ajax.php diff --git a/htdocs/stripe/admin/stripe.php b/htdocs/stripe/admin/stripe.php index 77c8d9a03b2..8240b21ff75 100644 --- a/htdocs/stripe/admin/stripe.php +++ b/htdocs/stripe/admin/stripe.php @@ -104,6 +104,10 @@ if ($action == 'setvalue' && $user->admin) { if (!$result > 0) { $error++; } + $result = dolibarr_set_const($db, "STRIPE_LOCATION", GETPOST('STRIPE_LOCATION', 'alpha'), 'chaine', 0, '', $conf->entity); + if (!$result > 0) { + $error++; + } $result = dolibarr_set_const($db, "ONLINE_PAYMENT_CSS_URL", GETPOST('ONLINE_PAYMENT_CSS_URL', 'alpha'), 'chaine', 0, '', $conf->entity); if (!$result > 0) { $error++; @@ -364,6 +368,56 @@ if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) { // What is this for ? print ''; } +// Card Present for Stripe Terminal +if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { // TODO Not used by current code + print ''; + print $langs->trans("STRIPE_CARD_PRESENT").''; + if ($conf->use_javascript_ajax) { + print ajax_constantonoff('STRIPE_CARD_PRESENT'); + } else { + $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); + print $form->selectarray("STRIPE_CARD_PRESENT", $arrval, $conf->global->STRIPE_CARD_PRESENT); + } + print ''; +} + +// Locations for Stripe Terminal +if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { // TODO Not used by current code + print ''; + print $langs->trans("STRIPE_LOCATION").''; + $service = 'StripeTest'; + $servicestatus = 0; + if (!empty($conf->global->STRIPE_LIVE) && !GETPOST('forcesandbox', 'alpha')) { + $service = 'StripeLive'; + $servicestatus = 1; + } + global $stripearrayofkeysbyenv; + $site_account = $stripearrayofkeysbyenv[$servicestatus]['secret_key']; + \Stripe\Stripe::setApiKey($site_account); + if (!empty($conf->stripe->enabled) && (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha'))) { + $service = 'StripeTest'; + $servicestatus = '0'; + dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode', 'Stripe'), '', 'warning'); + } else { + $service = 'StripeLive'; + $servicestatus = '1'; + } + $stripe = new Stripe($db); + $stripeacc = $stripe->getStripeAccount($service); + if ($stripeacc) { + $locations = \Stripe\Terminal\Location::all('', array("stripe_account" => $stripeacc)); + } else { + $locations = \Stripe\Terminal\Location::all(); + } + $location = array(); + $location[""] = $langs->trans("EmptyLocation"); + foreach ($locations as $locations) { + $location[$locations->id] = $locations->display_name; + } + print $form->selectarray("STRIPE_LOCATION", $location, $conf->global->STRIPE_LOCATION); + print ''; +} + // Activate Payment Request API if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { // TODO Not used by current code print ''; diff --git a/htdocs/stripe/ajax/ajax.php b/htdocs/stripe/ajax/ajax.php new file mode 100644 index 00000000000..e50b426ee87 --- /dev/null +++ b/htdocs/stripe/ajax/ajax.php @@ -0,0 +1,124 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/stripe/ajax/ajax.php + * \brief Ajax action for Stipe ie: Terminal + */ + +if (!defined('NOCSRFCHECK')) { + define('NOCSRFCHECK', '1'); +} +if (!defined('NOTOKENRENEWAL')) { + define('NOTOKENRENEWAL', '1'); +} +if (!defined('NOREQUIREMENU')) { + define('NOREQUIREMENU', '1'); +} +if (!defined('NOREQUIREHTML')) { + define('NOREQUIREHTML', '1'); +} +if (!defined('NOREQUIREAJAX')) { + define('NOREQUIREAJAX', '1'); +} +if (!defined('NOBROWSERNOTIF')) { + define('NOBROWSERNOTIF', '1'); +} + +require '../../main.inc.php'; // Load $user and permissions +require_once DOL_DOCUMENT_ROOT.'/includes/stripe/stripe-php/init.php'; +require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; +require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; + +$action = GETPOST('action', 'aZ09'); +$location = GETPOST('location', 'alphanohtml'); +$stripeacc = GETPOST('stripeacc', 'alphanohtml'); +$servicestatus = GETPOST('servicestatus', 'int'); +$amount = GETPOST('amount', 'int'); + +if (empty($user->rights->takepos->run)) { + accessforbidden(); +} + + +/* + * View + */ + +if ($action == 'getConnexionToken') { + try { + // Be sure to authenticate the endpoint for creating connection tokens. + // Force to use the correct API key + global $stripearrayofkeysbyenv; + \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$servicestatus]['secret_key']); + // The ConnectionToken's secret lets you connect to any Stripe Terminal reader + // and take payments with your Stripe account. + $array = array(); + if (isset($location) && !empty($location)) $array['location'] = $location; + if (empty($stripeacc)) { // If the Stripe connect account not set, we use common API usage + $connectionToken = \Stripe\Terminal\ConnectionToken::create($array); + } else { + $connectionToken = \Stripe\Terminal\ConnectionToken::create($array, array("stripe_account" => $stripeacc)); + } + echo json_encode(array('secret' => $connectionToken->secret)); + } catch (Error $e) { + http_response_code(500); + echo json_encode(['error' => $e->getMessage()]); + } +} elseif ($action == 'createPaymentIntent') { + try { + $json_str = file_get_contents('php://input'); + $json_obj = json_decode($json_str); + + // For Terminal payments, the 'payment_method_types' parameter must include + // 'card_present' and the 'capture_method' must be set to 'manual' + $object = new Facture($db); + $object->fetch($json_obj->invoiceid); + $object->fetch_thirdparty(); + + $fulltag='INV='.$object->id.'.CUS='.$object->thirdparty->id; + $tag=null; + $fulltag=dol_string_unaccent($fulltag); + + $stripe = new Stripe($db); + $customer = $stripe->customerStripe($object->thirdparty, $stripeacc, $servicestatus, 1); + + $intent = $stripe->getPaymentIntent($json_obj->amount, $object->multicurrency_code, null, 'Stripe payment: '.$fulltag.(is_object($object)?' ref='.$object->ref:''), $object, $customer, $stripeacc, $servicestatus, 1, 'terminal', false, null, 0, 1); + + echo json_encode(array('client_secret' => $intent->client_secret)); + } catch (Error $e) { + http_response_code(500); + echo json_encode(['error' => $e->getMessage()]); + } +} elseif ($action == 'capturePaymentIntent') { + try { + // retrieve JSON from POST body + $json_str = file_get_contents('php://input'); + $json_obj = json_decode($json_str); + if (empty($stripeacc)) { // If the Stripe connect account not set, we use common API usage + $intent = \Stripe\PaymentIntent::retrieve($json_obj->id); + } else { + $intent = \Stripe\PaymentIntent::retrieve($json_obj->id, array("stripe_account" => $stripeacc)); + } + $intent = $intent->capture(); + + echo json_encode($intent); + } catch (Error $e) { + http_response_code(500); + echo json_encode(['error' => $e->getMessage()]); + } +} diff --git a/htdocs/stripe/class/stripe.class.php b/htdocs/stripe/class/stripe.class.php index 36e67d2827c..b14ed0e8ca6 100644 --- a/htdocs/stripe/class/stripe.class.php +++ b/htdocs/stripe/class/stripe.class.php @@ -290,6 +290,34 @@ class Stripe extends CommonObject return $stripepaymentmethod; } + /** + * Get the Stripe reader Object from its ID + * + * @param string $reader Reader ID + * @param string $key ''=Use common API. If not '', it is the Stripe connect account 'acc_....' to use Stripe connect + * @param int $status Status (0=test, 1=live) + * @return \Stripe\Terminal\Reader|null Stripe Reader or null if not found + */ + public function getSelectedReader($reader, $key = '', $status = 0) + { + $selectedreader = null; + + try { + // Force to use the correct API key + global $stripearrayofkeysbyenv; + \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']); + if (empty($key)) { // If the Stripe connect account not set, we use common API usage + $selectedreader = \Stripe\Terminal\Reader::retrieve(''.$reader.''); + } else { + $stripepaymentmethod = \Stripe\Terminal\Reader::retrieve(''.$reader.'', array("stripe_account" => $key)); + } + } catch (Exception $e) { + $this->error = $e->getMessage(); + } + + return $selectedreader; + } + /** * Get the Stripe payment intent. Create it with confirmnow=false * Warning. If a payment was tried and failed, a payment intent was created. @@ -350,7 +378,7 @@ class Stripe extends CommonObject $paymentintent = null; - if (is_object($object) && !empty($conf->global->STRIPE_REUSE_EXISTING_INTENT_IF_FOUND)) { + if (is_object($object) && !empty($conf->global->STRIPE_REUSE_EXISTING_INTENT_IF_FOUND) && empty($conf->global->STRIPE_CARD_PRESENT)) { // Warning. If a payment was tried and failed, a payment intent was created. // But if we change something on object to pay (amount or other that does not change the idempotency key), reusing same payment intent is not allowed by Stripe. // Recommended solution is to recreate a new payment intent each time we need one (old one will be automatically closed by Stripe after a delay), Stripe will @@ -424,6 +452,9 @@ class Stripe extends CommonObject if (!empty($conf->global->STRIPE_SOFORT)) { $paymentmethodtypes[] = "sofort"; } + if (!empty($conf->global->STRIPE_CARD_PRESENT) && $mode == 'terminal') { + $paymentmethodtypes = array("card_present"); + } $dataforintent = array( "confirm" => $confirmnow, // Do not confirm immediatly during creation of intent @@ -456,6 +487,11 @@ class Stripe extends CommonObject if (!empty($conf->global->STRIPE_KLARNA)) { unset($dataforintent['setup_future_usage']); } + if (!empty($conf->global->STRIPE_CARD_PRESENT) && $mode == 'terminal') { + unset($dataforintent['setup_future_usage']); + $dataforintent["capture_method"] = "manual"; + $dataforintent["confirmation_method"] = "manual"; + } if (!is_null($payment_method)) { $dataforintent["payment_method"] = $payment_method; $description .= ' - '.$payment_method; @@ -607,6 +643,9 @@ class Stripe extends CommonObject if (!empty($conf->global->STRIPE_BANCONTACT)) { $paymentmethodtypes[] = "bancontact"; } + if (!empty($conf->global->STRIPE_KLARNA)) { + $paymentmethodtypes[] = "klarna"; + } if (!empty($conf->global->STRIPE_IDEAL)) { $paymentmethodtypes[] = "ideal"; } diff --git a/htdocs/takepos/admin/terminal.php b/htdocs/takepos/admin/terminal.php index f6562d81693..64ce74b6022 100644 --- a/htdocs/takepos/admin/terminal.php +++ b/htdocs/takepos/admin/terminal.php @@ -1,6 +1,7 @@ * Copyright (C) 2011-2017 Juanjo Menent + * Copyright (C) 2021 Thibault FOUCART * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,6 +29,7 @@ require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php'; require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; require_once DOL_DOCUMENT_ROOT."/core/lib/takepos.lib.php"; +require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; $terminal = GETPOST('terminal', 'int'); // If socid provided by ajax company selector @@ -73,6 +75,9 @@ if (GETPOST('action', 'alpha') == 'set') { $res = dolibarr_set_const($db, "CASHDESK_ID_BANKACCOUNT_CASH".$terminaltouse, (GETPOST('CASHDESK_ID_BANKACCOUNT_CASH'.$terminaltouse, 'alpha') > 0 ? GETPOST('CASHDESK_ID_BANKACCOUNT_CASH'.$terminaltouse, 'alpha') : ''), 'chaine', 0, '', $conf->entity); $res = dolibarr_set_const($db, "CASHDESK_ID_BANKACCOUNT_CHEQUE".$terminaltouse, (GETPOST('CASHDESK_ID_BANKACCOUNT_CHEQUE'.$terminaltouse, 'alpha') > 0 ? GETPOST('CASHDESK_ID_BANKACCOUNT_CHEQUE'.$terminaltouse, 'alpha') : ''), 'chaine', 0, '', $conf->entity); $res = dolibarr_set_const($db, "CASHDESK_ID_BANKACCOUNT_CB".$terminaltouse, (GETPOST('CASHDESK_ID_BANKACCOUNT_CB'.$terminaltouse, 'alpha') > 0 ? GETPOST('CASHDESK_ID_BANKACCOUNT_CB'.$terminaltouse, 'alpha') : ''), 'chaine', 0, '', $conf->entity); + if (!empty($conf->stripe->enabled) && !empty($conf->global->STRIPE_CARD_PRESENT)) { + $res = dolibarr_set_const($db, "CASHDESK_ID_BANKACCOUNT_STRIPETERMINAL".$terminaltouse, GETPOST('CASHDESK_ID_BANKACCOUNT_STRIPETERMINAL'.$terminaltouse, 'alpha'), 'chaine', 0, '', $conf->entity); + } if (!empty($conf->global->TAKEPOS_ENABLE_SUMUP)) { $res = dolibarr_set_const($db, "CASHDESK_ID_BANKACCOUNT_SUMUP".$terminaltouse, (GETPOST('CASHDESK_ID_BANKACCOUNT_SUMUP'.$terminaltouse, 'alpha') > 0 ? GETPOST('CASHDESK_ID_BANKACCOUNT_SUMUP'.$terminaltouse, 'alpha') : ''), 'chaine', 0, '', $conf->entity); } @@ -174,6 +179,44 @@ if (!empty($conf->banque->enabled)) { $atleastonefound++; } print ''; + + if (!empty($conf->stripe->enabled) && !empty($conf->global->STRIPE_CARD_PRESENT)) { + print ''.$langs->trans("CashDeskBankAccountForStripeTerminal").''; // Force Stripe Terminal + print ''; + $service = 'StripeTest'; + $servicestatus = 0; + if (!empty($conf->global->STRIPE_LIVE) && !GETPOST('forcesandbox', 'alpha')) { + $service = 'StripeLive'; + $servicestatus = 1; + } + global $stripearrayofkeysbyenv; + $site_account = $stripearrayofkeysbyenv[$servicestatus]['secret_key']; + \Stripe\Stripe::setApiKey($site_account); + if (!empty($conf->stripe->enabled) && (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha'))) { + $service = 'StripeTest'; + $servicestatus = '0'; + dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode', 'Stripe'), '', 'warning'); + } else { + $service = 'StripeLive'; + $servicestatus = '1'; + } + $stripe = new Stripe($db); + $stripeacc = $stripe->getStripeAccount($service); + if ($stripeacc) { + $readers = \Stripe\Terminal\Reader::all('', array("location" => $conf->global->STRIPE_LOCATION, "stripe_account" => $stripeacc)); + } else { + $readers = \Stripe\Terminal\Reader::all('', array("location" => $conf->global->STRIPE_LOCATION)); + } + + $reader = array(); + $reader[""] = $langs->trans("NoReader"); + foreach ($readers as $readers) { + $reader[$reader->id] = $readers->label.' ('.$readers->status.')'; + } + print $form->selectarray('CASHDESK_ID_BANKACCOUNT_STRIPETERMINAL'.$terminaltouse, $reader, $conf->global->{'CASHDESK_ID_BANKACCOUNT_STRIPETERMINAL'.$terminaltouse}); + print ''; + } + if ($conf->global->TAKEPOS_ENABLE_SUMUP) { print ''.$langs->trans("CashDeskBankAccountForSumup").''; print ''; diff --git a/htdocs/takepos/pay.php b/htdocs/takepos/pay.php index 40d873654c6..cc1d335272d 100644 --- a/htdocs/takepos/pay.php +++ b/htdocs/takepos/pay.php @@ -1,5 +1,6 @@ + * Copyright (C) 2021 Thibault FOUCART * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -40,6 +41,7 @@ if (!defined('NOREQUIREHTML')) { require '../main.inc.php'; // Load $user and permissions require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; +require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; $langs->loadLangs(array("main", "bills", "cashdesk", "banks")); @@ -51,11 +53,60 @@ if (empty($user->rights->takepos->run)) { accessforbidden(); } +if (!empty($conf->stripe->enabled)) { + $service = 'StripeTest'; + $servicestatus = 0; + if (!empty($conf->global->STRIPE_LIVE) && !GETPOST('forcesandbox', 'alpha')) { + $service = 'StripeLive'; + $servicestatus = 1; + } + + // Force to use the correct API key + global $stripearrayofkeysbyenv; + $site_account = $stripearrayofkeysbyenv[$servicestatus]['publishable_key']; + + $stripe = new Stripe($db); + $stripeacc = $stripe->getStripeAccount($service); // Get Stripe OAuth connect account (no remote access to Stripe here) + $stripecu = $stripe->getStripeCustomerAccount($object->id, $servicestatus, $site_account); // Get remote Stripe customer 'cus_...' (no remote access to Stripe here) + $keyforstripeterminalbank = "CASHDESK_ID_BANKACCOUNT_STRIPETERMINAL".$_SESSION["takeposterminal"]; + ?> + + +stripe->enabled) && (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha'))) { + dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode', 'Stripe'), '', 'warning', 1); +} + $invoice = new Facture($db); if ($invoiceid > 0) { $invoice->fetch($invoiceid); @@ -73,6 +124,57 @@ if ($invoiceid > 0) { } } +?> + +global->TAKEPOS_NUMPAD == 0) { }); } + function fetchPaymentIntentClientSecret(amount, invoiceid) { + const bodyContent = JSON.stringify({ amount : amount, invoiceid : invoiceid }); + + return fetch('', { + method: "POST", + headers: { + 'Content-Type': 'application/json' + }, + body: bodyContent + }) + .then(function(response) { + return response.json(); + }) + .then(function(data) { + return data.client_secret; + }); + } + + + function capturePaymentIntent(paymentIntentId) { + const bodyContent = JSON.stringify({"id": paymentIntentId}) + + return fetch('', { + method: "POST", + headers: { + 'Content-Type': 'application/json' + }, + body: bodyContent + }) + .then(function(response) { + return response.json(); + }) + .then(function(data) { + return data.client_secret; + }); + } + + + function ValidateStripeTerminal() { + console.log("Launch ValidateStripeTerminal"); + var invoiceid = 0 ? $invoiceid : 0); ?>; + var accountid = $("#selectaccountid").val(); + var amountpayed = $("#change1").val(); + var excess = $("#change2").val(); + if (amountpayed > getRemainToPay(); ?>) { + amountpayed = getRemainToPay(); ?>; + } + if (amountpayed == 0) { + amountpayed = getRemainToPay(); ?>; + } + + console.log("Pay with terminal ", amountpayed); + + fetchPaymentIntentClientSecret(amountpayed, invoiceid).then(function(client_secret) { + global->STRIPE_TERMINAL_SIMULATED)) { ?> + terminal.setSimulatorConfiguration({testCardNumber: 'global->STRIPE_TERMINAL_SIMULATED; ?>'}); + + document.getElementById("card-present-alert").innerHTML = '
trans('PaymentSendToStripeTerminal'); ?>
'; + terminal.collectPaymentMethod(client_secret).then(function(result) { + if (result.error) { + // Placeholder for handling result.error + document.getElementById("card-present-alert").innerHTML = '
'+result.error.message+'
'; + } else { + document.getElementById("card-present-alert").innerHTML = '
trans('PaymentBeingProcessed'); ?>
'; + console.log('terminal.collectPaymentMethod', result.paymentIntent); + terminal.processPayment(result.paymentIntent).then(function(result) { + if (result.error) { + document.getElementById("card-present-alert").innerHTML = '
'+result.error.message+'
'; + console.log(result.error) + } else if (result.paymentIntent) { + paymentIntentId = result.paymentIntent.id; + console.log('terminal.processPayment', result.paymentIntent); + capturePaymentIntent(paymentIntentId).then(function(client_secret) { + if (result.error) { + // Placeholder for handling result.error + document.getElementById("card-present-alert").innerHTML = '
'+result.error.message+'
'; + console.log("error when capturing paymentIntent", result.error); + } else { + document.getElementById("card-present-alert").innerHTML = '
trans('PaymentValidated'); ?>
'; + console.log("Capture paymentIntent successfull "+paymentIntentId); + parent.$("#poslines").load("invoice.php?place=&action=valid&pay=CB&amount="+amountpayed+"&excess="+excess+"&invoiceid="+invoiceid+"&accountid="+accountid, function() { + if (amountpayed > || amountpayed == || amountpayed==0 ) { + console.log("Close popup"); + parent.$.colorbox.close(); + } + else { + console.log("Amount is not comple, so we do NOT close popup and reload it."); + location.reload(); + } + }); + + } + }); + } + }); + } + }); + }); + } + function ValidateSumup() { console.log("Launch ValidateSumup"); @@ -271,7 +479,7 @@ if (!empty($conf->global->TAKEPOS_CUSTOMER_DISPLAY)) { ?> -
+
trans('TotalTTC'); ?>: total_ttc, 1, '', 1, -1, -1, $invoice->multicurrency_code); ?>
@@ -299,7 +507,6 @@ if (!empty($conf->global->TAKEPOS_CUSTOMER_DISPLAY)) { } ?>
-
global->TAKEPOS_NUMPAD; - +if (!empty($conf->stripe->enabled) && !empty($conf->global->STRIPE_CARD_PRESENT)) { + print ''; + dol_htmloutput_mesg($langs->trans('ConnectingToStripeTerminal', 'Stripe'), '', 'warning', 1); + print ''; +} print ''; print ''; print ''; @@ -424,8 +635,18 @@ while ($i < count($arrayOfValidPaymentModes)) { $i = $i + 1; } -$keyforsumupbank = "CASHDESK_ID_BANKACCOUNT_SUMUP".$_SESSION["takeposterminal"]; +if (!empty($conf->stripe->enabled) && !empty($conf->global->STRIPE_CARD_PRESENT)) { + $keyforstripeterminalbank = "CASHDESK_ID_BANKACCOUNT_STRIPETERMINAL".$_SESSION["takeposterminal"]; + print ''; + if (!empty($conf->global->$keyforstripeterminalbank)) { + } else { + $langs->loadLangs(array("errors", "admin")); + //print ''; + } +} + if ($conf->global->TAKEPOS_ENABLE_SUMUP) { + $keyforsumupbank = "CASHDESK_ID_BANKACCOUNT_SUMUP".$_SESSION["takeposterminal"]; if (!empty($conf->global->$keyforsumupbank)) { print ''; } else { From 627f3469336d636ea1f1a9d52c2a3231117c8463 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sun, 12 Jun 2022 21:40:21 +0200 Subject: [PATCH 049/826] Update pay.php --- htdocs/takepos/pay.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/takepos/pay.php b/htdocs/takepos/pay.php index cc1d335272d..f4c1a0416b1 100644 --- a/htdocs/takepos/pay.php +++ b/htdocs/takepos/pay.php @@ -103,7 +103,7 @@ function fetchConnectionToken() { * View */ -if (!empty($conf->stripe->enabled) && (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha'))) { +if (!empty($conf->stripe->enabled) && isset($keyforstripeterminalbank) && (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha'))) { dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode', 'Stripe'), '', 'warning', 1); } @@ -524,7 +524,7 @@ $action_buttons = array( ), ); $numpad = $conf->global->TAKEPOS_NUMPAD; -if (!empty($conf->stripe->enabled) && !empty($conf->global->STRIPE_CARD_PRESENT)) { +if (!empty($conf->stripe->enabled) && isset($keyforstripeterminalbank) && !empty($conf->global->STRIPE_CARD_PRESENT)) { print ''; dol_htmloutput_mesg($langs->trans('ConnectingToStripeTerminal', 'Stripe'), '', 'warning', 1); print ''; From 87f98b5bcbeea3778a45450dfe62293bef93f042 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sun, 12 Jun 2022 21:44:17 +0200 Subject: [PATCH 050/826] Update pay.php --- htdocs/takepos/pay.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/takepos/pay.php b/htdocs/takepos/pay.php index f4c1a0416b1..f487862e895 100644 --- a/htdocs/takepos/pay.php +++ b/htdocs/takepos/pay.php @@ -635,7 +635,7 @@ while ($i < count($arrayOfValidPaymentModes)) { $i = $i + 1; } -if (!empty($conf->stripe->enabled) && !empty($conf->global->STRIPE_CARD_PRESENT)) { +if (!empty($conf->stripe->enabled) && isset($keyforstripeterminalbank) && !empty($conf->global->STRIPE_CARD_PRESENT)) { $keyforstripeterminalbank = "CASHDESK_ID_BANKACCOUNT_STRIPETERMINAL".$_SESSION["takeposterminal"]; print ''; if (!empty($conf->global->$keyforstripeterminalbank)) { From 616e6f5a8f833a27c46f5667c85f2c989fa2ed60 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Sun, 12 Jun 2022 19:46:22 +0000 Subject: [PATCH 051/826] Fixing style errors. --- htdocs/stripe/ajax/ajax.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/stripe/ajax/ajax.php b/htdocs/stripe/ajax/ajax.php index e50b426ee87..cf6ec53d580 100644 --- a/htdocs/stripe/ajax/ajax.php +++ b/htdocs/stripe/ajax/ajax.php @@ -92,13 +92,13 @@ if ($action == 'getConnexionToken') { $fulltag='INV='.$object->id.'.CUS='.$object->thirdparty->id; $tag=null; - $fulltag=dol_string_unaccent($fulltag); + $fulltag=dol_string_unaccent($fulltag); $stripe = new Stripe($db); $customer = $stripe->customerStripe($object->thirdparty, $stripeacc, $servicestatus, 1); $intent = $stripe->getPaymentIntent($json_obj->amount, $object->multicurrency_code, null, 'Stripe payment: '.$fulltag.(is_object($object)?' ref='.$object->ref:''), $object, $customer, $stripeacc, $servicestatus, 1, 'terminal', false, null, 0, 1); - + echo json_encode(array('client_secret' => $intent->client_secret)); } catch (Error $e) { http_response_code(500); From b6bd8b3619a021de46e825f45c31bab31652161a Mon Sep 17 00:00:00 2001 From: BENKE Charlene <1179011+defrance@users.noreply.github.com> Date: Mon, 13 Jun 2022 08:20:29 +0200 Subject: [PATCH 052/826] php V8 warning --- htdocs/admin/modulehelp.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/admin/modulehelp.php b/htdocs/admin/modulehelp.php index 0c53bebfc52..0cf59831ae6 100644 --- a/htdocs/admin/modulehelp.php +++ b/htdocs/admin/modulehelp.php @@ -1,6 +1,7 @@ * Copyright (C) 2017 Regis Houssin + * Copyright (C) 2022 Charlene Benke * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -266,7 +267,7 @@ if ($ip) { $text .= '
'.$langs->trans("LastActivationIP").': '; $text .= $ip; } -$lastactivationversion = (empty($tmp['lastactivationversion']) ? '' : $tmp['lastactivationversion']); +$lastactivationversion = (empty($tmp['lastactivationversion']) ? '' : $tmp['lastactivationversion'][0]); if ($lastactivationversion) { $text .= '
'.$langs->trans("LastActivationVersion").': '; $text .= $lastactivationversion; @@ -505,7 +506,7 @@ if ($mode == 'feature') { $text .= '
'; $text .= '
'.$langs->trans("AddHooks").': '; - if (isset($objMod->module_parts) && is_array($objMod->module_parts['hooks']) && count($objMod->module_parts['hooks'])) { + if (isset($objMod->module_parts['hooks']) && is_array($objMod->module_parts['hooks']) && count($objMod->module_parts['hooks'])) { $i = 0; foreach ($objMod->module_parts['hooks'] as $key => $val) { if ($key === 'entity') { From 0e72085be681eaf485080490fddea2cc76973007 Mon Sep 17 00:00:00 2001 From: jpb Date: Mon, 13 Jun 2022 08:36:17 +0200 Subject: [PATCH 053/826] add trads on form fields --- htdocs/holiday/card_group.php | 11 +++++++---- htdocs/langs/en_US/holiday.lang | 2 ++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/htdocs/holiday/card_group.php b/htdocs/holiday/card_group.php index 9655bb24320..5dee6e54f6c 100644 --- a/htdocs/holiday/card_group.php +++ b/htdocs/holiday/card_group.php @@ -209,8 +209,9 @@ if (empty($reshook)) { } // If no groups and no users if (empty($groups) && empty($users)) { - setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("User")), null, 'errors'); - setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Group")), null, 'errors'); + setEventMessages($langs->trans("ErrorFieldRequiredUserOrGroup"), null, 'errors'); + //setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("UserOrGroup")), null, 'errors'); + //setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Group")), null, 'errors'); $error++; $action = 'create'; } @@ -486,7 +487,8 @@ if ((empty($id) && empty($ref)) || $action == 'create' || $action == 'add') { // groupe print ''; - print ''.$langs->trans("groups"); + print ''; + print $form->textwithpicto($langs->trans("groups"), $langs->trans("fusionGroupsUsers")); print ''; @@ -505,7 +507,8 @@ if ((empty($id) && empty($ref)) || $action == 'create' || $action == 'add') { // users print ''; - print ''.$langs->trans("users").''; + print ''; + print $form->textwithpicto($langs->trans("users"), $langs->trans("fusionGroupsUsers")); print ''; $sql = ' SELECT DISTINCT u.rowid,u.lastname,u.firstname from '.MAIN_DB_PREFIX.'user as u'; diff --git a/htdocs/langs/en_US/holiday.lang b/htdocs/langs/en_US/holiday.lang index 2005d7e613c..36f1e839e67 100644 --- a/htdocs/langs/en_US/holiday.lang +++ b/htdocs/langs/en_US/holiday.lang @@ -80,6 +80,8 @@ MotifCP=Reason UserCP=User ErrorAddEventToUserCP=An error occurred while adding the exceptional leave. AddEventToUserOkCP=The addition of the exceptional leave has been completed. +ErrorFieldRequiredUserOrGroup=The "group" field or the "user" field must be filled in +fusionGroupsUsers=The groups field and the user field will be merged MenuLogCP=View change logs LogCP=Log of all updates made to "Balance of Leave" ActionByCP=Updated by From 2209d31b2c6666cdd7917c48cedf80f5cf7e5819 Mon Sep 17 00:00:00 2001 From: jpb Date: Mon, 13 Jun 2022 08:51:49 +0200 Subject: [PATCH 054/826] add comment on function --- htdocs/holiday/card_group.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/htdocs/holiday/card_group.php b/htdocs/holiday/card_group.php index 5dee6e54f6c..f244c6374e5 100644 --- a/htdocs/holiday/card_group.php +++ b/htdocs/holiday/card_group.php @@ -655,11 +655,11 @@ if (is_object($db)) { } /** * send email to validator for current leave represented by (id) - * @param $id - * @param $cancreate - * @param $now - * @param $autoValidation - * @return string|void + * @param $id validator for current leave represented by (id) + * @param $cancreate flag for user right + * @param $now date + * @param $autoValidation boolean flag on autovalidation + * @return stdClass * @throws Exception */ function sendMail($id, $cancreate, $now, $autoValidation) From af0846e2f7b22e129628ee699b9dcb1ab6e00ccc Mon Sep 17 00:00:00 2001 From: jpb Date: Mon, 13 Jun 2022 09:09:19 +0200 Subject: [PATCH 055/826] add sanitize to sql --- htdocs/holiday/card_group.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/holiday/card_group.php b/htdocs/holiday/card_group.php index f244c6374e5..8de636da6c8 100644 --- a/htdocs/holiday/card_group.php +++ b/htdocs/holiday/card_group.php @@ -264,7 +264,7 @@ if (empty($reshook)) { /** GROUPS */ $sql = ' SELECT DISTINCT u.rowid,u.lastname,u.firstname from ' . MAIN_DB_PREFIX . 'user as u'; $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'usergroup_user as ug on ug.fk_user = u.rowid '; - $sql .= ' WHERE fk_usergroup in (' . implode(',', $groups) . ')'; + $sql .= ' WHERE fk_usergroup in (' .$this->db->sanitize(implode(',', $groups)) . ')'; $resql = $db->query($sql); if ($resql) { @@ -423,7 +423,7 @@ if ((empty($id) && empty($ref)) || $action == 'create' || $action == 'add') { } $("input[name=autoValidation]").click( function(e) { - console.log("chang") + if( $("input[name=autoValidation]").is(":checked") ){ $("#AutoSendMail").prop("disabled", false); From d7ca52f4ef996b9711a321823da0e19c11730d0d Mon Sep 17 00:00:00 2001 From: jpb Date: Mon, 13 Jun 2022 09:17:19 +0200 Subject: [PATCH 056/826] remove $this on sanitize --- htdocs/holiday/card_group.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/holiday/card_group.php b/htdocs/holiday/card_group.php index 8de636da6c8..b63a3ae657b 100644 --- a/htdocs/holiday/card_group.php +++ b/htdocs/holiday/card_group.php @@ -264,7 +264,7 @@ if (empty($reshook)) { /** GROUPS */ $sql = ' SELECT DISTINCT u.rowid,u.lastname,u.firstname from ' . MAIN_DB_PREFIX . 'user as u'; $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'usergroup_user as ug on ug.fk_user = u.rowid '; - $sql .= ' WHERE fk_usergroup in (' .$this->db->sanitize(implode(',', $groups)) . ')'; + $sql .= ' WHERE fk_usergroup in (' .$db->sanitize(implode(',', $groups)) . ')'; $resql = $db->query($sql); if ($resql) { From 09c5b8be79204817c5fc359df27b7690a6de7f19 Mon Sep 17 00:00:00 2001 From: jpb Date: Mon, 13 Jun 2022 10:38:49 +0200 Subject: [PATCH 057/826] add comment --- htdocs/holiday/card_group.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/holiday/card_group.php b/htdocs/holiday/card_group.php index b63a3ae657b..5e571f077c8 100644 --- a/htdocs/holiday/card_group.php +++ b/htdocs/holiday/card_group.php @@ -261,6 +261,7 @@ if (empty($reshook)) { if (!$error) { $TusersToProcess = array(); // usergroup select + // better perf on single sql /** GROUPS */ $sql = ' SELECT DISTINCT u.rowid,u.lastname,u.firstname from ' . MAIN_DB_PREFIX . 'user as u'; $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'usergroup_user as ug on ug.fk_user = u.rowid '; From dddd4186a864b53574b61d65d850c28ccf5c2fb0 Mon Sep 17 00:00:00 2001 From: lvessiller Date: Mon, 13 Jun 2022 15:37:43 +0200 Subject: [PATCH 058/826] NEW show product label on inventory --- htdocs/core/class/commonobject.class.php | 11 ++++++++- .../fourn/class/fournisseur.product.class.php | 20 ++++++++++++---- htdocs/product/class/product.class.php | 24 ++++++++++++------- .../inventory/class/inventory.class.php | 2 +- 4 files changed, 41 insertions(+), 16 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 1f64741385f..1f258fa2ba4 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -7556,11 +7556,20 @@ abstract class CommonObject if ($classname && class_exists($classname)) { $object = new $classname($this->db); if ($object->element === 'product') { // Special cas for product because default valut of fetch are wrong + $getnomurlparam3 = (!isset($InfoFieldList[5]) ? 0 : $InfoFieldList[5]); + $getnomurlparam4 = (!isset($InfoFieldList[6]) ? -1 : $InfoFieldList[6]); + $getnomurlparam5 = (!isset($InfoFieldList[7]) ? 0 : $InfoFieldList[7]); + $getnomurlparam6 = (!isset($InfoFieldList[8]) ? 0 : $InfoFieldList[8]); + + /** + * @var Product $object + */ $object->fetch($value, '', '', '', 0, 1, 1); + $value = $object->getNomUrl($getnomurlparam, $getnomurlparam2, $getnomurlparam3, $getnomurlparam4, $getnomurlparam5, $getnomurlparam6); } else { $object->fetch($value); + $value = $object->getNomUrl($getnomurlparam, $getnomurlparam2); } - $value = $object->getNomUrl($getnomurlparam, $getnomurlparam2); } } else { dol_syslog('Error bad setup of extrafield', LOG_WARNING); diff --git a/htdocs/fourn/class/fournisseur.product.class.php b/htdocs/fourn/class/fournisseur.product.class.php index d113eadd8a7..774dd192659 100644 --- a/htdocs/fourn/class/fournisseur.product.class.php +++ b/htdocs/fourn/class/fournisseur.product.class.php @@ -1091,12 +1091,15 @@ class ProductFournisseur extends Product * * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto) * @param string $option On what the link point to ('nolink', ...) - * @param int $notooltip 1=Disable tooltip - * @param string $morecss Add more css on link + * @param int $maxlength Maxlength of ref * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking + * @param int $notooltip No tooltip + * @param int $add_label 0=Default, 1=Add label into string, >1=Add first chars into string + * @param string $sep ' - '=Separator between ref and label if option 'add_label' is set + * @param string $morecss ''=Add more css on link * @return string String with URL */ - public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1) + public function getNomUrl($withpicto = 0, $option = '', $maxlength = 0, $save_lastsearch_value = -1, $notooltip = 0, $add_label = 0, $sep = ' - ', $morecss = '') { global $db, $conf, $langs, $hookmanager; @@ -1107,6 +1110,11 @@ class ProductFournisseur extends Product $result = ''; $label = ''; + $newref = $this->ref; + if ($maxlength) { + $newref = dol_trunc($newref, $maxlength, 'middle'); + } + if (!empty($this->entity)) { $tmpphoto = $this->show_photos('product', $conf->product->multidir_output[$this->entity], 1, 1, 0, 0, 0, 80); if ($this->nbphoto > 0) { @@ -1228,10 +1236,12 @@ class ProductFournisseur extends Product $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); } if ($withpicto != 2) { - $result .= $this->ref.($this->ref_supplier ? ' ('.$this->ref_supplier.')' : ''); + $result .= $newref.($this->ref_supplier ? ' ('.$this->ref_supplier.')' : ''); } $result .= $linkend; - //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : ''); + if ($withpicto != 2) { + $result .= (($add_label && $this->label) ? $sep.dol_trunc($this->label, ($add_label > 1 ? $add_label : 0)) : ''); + } global $action; $hookmanager->initHooks(array($this->element . 'dao')); diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 5a7990cd0a7..c5eb211de2c 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -4882,14 +4882,17 @@ class Product extends CommonObject /** * Return clicable link of object (with eventually picto) * - * @param int $withpicto Add picto into link - * @param string $option Where point the link ('stock', 'composition', 'category', 'supplier', '') - * @param int $maxlength Maxlength of ref - * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking - * @param int $notooltip No tooltip - * @return string String with URL + * @param int $withpicto Add picto into link + * @param string $option Where point the link ('stock', 'composition', 'category', 'supplier', '') + * @param int $maxlength Maxlength of ref + * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking + * @param int $notooltip No tooltip + * @param int $add_label 0=Default, 1=Add label into string, >1=Add first chars into string + * @param string $sep ' - '=Separator between ref and label if option 'add_label' is set + * @param string $morecss ''=Add more css on link + * @return string String with URL */ - public function getNomUrl($withpicto = 0, $option = '', $maxlength = 0, $save_lastsearch_value = -1, $notooltip = 0) + public function getNomUrl($withpicto = 0, $option = '', $maxlength = 0, $save_lastsearch_value = -1, $notooltip = 0, $add_label = 0, $sep = ' - ', $morecss = '') { global $conf, $langs, $hookmanager; include_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php'; @@ -4997,9 +5000,9 @@ class Product extends CommonObject } $linkclose .= ' title="'.dol_escape_htmltag($label, 1, 1).'"'; - $linkclose .= ' class="nowraponall classfortooltip"'; + $linkclose .= ' class="nowraponall classfortooltip'.($morecss ? ' '.$morecss : '').'"'; } else { - $linkclose = ' class="nowraponall"'; + $linkclose = ' class="nowraponall'.($morecss ? ' '.$morecss : '').'"'; } if ($option == 'supplier' || $option == 'category') { @@ -5038,6 +5041,9 @@ class Product extends CommonObject } $result .= $newref; $result .= $linkend; + if ($withpicto != 2) { + $result .= (($add_label && $this->label) ? $sep.dol_trunc($this->label, ($add_label > 1 ? $add_label : 0)) : ''); + } global $action; $hookmanager->initHooks(array('productdao')); diff --git a/htdocs/product/inventory/class/inventory.class.php b/htdocs/product/inventory/class/inventory.class.php index 80823c7ba5a..c755b92b3e4 100644 --- a/htdocs/product/inventory/class/inventory.class.php +++ b/htdocs/product/inventory/class/inventory.class.php @@ -101,7 +101,7 @@ class Inventory extends CommonObject 'entity' => array('type'=>'integer', 'label'=>'Entity', 'visible'=>0, 'enabled'=>1, 'position'=>20, 'notnull'=>1, 'index'=>1,), 'title' => array('type'=>'varchar(255)', 'label'=>'Label', 'visible'=>1, 'enabled'=>1, 'position'=>25, 'css'=>'minwidth300', 'csslist'=>'tdoverflowmax200'), 'fk_warehouse' => array('type'=>'integer:Entrepot:product/stock/class/entrepot.class.php', 'label'=>'Warehouse', 'visible'=>1, 'enabled'=>1, 'position'=>30, 'index'=>1, 'help'=>'InventoryForASpecificWarehouse', 'picto'=>'stock', 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'csslist'=>'tdoverflowmax200'), - 'fk_product' => array('type'=>'integer:Product:product/class/product.class.php', 'label'=>'Product', 'visible'=>1, 'enabled'=>1, 'position'=>32, 'index'=>1, 'help'=>'InventoryForASpecificProduct', 'picto'=>'product', 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'csslist'=>'tdoverflowmax200'), + 'fk_product' => array('type'=>'integer:Product:product/class/product.class.php::::0:-1:0:1', 'label'=>'Product', 'visible'=>1, 'enabled'=>1, 'position'=>32, 'index'=>1, 'help'=>'InventoryForASpecificProduct', 'picto'=>'product', 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'csslist'=>'tdoverflowmax200'), 'date_inventory' => array('type'=>'date', 'label'=>'DateValue', 'visible'=>1, 'enabled'=>'$conf->global->STOCK_INVENTORY_ADD_A_VALUE_DATE', 'position'=>35), // This date is not used so disabled by default. 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>500), 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>501), From 65d20bdc61e512f924a6cc6ad3eea9cd30e0f4ae Mon Sep 17 00:00:00 2001 From: lvessiller Date: Thu, 16 Jun 2022 12:06:06 +0200 Subject: [PATCH 059/826] NEW add attached file in presend email form of thirdparty card --- htdocs/core/tpl/card_presend.tpl.php | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/htdocs/core/tpl/card_presend.tpl.php b/htdocs/core/tpl/card_presend.tpl.php index 7b47c4676a6..9a99faef526 100644 --- a/htdocs/core/tpl/card_presend.tpl.php +++ b/htdocs/core/tpl/card_presend.tpl.php @@ -41,14 +41,16 @@ if ($action == 'presend') { $object->fetch_projet(); - if (!in_array($object->element, array('societe', 'user', 'member'))) { + $ref = dol_sanitizeFileName($object->ref); + if (!in_array($object->element, array('user', 'member'))) { // TODO get also the main_lastdoc field of $object. If not found, try to guess with following code - $ref = dol_sanitizeFileName($object->ref); include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; // Special case if ($object->element == 'invoice_supplier') { $fileparams = dol_most_recent_file($diroutput.'/'.get_exdir($object->id, 2, 0, 0, $object, $object->element).$ref, preg_quote($ref, '/').'([^\-])+'); + } elseif ($object->element == 'societe') { + $fileparams = dol_most_recent_file($diroutput.'/'.$ref); } else { $fileparams = dol_most_recent_file($diroutput.'/'.$ref, preg_quote($ref, '/').'[^\-]+'); } @@ -82,12 +84,15 @@ if ($action == 'presend') { // Build document if it not exists $forcebuilddoc = true; - if (in_array($object->element, array('societe', 'user', 'member'))) { + if (in_array($object->element, array('user', 'member'))) { $forcebuilddoc = false; } if ($object->element == 'invoice_supplier' && empty($conf->global->INVOICE_SUPPLIER_ADDON_PDF)) { $forcebuilddoc = false; } + if ($object->element == 'societe' && empty($conf->global->COMPANY_ADDON_PDF)) { + $forcebuilddoc = false; + } if ($forcebuilddoc) { // If there is no default value for supplier invoice, we do not generate file, even if modelpdf was set by a manual generation if ((!$file || !is_readable($file)) && method_exists($object, 'generateDocument')) { $result = $object->generateDocument(GETPOST('model') ? GETPOST('model') : $object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref); @@ -97,6 +102,8 @@ if ($action == 'presend') { } if ($object->element == 'invoice_supplier') { $fileparams = dol_most_recent_file($diroutput.'/'.get_exdir($object->id, 2, 0, 0, $object, $object->element).$ref, preg_quote($ref, '/').'([^\-])+'); + } elseif ($object->element == 'societe') { + $fileparams = dol_most_recent_file($diroutput.'/'.$ref); } else { $fileparams = dol_most_recent_file($diroutput.'/'.$ref, preg_quote($ref, '/').'[^\-]+'); } From 61a9521e3c7f48ac29e4df7bec471c586eecb0e3 Mon Sep 17 00:00:00 2001 From: lvessiller Date: Fri, 17 Jun 2022 17:32:22 +0200 Subject: [PATCH 060/826] NEW Changelog and reorder getNomUrl parameters --- ChangeLog | 7 +++++++ htdocs/core/class/commonobject.class.php | 5 +++-- htdocs/fourn/class/fournisseur.product.class.php | 4 ++-- htdocs/product/class/product.class.php | 4 ++-- htdocs/product/inventory/class/inventory.class.php | 2 +- 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 37957f61c1d..5813c185885 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,13 @@ English Dolibarr ChangeLog -------------------------------------------------------------- +***** ChangeLog for 17.0.0 compared to 16.0.0 ***** + +For developers or integrators: +------------------------------ + +Following changes may create regressions for some external modules, but were necessary to make Dolibarr better: +* The signature of method getNomUrl() of class ProductFournisseur has been modified to match the signature of method Product ***** ChangeLog for 16.0.0 compared to 15.0.0 ***** diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 10b6fd5e690..a9b7edf6078 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -7565,12 +7565,13 @@ abstract class CommonObject $getnomurlparam3 = (!isset($InfoFieldList[5]) ? 0 : $InfoFieldList[5]); $getnomurlparam4 = (!isset($InfoFieldList[6]) ? -1 : $InfoFieldList[6]); $getnomurlparam5 = (!isset($InfoFieldList[7]) ? 0 : $InfoFieldList[7]); - $getnomurlparam6 = (!isset($InfoFieldList[8]) ? 0 : $InfoFieldList[8]); + $getnomurlparam6 = (!isset($InfoFieldList[8]) ? '' : $InfoFieldList[8]); + $getnomurlparam7 = (!isset($InfoFieldList[9]) ? 0 : $InfoFieldList[9]); /** * @var Product $object */ - $value = $object->getNomUrl($getnomurlparam, $getnomurlparam2, $getnomurlparam3, $getnomurlparam4, $getnomurlparam5, $getnomurlparam6); + $value = $object->getNomUrl($getnomurlparam, $getnomurlparam2, $getnomurlparam3, $getnomurlparam4, $getnomurlparam5, $getnomurlparam6, $getnomurlparam7); } else { $value = $object->getNomUrl($getnomurlparam, $getnomurlparam2); } diff --git a/htdocs/fourn/class/fournisseur.product.class.php b/htdocs/fourn/class/fournisseur.product.class.php index 774dd192659..349a317b1d2 100644 --- a/htdocs/fourn/class/fournisseur.product.class.php +++ b/htdocs/fourn/class/fournisseur.product.class.php @@ -1094,12 +1094,12 @@ class ProductFournisseur extends Product * @param int $maxlength Maxlength of ref * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking * @param int $notooltip No tooltip + * @param string $morecss ''=Add more css on link * @param int $add_label 0=Default, 1=Add label into string, >1=Add first chars into string * @param string $sep ' - '=Separator between ref and label if option 'add_label' is set - * @param string $morecss ''=Add more css on link * @return string String with URL */ - public function getNomUrl($withpicto = 0, $option = '', $maxlength = 0, $save_lastsearch_value = -1, $notooltip = 0, $add_label = 0, $sep = ' - ', $morecss = '') + public function getNomUrl($withpicto = 0, $option = '', $maxlength = 0, $save_lastsearch_value = -1, $notooltip = 0, $morecss = '', $add_label = 0, $sep = ' - ') { global $db, $conf, $langs, $hookmanager; diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index c5eb211de2c..c268929d59c 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -4887,12 +4887,12 @@ class Product extends CommonObject * @param int $maxlength Maxlength of ref * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking * @param int $notooltip No tooltip + * @param string $morecss ''=Add more css on link * @param int $add_label 0=Default, 1=Add label into string, >1=Add first chars into string * @param string $sep ' - '=Separator between ref and label if option 'add_label' is set - * @param string $morecss ''=Add more css on link * @return string String with URL */ - public function getNomUrl($withpicto = 0, $option = '', $maxlength = 0, $save_lastsearch_value = -1, $notooltip = 0, $add_label = 0, $sep = ' - ', $morecss = '') + public function getNomUrl($withpicto = 0, $option = '', $maxlength = 0, $save_lastsearch_value = -1, $notooltip = 0, $morecss = '', $add_label = 0, $sep = ' - ') { global $conf, $langs, $hookmanager; include_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php'; diff --git a/htdocs/product/inventory/class/inventory.class.php b/htdocs/product/inventory/class/inventory.class.php index c755b92b3e4..ddf7d582fba 100644 --- a/htdocs/product/inventory/class/inventory.class.php +++ b/htdocs/product/inventory/class/inventory.class.php @@ -101,7 +101,7 @@ class Inventory extends CommonObject 'entity' => array('type'=>'integer', 'label'=>'Entity', 'visible'=>0, 'enabled'=>1, 'position'=>20, 'notnull'=>1, 'index'=>1,), 'title' => array('type'=>'varchar(255)', 'label'=>'Label', 'visible'=>1, 'enabled'=>1, 'position'=>25, 'css'=>'minwidth300', 'csslist'=>'tdoverflowmax200'), 'fk_warehouse' => array('type'=>'integer:Entrepot:product/stock/class/entrepot.class.php', 'label'=>'Warehouse', 'visible'=>1, 'enabled'=>1, 'position'=>30, 'index'=>1, 'help'=>'InventoryForASpecificWarehouse', 'picto'=>'stock', 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'csslist'=>'tdoverflowmax200'), - 'fk_product' => array('type'=>'integer:Product:product/class/product.class.php::::0:-1:0:1', 'label'=>'Product', 'visible'=>1, 'enabled'=>1, 'position'=>32, 'index'=>1, 'help'=>'InventoryForASpecificProduct', 'picto'=>'product', 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'csslist'=>'tdoverflowmax200'), + 'fk_product' => array('type'=>'integer:Product:product/class/product.class.php::::0:-1:0::1', 'label'=>'Product', 'visible'=>1, 'enabled'=>1, 'position'=>32, 'index'=>1, 'help'=>'InventoryForASpecificProduct', 'picto'=>'product', 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'csslist'=>'tdoverflowmax200'), 'date_inventory' => array('type'=>'date', 'label'=>'DateValue', 'visible'=>1, 'enabled'=>'$conf->global->STOCK_INVENTORY_ADD_A_VALUE_DATE', 'position'=>35), // This date is not used so disabled by default. 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>500), 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>501), From 82cfca1a80d04e883fbcc6658246042c67aeeafa Mon Sep 17 00:00:00 2001 From: Yoan Mollard Date: Sun, 19 Jun 2022 00:48:06 +0200 Subject: [PATCH 061/826] Filter accounting reports by projects --- htdocs/compta/accounting-files.php | 44 ++++++++++++++++++++++++++--- htdocs/langs/en_US/accountancy.lang | 3 +- htdocs/langs/en_US/projects.lang | 3 +- htdocs/projet/card.php | 11 ++++++++ 4 files changed, 55 insertions(+), 6 deletions(-) diff --git a/htdocs/compta/accounting-files.php b/htdocs/compta/accounting-files.php index 996ad22fbce..88dd1c317f2 100644 --- a/htdocs/compta/accounting-files.php +++ b/htdocs/compta/accounting-files.php @@ -47,6 +47,11 @@ require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/paymentvarious.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; require_once DOL_DOCUMENT_ROOT.'/loan/class/paymentloan.class.php'; +if (!empty($conf->project->enabled)) { + require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php'; +} + // Constant to define payment sens const PAY_DEBIT = 0; const PAY_CREDIT = 1; @@ -64,6 +69,7 @@ $date_stopMonth = GETPOST('date_stopmonth', 'int'); $date_stopYear = GETPOST('date_stopyear', 'int'); $date_stop = dol_mktime(23, 59, 59, $date_stopMonth, $date_stopDay, $date_stopYear, 'tzuserrel'); $action = GETPOST('action', 'aZ09'); +$projectid = (GETPOST('projectid', 'int') ? GETPOST('projectid', 'int') : 0); // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context $hookmanager->initHooks(array('comptafileslist', 'globallist')); @@ -175,6 +181,7 @@ if (($action == 'searchfiles' || $action == 'dl')) { $sql .= " WHERE datef between ".$wheretail; $sql .= " AND t.entity IN (".$db->sanitize($entity == 1 ? '0,1' : $entity).')'; $sql .= " AND t.fk_statut <> ".Facture::STATUS_DRAFT; + if(!empty($projectid)) $sql .= " AND fk_projet = ".$db->sanitize($projectid); } // Vendor invoices if (GETPOST('selectsupplierinvoices') && !empty($listofchoices['selectsupplierinvoices']['perms'])) { @@ -186,9 +193,10 @@ if (($action == 'searchfiles' || $action == 'dl')) { $sql .= " WHERE datef between ".$wheretail; $sql .= " AND t.entity IN (".$db->sanitize($entity == 1 ? '0,1' : $entity).')'; $sql .= " AND t.fk_statut <> ".FactureFournisseur::STATUS_DRAFT; + if(!empty($projectid)) $sql .= " AND fk_projet = ".$db->sanitize($projectid); } // Expense reports - if (GETPOST('selectexpensereports') && !empty($listofchoices['selectexpensereports']['perms'])) { + if (GETPOST('selectexpensereports') && !empty($listofchoices['selectexpensereports']['perms']) and empty($projectid)) { if (!empty($sql)) { $sql .= " UNION ALL"; } @@ -208,6 +216,7 @@ if (($action == 'searchfiles' || $action == 'dl')) { $sql .= " WHERE datedon between ".$wheretail; $sql .= " AND t.entity IN (".$db->sanitize($entity == 1 ? '0,1' : $entity).')'; $sql .= " AND t.fk_statut <> ".Don::STATUS_DRAFT; + if(!empty($projectid)) $sql .= " AND fk_projet = ".$db->sanitize($projectid); } // Payments of salaries if (GETPOST('selectpaymentsofsalaries') && !empty($listofchoices['selectpaymentsofsalaries']['perms'])) { @@ -219,6 +228,7 @@ if (($action == 'searchfiles' || $action == 'dl')) { $sql .= " WHERE datep between ".$wheretail; $sql .= " AND t.entity IN (".$db->sanitize($entity == 1 ? '0,1' : $entity).')'; //$sql.=" AND fk_statut <> ".PaymentSalary::STATUS_DRAFT; + if(!empty($projectid)) $sql .= " AND fk_projet = ".$db->sanitize($projectid); } // Social contributions if (GETPOST('selectsocialcontributions') && !empty($listofchoices['selectsocialcontributions']['perms'])) { @@ -230,6 +240,7 @@ if (($action == 'searchfiles' || $action == 'dl')) { $sql .= " WHERE t.date_ech between ".$wheretail; $sql .= " AND t.entity IN (".$db->sanitize($entity == 1 ? '0,1' : $entity).')'; //$sql.=" AND fk_statut <> ".ChargeSociales::STATUS_DRAFT; + if(!empty($projectid)) $sql .= " AND fk_projet = ".$db->sanitize($projectid); } // Various payments if (GETPOST('selectvariouspayment') && !empty($listofchoices['selectvariouspayment']['perms'])) { @@ -240,9 +251,10 @@ if (($action == 'searchfiles' || $action == 'dl')) { $sql .= " FROM ".MAIN_DB_PREFIX."payment_various as t"; $sql .= " WHERE datep between ".$wheretail; $sql .= " AND t.entity IN (".$db->sanitize($entity == 1 ? '0,1' : $entity).')'; + if(!empty($projectid)) $sql .= " AND fk_projet = ".$db->sanitize($projectid); } // Loan payments - if (GETPOST('selectloanspayment') && !empty($listofchoices['selectloanspayment']['perms'])) { + if (GETPOST('selectloanspayment') && !empty($listofchoices['selectloanspayment']['perms']) and empty($projectid)) { if (!empty($sql)) { $sql .= " UNION ALL"; } @@ -460,7 +472,19 @@ if ($result && $action == "dl" && !$error) { $log .= ','.$langs->transnoentitiesnoconv("Country"); $log .= ','.$langs->transnoentitiesnoconv("VATIntra"); $log .= ','.$langs->transnoentitiesnoconv("Sens")."\n"; - $zipname = $dirfortmpfile.'/'.dol_print_date($date_start, 'dayrfc', 'tzuserrel')."-".dol_print_date($date_stop, 'dayrfc', 'tzuserrel').'_export.zip'; + $zipname = $dirfortmpfile.'/'.dol_print_date($date_start, 'dayrfc', 'tzuserrel')."-".dol_print_date($date_stop, 'dayrfc', 'tzuserrel'); + if(!empty($projectid)) { + $sql = 'SELECT t.ref FROM '.MAIN_DB_PREFIX.'projet as t'; + $sql .= ' WHERE t.rowid = '.((int) $db->sanitize($projectid)); + $resql = $db->query($sql); + if ($resql) { + $obj = $db->fetch_object($resql); + $zipname .= '_'.$obj->ref; + } else { + dol_print_error($db); + } + } + $zipname .='_export.zip'; dol_delete_file($zipname); @@ -561,11 +585,13 @@ print $form->selectDate($date_stop, 'date_stop', 0, 0, 0, "", 1, 1, 0, '', '', ' print "\n"; // Export is for current company only +$socid = 0; if (!empty($conf->multicompany->enabled) && is_object($mc)) { $mc->getInfo($conf->entity); print '('.$langs->trans("Entity").' : '; print ""; if (!empty($conf->global->MULTICOMPANY_ALLOW_EXPORT_ACCOUNTING_DOC_FOR_ALL_ENTITIES)) { + $socid = $mc->id; print $mc->select_entities(GETPOSTISSET('search_entity') ? GETPOST('search_entity', 'int') : $mc->id, 'search_entity', '', false, false, false, false, true); } else { print $mc->label; @@ -576,6 +602,16 @@ if (!empty($conf->multicompany->enabled) && is_object($mc)) { print '
'; +// Project filter +if (!empty($conf->projet->enabled)) { + $formproject = new FormProjets($db); + $langs->load('projects'); + print ''.$langs->trans('Project').":"; + print img_picto('', 'project').$formproject->select_projects(($socid > 0 ? $socid : -1), $projectid, 'projectid', 0, 0, 1, 0, 0, 0, 0, '', 1, 0, ''); + print ''; + print '
'; +} + foreach ($listofchoices as $choice => $val) { if (empty($val['enabled'])) { continue; // list not qualified @@ -614,7 +650,7 @@ if (!empty($date_start) && !empty($date_stop)) { echo dol_print_date($date_start, 'day', 'tzuserrel')." - ".dol_print_date($date_stop, 'day', 'tzuserrel'); - print 'The exported ZIP file will contain the lists of requested items in CSV, as well as their attached files in their original format (PDF, ODT, DOCX...). ExportAccountingSourceDocHelp2=To export your journals, use the menu entry %s - %s. +ExportAccountingProjectHelp=Specify a project if you need an accounting report only for a specific project. Expense reports and loan payments are not included in project reports. VueByAccountAccounting=View by accounting account VueBySubAccountAccounting=View by accounting subaccount diff --git a/htdocs/langs/en_US/projects.lang b/htdocs/langs/en_US/projects.lang index e0fa85dd273..b4bd6f75d9a 100644 --- a/htdocs/langs/en_US/projects.lang +++ b/htdocs/langs/en_US/projects.lang @@ -293,4 +293,5 @@ LeadPublicFormDesc=You can enable here a public page to allow your prospects to EnablePublicLeadForm=Enable the public form for contact NewLeadbyWeb=Your message or request has been recorded. We will answer or contact your soon. NewLeadForm=New contact form -LeadFromPublicForm=Online lead from public form \ No newline at end of file +LeadFromPublicForm=Online lead from public form +ExportAccountingReportButtonLabel=Get report \ No newline at end of file diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index 0cfe126d69b..f3b60e8593c 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -1280,6 +1280,17 @@ if ($action == 'create' && $user->rights->projet->creer) { } } + // Accounting Report + $accouting_module_activated = !empty($conf->comptabilite->enabled) || !empty($conf->accounting->enabled); + if ($accouting_module_activated && $object->statut != Project::STATUS_DRAFT) { + $start = dol_getdate((int)$object->date_start); + $end = dol_getdate((int)$object->date_end); + $url = DOL_URL_ROOT.'/compta/accounting-files.php?projectid='.$object->id; + if(!empty($object->date_start)) $url .= '&date_startday='.$start['mday'].'&date_startmonth='.$start['mon'].'&date_startyear='.$start['year']; + if(!empty($object->date_end)) $url .= '&date_stopday='.$end['mday'].'&date_stopmonth='.$end['mon'].'&date_stopyear='.$end['year']; + print dolGetButtonAction('', $langs->trans('ExportAccountingReportButtonLabel'), 'default', $url, ''); + } + // Modify if ($object->statut != Project::STATUS_CLOSED && $user->rights->projet->creer) { if ($userWrite > 0) { From eb4c42e98758abd117f88afc54e60ba59e1a1405 Mon Sep 17 00:00:00 2001 From: Yoan Mollard Date: Sun, 19 Jun 2022 19:21:51 +0200 Subject: [PATCH 062/826] Fixed AND operator to standardize code --- htdocs/compta/accounting-files.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/accounting-files.php b/htdocs/compta/accounting-files.php index 88dd1c317f2..327298a033d 100644 --- a/htdocs/compta/accounting-files.php +++ b/htdocs/compta/accounting-files.php @@ -254,7 +254,7 @@ if (($action == 'searchfiles' || $action == 'dl')) { if(!empty($projectid)) $sql .= " AND fk_projet = ".$db->sanitize($projectid); } // Loan payments - if (GETPOST('selectloanspayment') && !empty($listofchoices['selectloanspayment']['perms']) and empty($projectid)) { + if (GETPOST('selectloanspayment') && !empty($listofchoices['selectloanspayment']['perms']) && empty($projectid)) { if (!empty($sql)) { $sql .= " UNION ALL"; } From 13511d983eeb1487530951b5aa232303a3cecf71 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Sun, 19 Jun 2022 17:27:15 +0000 Subject: [PATCH 063/826] Fixing style errors. --- htdocs/compta/accounting-files.php | 14 +++++++------- htdocs/projet/card.php | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/htdocs/compta/accounting-files.php b/htdocs/compta/accounting-files.php index 327298a033d..571d17bea08 100644 --- a/htdocs/compta/accounting-files.php +++ b/htdocs/compta/accounting-files.php @@ -181,7 +181,7 @@ if (($action == 'searchfiles' || $action == 'dl')) { $sql .= " WHERE datef between ".$wheretail; $sql .= " AND t.entity IN (".$db->sanitize($entity == 1 ? '0,1' : $entity).')'; $sql .= " AND t.fk_statut <> ".Facture::STATUS_DRAFT; - if(!empty($projectid)) $sql .= " AND fk_projet = ".$db->sanitize($projectid); + if (!empty($projectid)) $sql .= " AND fk_projet = ".$db->sanitize($projectid); } // Vendor invoices if (GETPOST('selectsupplierinvoices') && !empty($listofchoices['selectsupplierinvoices']['perms'])) { @@ -193,7 +193,7 @@ if (($action == 'searchfiles' || $action == 'dl')) { $sql .= " WHERE datef between ".$wheretail; $sql .= " AND t.entity IN (".$db->sanitize($entity == 1 ? '0,1' : $entity).')'; $sql .= " AND t.fk_statut <> ".FactureFournisseur::STATUS_DRAFT; - if(!empty($projectid)) $sql .= " AND fk_projet = ".$db->sanitize($projectid); + if (!empty($projectid)) $sql .= " AND fk_projet = ".$db->sanitize($projectid); } // Expense reports if (GETPOST('selectexpensereports') && !empty($listofchoices['selectexpensereports']['perms']) and empty($projectid)) { @@ -216,7 +216,7 @@ if (($action == 'searchfiles' || $action == 'dl')) { $sql .= " WHERE datedon between ".$wheretail; $sql .= " AND t.entity IN (".$db->sanitize($entity == 1 ? '0,1' : $entity).')'; $sql .= " AND t.fk_statut <> ".Don::STATUS_DRAFT; - if(!empty($projectid)) $sql .= " AND fk_projet = ".$db->sanitize($projectid); + if (!empty($projectid)) $sql .= " AND fk_projet = ".$db->sanitize($projectid); } // Payments of salaries if (GETPOST('selectpaymentsofsalaries') && !empty($listofchoices['selectpaymentsofsalaries']['perms'])) { @@ -228,7 +228,7 @@ if (($action == 'searchfiles' || $action == 'dl')) { $sql .= " WHERE datep between ".$wheretail; $sql .= " AND t.entity IN (".$db->sanitize($entity == 1 ? '0,1' : $entity).')'; //$sql.=" AND fk_statut <> ".PaymentSalary::STATUS_DRAFT; - if(!empty($projectid)) $sql .= " AND fk_projet = ".$db->sanitize($projectid); + if (!empty($projectid)) $sql .= " AND fk_projet = ".$db->sanitize($projectid); } // Social contributions if (GETPOST('selectsocialcontributions') && !empty($listofchoices['selectsocialcontributions']['perms'])) { @@ -240,7 +240,7 @@ if (($action == 'searchfiles' || $action == 'dl')) { $sql .= " WHERE t.date_ech between ".$wheretail; $sql .= " AND t.entity IN (".$db->sanitize($entity == 1 ? '0,1' : $entity).')'; //$sql.=" AND fk_statut <> ".ChargeSociales::STATUS_DRAFT; - if(!empty($projectid)) $sql .= " AND fk_projet = ".$db->sanitize($projectid); + if (!empty($projectid)) $sql .= " AND fk_projet = ".$db->sanitize($projectid); } // Various payments if (GETPOST('selectvariouspayment') && !empty($listofchoices['selectvariouspayment']['perms'])) { @@ -251,7 +251,7 @@ if (($action == 'searchfiles' || $action == 'dl')) { $sql .= " FROM ".MAIN_DB_PREFIX."payment_various as t"; $sql .= " WHERE datep between ".$wheretail; $sql .= " AND t.entity IN (".$db->sanitize($entity == 1 ? '0,1' : $entity).')'; - if(!empty($projectid)) $sql .= " AND fk_projet = ".$db->sanitize($projectid); + if (!empty($projectid)) $sql .= " AND fk_projet = ".$db->sanitize($projectid); } // Loan payments if (GETPOST('selectloanspayment') && !empty($listofchoices['selectloanspayment']['perms']) && empty($projectid)) { @@ -473,7 +473,7 @@ if ($result && $action == "dl" && !$error) { $log .= ','.$langs->transnoentitiesnoconv("VATIntra"); $log .= ','.$langs->transnoentitiesnoconv("Sens")."\n"; $zipname = $dirfortmpfile.'/'.dol_print_date($date_start, 'dayrfc', 'tzuserrel')."-".dol_print_date($date_stop, 'dayrfc', 'tzuserrel'); - if(!empty($projectid)) { + if (!empty($projectid)) { $sql = 'SELECT t.ref FROM '.MAIN_DB_PREFIX.'projet as t'; $sql .= ' WHERE t.rowid = '.((int) $db->sanitize($projectid)); $resql = $db->query($sql); diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index f3b60e8593c..7a3690fb39f 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -1283,11 +1283,11 @@ if ($action == 'create' && $user->rights->projet->creer) { // Accounting Report $accouting_module_activated = !empty($conf->comptabilite->enabled) || !empty($conf->accounting->enabled); if ($accouting_module_activated && $object->statut != Project::STATUS_DRAFT) { - $start = dol_getdate((int)$object->date_start); - $end = dol_getdate((int)$object->date_end); + $start = dol_getdate((int) $object->date_start); + $end = dol_getdate((int) $object->date_end); $url = DOL_URL_ROOT.'/compta/accounting-files.php?projectid='.$object->id; - if(!empty($object->date_start)) $url .= '&date_startday='.$start['mday'].'&date_startmonth='.$start['mon'].'&date_startyear='.$start['year']; - if(!empty($object->date_end)) $url .= '&date_stopday='.$end['mday'].'&date_stopmonth='.$end['mon'].'&date_stopyear='.$end['year']; + if (!empty($object->date_start)) $url .= '&date_startday='.$start['mday'].'&date_startmonth='.$start['mon'].'&date_startyear='.$start['year']; + if (!empty($object->date_end)) $url .= '&date_stopday='.$end['mday'].'&date_stopmonth='.$end['mon'].'&date_stopyear='.$end['year']; print dolGetButtonAction('', $langs->trans('ExportAccountingReportButtonLabel'), 'default', $url, ''); } From 623917291085f3ee8293b0187eb9ea08c8bd8577 Mon Sep 17 00:00:00 2001 From: Yoan Mollard Date: Sun, 19 Jun 2022 19:30:10 +0200 Subject: [PATCH 064/826] Fixed sanitization of int --- htdocs/compta/accounting-files.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/compta/accounting-files.php b/htdocs/compta/accounting-files.php index 571d17bea08..a0a592c72e1 100644 --- a/htdocs/compta/accounting-files.php +++ b/htdocs/compta/accounting-files.php @@ -181,7 +181,7 @@ if (($action == 'searchfiles' || $action == 'dl')) { $sql .= " WHERE datef between ".$wheretail; $sql .= " AND t.entity IN (".$db->sanitize($entity == 1 ? '0,1' : $entity).')'; $sql .= " AND t.fk_statut <> ".Facture::STATUS_DRAFT; - if (!empty($projectid)) $sql .= " AND fk_projet = ".$db->sanitize($projectid); + if(!empty($projectid)) $sql .= " AND fk_projet = ".((int) $projectid); } // Vendor invoices if (GETPOST('selectsupplierinvoices') && !empty($listofchoices['selectsupplierinvoices']['perms'])) { @@ -193,7 +193,7 @@ if (($action == 'searchfiles' || $action == 'dl')) { $sql .= " WHERE datef between ".$wheretail; $sql .= " AND t.entity IN (".$db->sanitize($entity == 1 ? '0,1' : $entity).')'; $sql .= " AND t.fk_statut <> ".FactureFournisseur::STATUS_DRAFT; - if (!empty($projectid)) $sql .= " AND fk_projet = ".$db->sanitize($projectid); + if(!empty($projectid)) $sql .= " AND fk_projet = ".((int) $projectid); } // Expense reports if (GETPOST('selectexpensereports') && !empty($listofchoices['selectexpensereports']['perms']) and empty($projectid)) { @@ -216,7 +216,7 @@ if (($action == 'searchfiles' || $action == 'dl')) { $sql .= " WHERE datedon between ".$wheretail; $sql .= " AND t.entity IN (".$db->sanitize($entity == 1 ? '0,1' : $entity).')'; $sql .= " AND t.fk_statut <> ".Don::STATUS_DRAFT; - if (!empty($projectid)) $sql .= " AND fk_projet = ".$db->sanitize($projectid); + if(!empty($projectid)) $sql .= " AND fk_projet = ".((int) $projectid); } // Payments of salaries if (GETPOST('selectpaymentsofsalaries') && !empty($listofchoices['selectpaymentsofsalaries']['perms'])) { @@ -228,7 +228,7 @@ if (($action == 'searchfiles' || $action == 'dl')) { $sql .= " WHERE datep between ".$wheretail; $sql .= " AND t.entity IN (".$db->sanitize($entity == 1 ? '0,1' : $entity).')'; //$sql.=" AND fk_statut <> ".PaymentSalary::STATUS_DRAFT; - if (!empty($projectid)) $sql .= " AND fk_projet = ".$db->sanitize($projectid); + if(!empty($projectid)) $sql .= " AND fk_projet = ".((int) $projectid); } // Social contributions if (GETPOST('selectsocialcontributions') && !empty($listofchoices['selectsocialcontributions']['perms'])) { @@ -240,7 +240,7 @@ if (($action == 'searchfiles' || $action == 'dl')) { $sql .= " WHERE t.date_ech between ".$wheretail; $sql .= " AND t.entity IN (".$db->sanitize($entity == 1 ? '0,1' : $entity).')'; //$sql.=" AND fk_statut <> ".ChargeSociales::STATUS_DRAFT; - if (!empty($projectid)) $sql .= " AND fk_projet = ".$db->sanitize($projectid); + if(!empty($projectid)) $sql .= " AND fk_projet = ".((int) $projectid); } // Various payments if (GETPOST('selectvariouspayment') && !empty($listofchoices['selectvariouspayment']['perms'])) { @@ -251,7 +251,7 @@ if (($action == 'searchfiles' || $action == 'dl')) { $sql .= " FROM ".MAIN_DB_PREFIX."payment_various as t"; $sql .= " WHERE datep between ".$wheretail; $sql .= " AND t.entity IN (".$db->sanitize($entity == 1 ? '0,1' : $entity).')'; - if (!empty($projectid)) $sql .= " AND fk_projet = ".$db->sanitize($projectid); + if(!empty($projectid)) $sql .= " AND fk_projet = ".((int) $projectid); } // Loan payments if (GETPOST('selectloanspayment') && !empty($listofchoices['selectloanspayment']['perms']) && empty($projectid)) { From 4e2bacb039af2b48a6e219c77f090533af44adea Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Sun, 19 Jun 2022 18:26:33 +0000 Subject: [PATCH 065/826] Fixing style errors. --- htdocs/compta/accounting-files.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/compta/accounting-files.php b/htdocs/compta/accounting-files.php index a0a592c72e1..e754af8c60e 100644 --- a/htdocs/compta/accounting-files.php +++ b/htdocs/compta/accounting-files.php @@ -181,7 +181,7 @@ if (($action == 'searchfiles' || $action == 'dl')) { $sql .= " WHERE datef between ".$wheretail; $sql .= " AND t.entity IN (".$db->sanitize($entity == 1 ? '0,1' : $entity).')'; $sql .= " AND t.fk_statut <> ".Facture::STATUS_DRAFT; - if(!empty($projectid)) $sql .= " AND fk_projet = ".((int) $projectid); + if (!empty($projectid)) $sql .= " AND fk_projet = ".((int) $projectid); } // Vendor invoices if (GETPOST('selectsupplierinvoices') && !empty($listofchoices['selectsupplierinvoices']['perms'])) { @@ -193,7 +193,7 @@ if (($action == 'searchfiles' || $action == 'dl')) { $sql .= " WHERE datef between ".$wheretail; $sql .= " AND t.entity IN (".$db->sanitize($entity == 1 ? '0,1' : $entity).')'; $sql .= " AND t.fk_statut <> ".FactureFournisseur::STATUS_DRAFT; - if(!empty($projectid)) $sql .= " AND fk_projet = ".((int) $projectid); + if (!empty($projectid)) $sql .= " AND fk_projet = ".((int) $projectid); } // Expense reports if (GETPOST('selectexpensereports') && !empty($listofchoices['selectexpensereports']['perms']) and empty($projectid)) { @@ -216,7 +216,7 @@ if (($action == 'searchfiles' || $action == 'dl')) { $sql .= " WHERE datedon between ".$wheretail; $sql .= " AND t.entity IN (".$db->sanitize($entity == 1 ? '0,1' : $entity).')'; $sql .= " AND t.fk_statut <> ".Don::STATUS_DRAFT; - if(!empty($projectid)) $sql .= " AND fk_projet = ".((int) $projectid); + if (!empty($projectid)) $sql .= " AND fk_projet = ".((int) $projectid); } // Payments of salaries if (GETPOST('selectpaymentsofsalaries') && !empty($listofchoices['selectpaymentsofsalaries']['perms'])) { @@ -228,7 +228,7 @@ if (($action == 'searchfiles' || $action == 'dl')) { $sql .= " WHERE datep between ".$wheretail; $sql .= " AND t.entity IN (".$db->sanitize($entity == 1 ? '0,1' : $entity).')'; //$sql.=" AND fk_statut <> ".PaymentSalary::STATUS_DRAFT; - if(!empty($projectid)) $sql .= " AND fk_projet = ".((int) $projectid); + if (!empty($projectid)) $sql .= " AND fk_projet = ".((int) $projectid); } // Social contributions if (GETPOST('selectsocialcontributions') && !empty($listofchoices['selectsocialcontributions']['perms'])) { @@ -240,7 +240,7 @@ if (($action == 'searchfiles' || $action == 'dl')) { $sql .= " WHERE t.date_ech between ".$wheretail; $sql .= " AND t.entity IN (".$db->sanitize($entity == 1 ? '0,1' : $entity).')'; //$sql.=" AND fk_statut <> ".ChargeSociales::STATUS_DRAFT; - if(!empty($projectid)) $sql .= " AND fk_projet = ".((int) $projectid); + if (!empty($projectid)) $sql .= " AND fk_projet = ".((int) $projectid); } // Various payments if (GETPOST('selectvariouspayment') && !empty($listofchoices['selectvariouspayment']['perms'])) { @@ -251,7 +251,7 @@ if (($action == 'searchfiles' || $action == 'dl')) { $sql .= " FROM ".MAIN_DB_PREFIX."payment_various as t"; $sql .= " WHERE datep between ".$wheretail; $sql .= " AND t.entity IN (".$db->sanitize($entity == 1 ? '0,1' : $entity).')'; - if(!empty($projectid)) $sql .= " AND fk_projet = ".((int) $projectid); + if (!empty($projectid)) $sql .= " AND fk_projet = ".((int) $projectid); } // Loan payments if (GETPOST('selectloanspayment') && !empty($listofchoices['selectloanspayment']['perms']) && empty($projectid)) { From 950c0c2183963a32eba08f0ecd3094648fbbd57a Mon Sep 17 00:00:00 2001 From: BENKE Charlene <1179011+defrance@users.noreply.github.com> Date: Mon, 20 Jun 2022 09:15:19 +0200 Subject: [PATCH 066/826] Create llx_element_categorie.sql The goal of table llx_element_categorie is to replace all tables llx_categories_xxx (with one table). the llx_element_tag table initially intended for this does not have the correct nomenclature to express its real use (and was used for other things before) more informations here : https://github.com/Dolibarr/dolibarr/pull/21192 --- .../mysql/tables/llx_element_categorie.sql | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 htdocs/install/mysql/tables/llx_element_categorie.sql diff --git a/htdocs/install/mysql/tables/llx_element_categorie.sql b/htdocs/install/mysql/tables/llx_element_categorie.sql new file mode 100644 index 00000000000..a1c7fddb0eb --- /dev/null +++ b/htdocs/install/mysql/tables/llx_element_categorie.sql @@ -0,0 +1,25 @@ +-- ============================================================================ +-- Copyright (C) 2022 charlene Benke +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . +-- +-- ============================================================================ + +create table llx_element_categorie +( + rowid integer AUTO_INCREMENT PRIMARY KEY, + fk_categorie integer NOT NULL, + fk_element integer NOT NULL, + import_key varchar(14) +)ENGINE=innodb; From a5148243427208c041489ae9c59a71487ab2c9ce Mon Sep 17 00:00:00 2001 From: Franck Lauby Date: Mon, 20 Jun 2022 14:55:07 +0200 Subject: [PATCH 067/826] =?UTF-8?q?pr=C3=A9pa=20des=20d=C3=A9pots?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- htdocs/custom/.gitignore | 1 + htdocs/custom/README.md | 27 --------------------------- 2 files changed, 1 insertion(+), 27 deletions(-) delete mode 100644 htdocs/custom/README.md diff --git a/htdocs/custom/.gitignore b/htdocs/custom/.gitignore index e69de29bb2d..cd95745c140 100644 --- a/htdocs/custom/.gitignore +++ b/htdocs/custom/.gitignore @@ -0,0 +1 @@ +moduleFormation/ diff --git a/htdocs/custom/README.md b/htdocs/custom/README.md deleted file mode 100644 index 2fc3067f204..00000000000 --- a/htdocs/custom/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# DOLIBARR ERP & CRM custom directory for external modules - -This directory is dedicated to store external modules. -To use it, just copy here the directory of the module into this directory. - -Note: On linux or MAC systems, it is better to unzip/store the external module directory into -a different place than this directory and just adding a symbolic link here to the htdocs directory -of the module. - -For example on Linux OS: Get the module from the command - -`mkdir ~/git; cd ~/git` - -`git clone https://git.framasoft.org/p/newmodule/newmodule.git` - -Then create the symbolic link - -`ln -fs ~/git/newmodule/htdocs /path_to_dolibarr/htdocs/custom/newmodule` - -WARNING !!! -Check also that the /custom directory is active by adding into dolibarr `conf/conf.php` file the following -two lines, so dolibarr will also scan /custom directory to find external external modules: - -```php -$dolibarr_main_url_root_alt='/custom'; -$dolibarr_main_document_root_alt='/path_to_dolibarr/htdocs/custom/'; -``` From aebdb0eaa1075cf277d349de6c7b39c5d923f23b Mon Sep 17 00:00:00 2001 From: Quatadah Nasdami Date: Tue, 21 Jun 2022 13:22:59 +0200 Subject: [PATCH 068/826] adding clone button --- htdocs/projet/tasks/task.php | 41 ++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/htdocs/projet/tasks/task.php b/htdocs/projet/tasks/task.php index 3df3cf8928e..a1aae4eadf4 100644 --- a/htdocs/projet/tasks/task.php +++ b/htdocs/projet/tasks/task.php @@ -128,6 +128,29 @@ if ($action == 'update' && !GETPOST("cancel") && $user->rights->projet->creer) { } } +if ($action == 'confirm_clone' && $confirm == 'yes') { + //$clone_contacts = GETPOST('clone_contacts') ? 1 : 0; + $clone_prog = GETPOST('clone_prog') ? 1 : 0; + $clone_time = GETPOST('clone_time') ? 1 : 0; + $clone_affectation = GETPOST('clone_affectation') ? 1 : 0; + $clone_change_dt = GETPOST('clone_change_dt') ? 1 : 0; + $clone_notes = GETPOST('clone_notes') ? 1 : 0; + $clone_file = GETPOST('clone_file') ? 1 : 0; + $result = $object->createFromClone($user, $object->id, $object->fk_project, $object->fk_task_parent, $clone_change_dt, $clone_affectation, $clone_time, $clone_file, $clone_notes, $clone_prog); + if ($result <= 0) { + setEventMessages($object->error, $object->errors, 'errors'); + } else { + // Load new object + $newobject = new Task($db); + $newobject->fetch($result); + $newobject->fetch_optionals(); + $newobject->fetch_thirdparty(); // Load new object + $object = $newobject; + $action = 'edit'; + $comefromclone = true; + } +} + if ($action == 'confirm_delete' && $confirm == "yes" && $user->rights->projet->supprimer) { $result = $projectstatic->fetch($object->fk_project); $projectstatic->fetch_thirdparty(); @@ -199,6 +222,7 @@ $form = new Form($db); $formother = new FormOther($db); $formfile = new FormFile($db); + if ($id > 0 || !empty($ref)) { $res = $object->fetch_optionals(); if (!empty($conf->global->PROJECT_ALLOW_COMMENT_ON_TASK) && method_exists($object, 'fetchComments') && empty($object->comments)) { @@ -379,6 +403,22 @@ if ($id > 0 || !empty($ref)) { //$userAccess = $projectstatic->restrictedProjectArea($user); // We allow task affected to user even if a not allowed project //$arrayofuseridoftask=$object->getListContactId('internal'); + if ($action == 'clone') { + $formquestion = array( + 'text' => $langs->trans("ConfirmClone"), + //array('type' => 'checkbox', 'name' => 'clone_contacts', 'label' => $langs->trans("CloneContacts"), 'value' => true), + array('type' => 'checkbox', 'name' => 'clone_change_dt', 'label' => $langs->trans("CloneChanges"), 'value' => true), + array('type' => 'checkbox', 'name' => 'clone_affectation', 'label' => $langs->trans("CloneAffectation"), 'value' => true), + array('type' => 'checkbox', 'name' => 'clone_prog', 'label' => $langs->trans("CloneProgression"), 'value' => true), + array('type' => 'checkbox', 'name' => 'clone_time', 'label' => $langs->trans("CloneTimes"), 'value' => true), + array('type' => 'checkbox', 'name' => 'clone_file', 'label' => $langs->trans("CloneFile"), 'value' => true), + + ); + + print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id, $langs->trans("ToClone"), $langs->trans("ConfirmCloneTask"), "confirm_clone", $formquestion, '', 1, 300, 590); + } + + $head = task_prepare_head($object); if ($action == 'edit' && $user->rights->projet->creer) { @@ -622,6 +662,7 @@ if ($id > 0 || !empty($ref)) { // Modify if ($user->rights->projet->creer) { print ''.$langs->trans('Modify').''; + print ''.$langs->trans('Clone').''; } else { print ''.$langs->trans('Modify').''; } From 629ece047378fba6f443768dabf4e4217796ff37 Mon Sep 17 00:00:00 2001 From: Quatadah Nasdami Date: Tue, 21 Jun 2022 13:33:55 +0200 Subject: [PATCH 069/826] adding clone button on task 2 --- htdocs/projet/tasks/task.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/htdocs/projet/tasks/task.php b/htdocs/projet/tasks/task.php index a1aae4eadf4..4ca35cf46d3 100644 --- a/htdocs/projet/tasks/task.php +++ b/htdocs/projet/tasks/task.php @@ -45,6 +45,7 @@ $confirm = GETPOST('confirm', 'alpha'); $withproject = GETPOST('withproject', 'int'); $project_ref = GETPOST('project_ref', 'alpha'); $planned_workload = ((GETPOST('planned_workloadhour', 'int') != '' || GETPOST('planned_workloadmin', 'int') != '') ? (GETPOST('planned_workloadhour', 'int') > 0 ?GETPOST('planned_workloadhour', 'int') * 3600 : 0) + (GETPOST('planned_workloadmin', 'int') > 0 ?GETPOST('planned_workloadmin', 'int') * 60 : 0) : ''); +$comefromclone = GETPOST("comefromclone", "alpha"); // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context $hookmanager->initHooks(array('projecttaskcard', 'globalcard')); @@ -659,6 +660,20 @@ if ($id > 0 || !empty($ref)) { $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been // modified by hook if (empty($reshook)) { + // Cancel + if ($cancel) { + if (GETPOST("comefromclone") == 1) { + $result = $object->delete($user); + if ($result > 0) { + header("Location: index.php"); + exit; + } else { + dol_syslog($object->error, LOG_DEBUG); + setEventMessages($langs->trans("CantRemoveProject", $langs->transnoentitiesnoconv("ProjectOverview")), null, 'errors'); + } + } + } + // Modify if ($user->rights->projet->creer) { print ''.$langs->trans('Modify').''; From 8c0b1efce4e32715fa4b415acef39fa056644eab Mon Sep 17 00:00:00 2001 From: GregM Date: Tue, 21 Jun 2022 15:21:45 +0200 Subject: [PATCH 070/826] NEW add objectLink expedition --- htdocs/core/class/html.form.class.php | 3 ++- htdocs/expedition/card.php | 4 ++-- htdocs/expedition/tpl/linkedobjectblock.tpl.php | 3 +-- htdocs/langs/en_US/main.lang | 1 + htdocs/langs/fr_FR/main.lang | 1 + 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 8f112b9aa98..072383f7ae9 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -8414,7 +8414,7 @@ class Form if (empty($conf->supplier_proposal->enabled)) { continue; // Do not show if module disabled } - } elseif ($objecttype == 'shipping' || $objecttype == 'shipment') { + } elseif ($objecttype == 'shipping' || $objecttype == 'shipment' || $objecttype == 'expedition') { $tplpath = 'expedition'; if (empty($conf->expedition->enabled)) { continue; // Do not show if module disabled @@ -8533,6 +8533,7 @@ class Form $possiblelinks = array( 'propal'=>array('enabled'=>$conf->propal->enabled, 'perms'=>1, 'label'=>'LinkToProposal', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_client, t.total_ht FROM ".$this->db->prefix()."societe as s, ".$this->db->prefix()."propal as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$this->db->sanitize($listofidcompanytoscan).') AND t.entity IN ('.getEntity('propal').')'), + 'shipping'=>array('enabled'=>$conf->expedition->enabled, 'perms'=>1, 'label'=>'LinkToExpedition', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref FROM ".$this->db->prefix()."societe as s, ".$this->db->prefix()."expedition as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$this->db->sanitize($listofidcompanytoscan).') AND t.entity IN ('.getEntity('shipping').')'), 'order'=>array('enabled'=>$conf->commande->enabled, 'perms'=>1, 'label'=>'LinkToOrder', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_client, t.total_ht FROM ".$this->db->prefix()."societe as s, ".$this->db->prefix()."commande as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$this->db->sanitize($listofidcompanytoscan).') AND t.entity IN ('.getEntity('commande').')'), 'invoice'=>array('enabled'=>$conf->facture->enabled, 'perms'=>1, 'label'=>'LinkToInvoice', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_client, t.total_ht FROM ".$this->db->prefix()."societe as s, ".$this->db->prefix()."facture as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$this->db->sanitize($listofidcompanytoscan).') AND t.entity IN ('.getEntity('invoice').')'), 'invoice_template'=>array('enabled'=>$conf->facture->enabled, 'perms'=>1, 'label'=>'LinkToTemplateInvoice', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.titre as ref, t.total_ht FROM ".$this->db->prefix()."societe as s, ".$this->db->prefix()."facture_rec as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$this->db->sanitize($listofidcompanytoscan).') AND t.entity IN ('.getEntity('invoice').')'), diff --git a/htdocs/expedition/card.php b/htdocs/expedition/card.php index f835e293f5f..09f28d456e6 100644 --- a/htdocs/expedition/card.php +++ b/htdocs/expedition/card.php @@ -2551,8 +2551,8 @@ if ($action == 'create') { // Show links to link elements - //$linktoelem = $form->showLinkToObjectBlock($object, null, array('order')); - $somethingshown = $form->showLinkedObjectBlock($object, ''); + $linktoelem = $form->showLinkToObjectBlock($object, null, array('shipping')); + $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem); print '
'; diff --git a/htdocs/expedition/tpl/linkedobjectblock.tpl.php b/htdocs/expedition/tpl/linkedobjectblock.tpl.php index 26e4ebbb47d..e26f60486e5 100644 --- a/htdocs/expedition/tpl/linkedobjectblock.tpl.php +++ b/htdocs/expedition/tpl/linkedobjectblock.tpl.php @@ -60,8 +60,7 @@ foreach ($linkedObjectBlock as $key => $objectlink) { // For now, shipments must stay linked to order, so link is not deletable if ($object->element != 'commande') { ?> - ">transnoentitiesnoconv("RemoveLink"), 'unlink'); ?> - id.'&token='.newToken().'&action=dellink&dellinkid='.$key; ?>">transnoentitiesnoconv("RemoveLink"), 'unlink'); ?> diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 2867c7b853b..503587aa8f0 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -799,6 +799,7 @@ URLPhoto=URL of photo/logo SetLinkToAnotherThirdParty=Link to another third party LinkTo=Link to LinkToProposal=Link to proposal +LinkToExpedition= Link to expedition LinkToOrder=Link to order LinkToInvoice=Link to invoice LinkToTemplateInvoice=Link to template invoice diff --git a/htdocs/langs/fr_FR/main.lang b/htdocs/langs/fr_FR/main.lang index 12778f337dd..2c0a6cee908 100644 --- a/htdocs/langs/fr_FR/main.lang +++ b/htdocs/langs/fr_FR/main.lang @@ -799,6 +799,7 @@ URLPhoto=URL de la photo/logo SetLinkToAnotherThirdParty=Lier vers un autre tiers LinkTo=Lier à LinkToProposal=Lier à une proposition commerciale +LinkToExpedition=Lier à une expédition LinkToOrder=Lier à une commande LinkToInvoice=Lier à une facture LinkToTemplateInvoice=Lien vers le modèle de facture From dd9e77e764f09632147330b499b153441e47cea7 Mon Sep 17 00:00:00 2001 From: Faustin Date: Tue, 21 Jun 2022 17:57:00 +0200 Subject: [PATCH 071/826] NEW 21000 Added columns 'alias_name' on poject list --- htdocs/projet/list.php | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/htdocs/projet/list.php b/htdocs/projet/list.php index eaf9c5022a3..eab0d8cd8be 100644 --- a/htdocs/projet/list.php +++ b/htdocs/projet/list.php @@ -91,6 +91,7 @@ $search_all = GETPOST('search_all', 'alphanohtml') ? GETPOST('search_all', 'alph $search_ref = GETPOST("search_ref", 'alpha'); $search_label = GETPOST("search_label", 'alpha'); $search_societe = GETPOST("search_societe", 'alpha'); +$search_societe_alias = GETPOST("search_societe_alias", 'alpha'); $search_status = GETPOST("search_status", 'int'); $search_opp_status = GETPOST("search_opp_status", 'alpha'); $search_opp_percent = GETPOST("search_opp_percent", 'alpha'); @@ -198,6 +199,7 @@ include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php'; // Add non object fields to fields for list $arrayfields['s.nom'] = array('label'=>$langs->trans("ThirdParty"), 'checked'=>1, 'position'=>21, 'enabled'=>(empty($conf->societe->enabled) ? 0 : 1)); +$arrayfields['s.name_alias'] = array('label'=>"AliasNameShort", 'checked'=>1, 'position'=>22); $arrayfields['commercial'] = array('label'=>$langs->trans("SaleRepresentativesOfThirdParty"), 'checked'=>0, 'position'=>23); $arrayfields['c.assigned'] = array('label'=>$langs->trans("AssignedTo"), 'checked'=>-1, 'position'=>120); $arrayfields['opp_weighted_amount'] = array('label'=>$langs->trans('OpportunityWeightedAmountShort'), 'checked'=>0, 'position'=> 116, 'enabled'=>(empty($conf->global->PROJECT_USE_OPPORTUNITIES) ? 0 : 1), 'position'=>106); @@ -246,6 +248,7 @@ if (empty($reshook)) { $search_ref = ""; $search_label = ""; $search_societe = ""; + $search_societe_alias = ''; $search_status = -1; $search_opp_status = -1; $search_opp_amount = ''; @@ -447,6 +450,9 @@ if ($search_label) { if ($search_societe) { $sql .= natural_search('s.nom', $search_societe); } +if ($search_societe_alias) { + $sql .= natural_search('s.name_alias', $search_societe_alias); +} if ($search_opp_amount) { $sql .= natural_search('p.opp_amount', $search_opp_amount, 1); } @@ -687,6 +693,9 @@ if ($search_label != '') { if ($search_societe != '') { $param .= '&search_societe='.urlencode($search_societe); } +if ($search_societe_alias != '') { + $param .= '&search_societe_alias='.urlencode($search_societe_alias); +} if ($search_status >= 0) { $param .= '&search_status='.urlencode($search_status); } @@ -887,6 +896,18 @@ if (!empty($arrayfields['s.nom']['checked'])) { print ''; print ''; } + +// Alias +if (!empty($arrayfields['s.name_alias']['checked'])) { + print ''; + if ($socid > 0) { + $tmpthirdparty = new Societe($db); + $tmpthirdparty->fetch($socid); + $search_societe_alias = $tmpthirdparty->name_alias; + } + print ''; + print ''; +} // Sale representative if (!empty($arrayfields['commercial']['checked'])) { print ' '; @@ -1050,6 +1071,9 @@ if (!empty($arrayfields['p.title']['checked'])) { if (!empty($arrayfields['s.nom']['checked'])) { print_liste_field_titre($arrayfields['s.nom']['label'], $_SERVER["PHP_SELF"], "s.nom", "", $param, "", $sortfield, $sortorder); } +if (!empty($arrayfields['s.name_alias']['checked'])) { + print_liste_field_titre($arrayfields['s.name_alias']['label'], $_SERVER["PHP_SELF"], "s.name_alias", "", $param, "", $sortfield, $sortorder); +} if (!empty($arrayfields['commercial']['checked'])) { print_liste_field_titre($arrayfields['commercial']['label'], $_SERVER["PHP_SELF"], "", "", $param, "", $sortfield, $sortorder, 'tdoverflowmax100imp '); } @@ -1185,7 +1209,20 @@ while ($i < min($num, $limit)) { if (!empty($arrayfields['s.nom']['checked'])) { print ''; if ($obj->socid) { - print $companystatic->getNomUrl(1); + print $companystatic->getNomUrl(1, '', 0, 0, -1, empty($arrayfields['s.name_alias']['checked']) ? 0 : 1); + } else { + print ' '; + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Alias + if (!empty($arrayfields['s.name_alias']['checked'])) { + print ''; + if ($obj->socid) { + print $companystatic->name_alias; } else { print ' '; } From e76b49c360ae4db85eef85453d65e9f92f0151ef Mon Sep 17 00:00:00 2001 From: Faustin Date: Tue, 21 Jun 2022 18:06:58 +0200 Subject: [PATCH 072/826] NEW 21000 Added columns 'alias_name' on poject list --- htdocs/projet/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/projet/list.php b/htdocs/projet/list.php index eab0d8cd8be..1ec8245b868 100644 --- a/htdocs/projet/list.php +++ b/htdocs/projet/list.php @@ -199,7 +199,7 @@ include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php'; // Add non object fields to fields for list $arrayfields['s.nom'] = array('label'=>$langs->trans("ThirdParty"), 'checked'=>1, 'position'=>21, 'enabled'=>(empty($conf->societe->enabled) ? 0 : 1)); -$arrayfields['s.name_alias'] = array('label'=>"AliasNameShort", 'checked'=>1, 'position'=>22); +$arrayfields['s.name_alias'] = array('label'=>"AliasNameShort", 'checked'=>0, 'position'=>22); $arrayfields['commercial'] = array('label'=>$langs->trans("SaleRepresentativesOfThirdParty"), 'checked'=>0, 'position'=>23); $arrayfields['c.assigned'] = array('label'=>$langs->trans("AssignedTo"), 'checked'=>-1, 'position'=>120); $arrayfields['opp_weighted_amount'] = array('label'=>$langs->trans('OpportunityWeightedAmountShort'), 'checked'=>0, 'position'=> 116, 'enabled'=>(empty($conf->global->PROJECT_USE_OPPORTUNITIES) ? 0 : 1), 'position'=>106); From 57d2a0352e5200a0733843689240f17a3b254565 Mon Sep 17 00:00:00 2001 From: Faustin Date: Tue, 21 Jun 2022 18:30:23 +0200 Subject: [PATCH 073/826] NEW 21000 Added columns 'alias_name' on tasks list --- htdocs/projet/tasks/list.php | 37 ++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/htdocs/projet/tasks/list.php b/htdocs/projet/tasks/list.php index bfda3ad31be..f6da556e8d7 100644 --- a/htdocs/projet/tasks/list.php +++ b/htdocs/projet/tasks/list.php @@ -154,6 +154,7 @@ $arrayfields = array( 'p.ref'=>array('label'=>"ProjectRef", 'checked'=>1), 'p.title'=>array('label'=>"ProjectLabel", 'checked'=>0), 's.nom'=>array('label'=>"ThirdParty", 'checked'=>0), + 's.name_alias'=>array('label'=>"AliasNameShort", 'checked'=>1), 'p.fk_statut'=>array('label'=>"ProjectStatus", 'checked'=>1), 't.planned_workload'=>array('label'=>"PlannedWorkload", 'checked'=>1, 'position'=>102), 't.duration_effective'=>array('label'=>"TimeSpent", 'checked'=>1, 'position'=>103), @@ -326,7 +327,7 @@ if (count($listoftaskcontacttype) == 0) { $distinct = 'DISTINCT'; // We add distinct until we are added a protection to be sure a contact of a project and task is assigned only once. $sql = "SELECT ".$distinct." p.rowid as projectid, p.ref as projectref, p.title as projecttitle, p.fk_statut as projectstatus, p.datee as projectdatee, p.fk_opp_status, p.public, p.fk_user_creat as projectusercreate, p.usage_bill_time,"; -$sql .= " s.nom as name, s.rowid as socid,"; +$sql .= " s.nom as name, s.name_alias as alias, s.rowid as socid,"; $sql .= " t.datec as date_creation, t.dateo as date_start, t.datee as date_end, t.tms as date_update,"; $sql .= " t.rowid as id, t.ref, t.label, t.planned_workload, t.duration_effective, t.progress, t.fk_statut, "; $sql .= " t.description, t.fk_task_parent"; @@ -413,6 +414,9 @@ if ($search_task_budget_amount) { if ($search_societe) { $sql .= natural_search('s.nom', $search_societe); } +if ($search_societe_alias) { + $sql .= natural_search('s.name_alias', $search_societe_alias); +} if ($search_date_start) { $sql .= " AND t.dateo >= '".$db->idate($search_date_start)."'"; } @@ -768,6 +772,11 @@ if (!empty($arrayfields['s.nom']['checked'])) { print ''; print ''; } +if (!empty($arrayfields['s.name_alias']['checked'])) { + print ''; + print ''; + print ''; +} if (!empty($arrayfields['p.fk_statut']['checked'])) { print ''; $arrayofstatus = array(); @@ -890,6 +899,10 @@ if (!empty($arrayfields['s.nom']['checked'])) { print_liste_field_titre($arrayfields['s.nom']['label'], $_SERVER["PHP_SELF"], "s.nom", "", $param, "", $sortfield, $sortorder); $totalarray['nbfield']++; } +if (!empty($arrayfields['s.name_alias']['checked'])) { + print_liste_field_titre($arrayfields['s.name_alias']['label'], $_SERVER["PHP_SELF"], "s.name_alias", "", $param, "", $sortfield, $sortorder); + $totalarray['nbfield']++; +} if (!empty($arrayfields['p.fk_statut']['checked'])) { print_liste_field_titre($arrayfields['p.fk_statut']['label'], $_SERVER["PHP_SELF"], "p.fk_statut", "", $param, '', $sortfield, $sortorder, 'center '); $totalarray['nbfield']++; @@ -992,6 +1005,11 @@ while ($i < $imaxinloop) { $projectstatic->statut = $obj->projectstatus; $projectstatic->datee = $db->jdate($obj->projectdatee); + if ($obj->socid) { + $socstatic->id = $obj->socid; + $socstatic->name = $obj->name; + $socstatic->name_alias = $obj->alias; + } if ($mode == 'kanban') { if ($i == 0) { print ''; @@ -1101,9 +1119,20 @@ while ($i < $imaxinloop) { if (!empty($arrayfields['s.nom']['checked'])) { print ''; if ($obj->socid) { - $socstatic->id = $obj->socid; - $socstatic->name = $obj->name; - print $socstatic->getNomUrl(1); + print $socstatic->getNomUrl(1, '', 0, 0, -1, empty($arrayfields['s.name_alias']['checked']) ? 0 : 1); + } else { + print ' '; + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Alias + if (!empty($arrayfields['s.name_alias']['checked'])) { + print ''; + if ($obj->socid) { + print $socstatic->name_alias; } else { print ' '; } From 0adc7116a6a8a562da02ba1fad5c2feafe9877f3 Mon Sep 17 00:00:00 2001 From: Faustin Date: Tue, 21 Jun 2022 19:21:50 +0200 Subject: [PATCH 074/826] NEW 21000 Added columns 'alias_name' on supplier order list --- htdocs/fourn/commande/list.php | 36 ++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/htdocs/fourn/commande/list.php b/htdocs/fourn/commande/list.php index 22c4921b5b1..6f2669ac877 100644 --- a/htdocs/fourn/commande/list.php +++ b/htdocs/fourn/commande/list.php @@ -93,6 +93,7 @@ $search_product_category = GETPOST('search_product_category', 'int'); $search_ref = GETPOST('search_ref', 'alpha'); $search_refsupp = GETPOST('search_refsupp', 'alpha'); $search_company = GETPOST('search_company', 'alpha'); +$search_company_alias = GETPOST('search_company_alias', 'alpha'); $search_town = GETPOST('search_town', 'alpha'); $search_zip = GETPOST('search_zip', 'alpha'); $search_state = GETPOST("search_state", 'alpha'); @@ -181,6 +182,7 @@ $checkedtypetiers = 0; // Definition of array of fields for columns $arrayfields = array( + 's.name_alias'=>array('label'=>"AliasNameShort", 'position'=>47, 'checked'=>0), 's.town'=>array('label'=>"Town", 'enabled'=>1, 'position'=>47, 'checked'=>1), 's.zip'=>array('label'=>"Zip", 'enabled'=>1, 'position'=>47, 'checked'=>1), 'state.nom'=>array('label'=>"StateShort", 'enabled'=>1, 'position'=>48), @@ -246,6 +248,7 @@ if (empty($reshook)) { $search_ref = ''; $search_refsupp = ''; $search_company = ''; + $search_company_alias = ''; $search_town = ''; $search_zip = ""; $search_state = ""; @@ -657,6 +660,9 @@ if (empty($reshook)) { if ($search_company) { $param .= '&search_company='.urlencode($search_company); } + if ($search_company_alias) { + $param .= '&search_company_alias='.urlencode($search_company_alias); + } //if ($search_ref_customer) $param .= '&search_ref_customer='.urlencode($search_ref_customer); if ($search_user > 0) { $param .= '&search_user='.urlencode($search_user); @@ -741,7 +747,7 @@ $sql = 'SELECT'; if ($sall || $search_product_category > 0) { $sql = 'SELECT DISTINCT'; } -$sql .= ' s.rowid as socid, s.nom as name, s.town, s.zip, s.fk_pays, s.client, s.code_client, s.email,'; +$sql .= ' s.rowid as socid, s.nom as name, s.name_alias as alias, s.town, s.zip, s.fk_pays, s.client, s.code_client, s.email,'; $sql .= " typent.code as typent_code,"; $sql .= " state.code_departement as state_code, state.nom as state_name,"; $sql .= " cf.rowid, cf.ref, cf.ref_supplier, cf.fk_statut, cf.billed, cf.total_ht, cf.total_tva, cf.total_ttc, cf.fk_user_author, cf.date_commande as date_commande, cf.date_livraison as date_livraison,cf.date_valid, cf.date_approve,"; @@ -803,6 +809,9 @@ if ($sall) { if ($search_company) { $sql .= natural_search('s.nom', $search_company); } +if ($search_company_alias) { + $sql .= natural_search('s.name_alias', $search_company_alias); +} if ($search_request_author) { $sql .= natural_search(array('u.lastname', 'u.firstname', 'u.login'), $search_request_author); } @@ -861,6 +870,9 @@ if ($search_type_thirdparty != '' && $search_type_thirdparty > 0) { if ($search_company) { $sql .= natural_search('s.nom', $search_company); } +if ($search_company_alias) { + $sql .= natural_search('s.name_alias', $search_company_alias); +} if ($search_sale > 0) { $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".((int) $search_sale); } @@ -1032,6 +1044,9 @@ if ($resql) { if ($search_company) { $param .= '&search_company='.urlencode($search_company); } + if ($search_company_alias) { + $param .= '&search_company_alias='.urlencode($search_company_alias); + } if ($search_user > 0) { $param .= '&search_user='.urlencode($search_user); } @@ -1275,6 +1290,10 @@ if ($resql) { if (!empty($arrayfields['cf.fk_soc']['checked'])) { print ''; } + // Alias + if (!empty($arrayfields['s.name_alias']['checked'])) { + print ''; + } // Town if (!empty($arrayfields['s.town']['checked'])) { print ''; @@ -1447,6 +1466,9 @@ if ($resql) { if (!empty($arrayfields['cf.fk_soc']['checked'])) { print_liste_field_titre($arrayfields['cf.fk_soc']['label'], $_SERVER["PHP_SELF"], "s.nom", "", $param, '', $sortfield, $sortorder); } + if (!empty($arrayfields['s.name_alias']['checked'])) { + print_liste_field_titre($arrayfields['s.name_alias']['label'], $_SERVER["PHP_SELF"], "s.name_alias", "", $param, '', $sortfield, $sortorder); + } if (!empty($arrayfields['s.town']['checked'])) { print_liste_field_titre($arrayfields['s.town']['label'], $_SERVER["PHP_SELF"], 's.town', '', $param, '', $sortfield, $sortorder); } @@ -1623,7 +1645,17 @@ if ($resql) { $thirdpartytmp->id = $obj->socid; $thirdpartytmp->name = $obj->name; $thirdpartytmp->email = $obj->email; - print $thirdpartytmp->getNomUrl(1, 'supplier'); + $thirdpartytmp->name_alias = $obj->alias; + print $thirdpartytmp->getNomUrl(1, 'supplier', 0, 0, -1, empty($arrayfields['s.name_alias']['checked']) ? 0 : 1); + print ''."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + //alias + if (!empty($arrayfields['s.name_alias']['checked'])) { + print ''; + print $obj->alias; print ''."\n"; if (!$i) { $totalarray['nbfield']++; From 08ba39f70444d2e3b1992dc26039aac1606d2e6e Mon Sep 17 00:00:00 2001 From: Faustin Date: Tue, 21 Jun 2022 19:25:38 +0200 Subject: [PATCH 075/826] NEW 21000 Added columns 'alias_name' on supplier order list --- htdocs/projet/tasks/list.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/htdocs/projet/tasks/list.php b/htdocs/projet/tasks/list.php index f6da556e8d7..183a53783fb 100644 --- a/htdocs/projet/tasks/list.php +++ b/htdocs/projet/tasks/list.php @@ -68,6 +68,7 @@ $search_task_user = GETPOST('search_task_user', 'int'); $search_task_progress = GETPOST('search_task_progress'); $search_task_budget_amount = GETPOST('search_task_budget_amount'); $search_societe = GETPOST('search_societe'); +$search_societe_alias = GETPOST('search_societe_alias'); $search_opp_status = GETPOST("search_opp_status", 'alpha'); $mine = GETPOST('mode', 'alpha') == 'mine' ? 1 : 0; @@ -206,6 +207,8 @@ if (empty($reshook)) { $search_categ = ""; $search_projectstatus = -1; $search_project_ref = ""; + $search_societe = ""; + $search_societe_alias = ""; $search_project_title = ""; $search_task_ref = ""; $search_task_label = ""; @@ -583,6 +586,9 @@ if ($search_task_progress != '') { if ($search_societe != '') { $param .= '&search_societe='.urlencode($search_societe); } +if ($search_societe != '') { + $param .= '&search_societe_alias='.urlencode($search_societe_alias); +} if ($search_projectstatus != '') { $param .= '&search_projectstatus='.urlencode($search_projectstatus); } @@ -774,7 +780,7 @@ if (!empty($arrayfields['s.nom']['checked'])) { } if (!empty($arrayfields['s.name_alias']['checked'])) { print ''; - print ''; + print ''; print ''; } if (!empty($arrayfields['p.fk_statut']['checked'])) { From df8580dd4cdba7ed69ec658fd57b88bc2a72c161 Mon Sep 17 00:00:00 2001 From: Faustin Date: Tue, 21 Jun 2022 19:50:05 +0200 Subject: [PATCH 076/826] NEW 21000 Added columns 'alias_name' on supplier invoice list --- htdocs/fourn/facture/list.php | 36 ++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/htdocs/fourn/facture/list.php b/htdocs/fourn/facture/list.php index 70a7334196a..4df04f30f70 100644 --- a/htdocs/fourn/facture/list.php +++ b/htdocs/fourn/facture/list.php @@ -77,6 +77,7 @@ $search_refsupplier = GETPOST('search_refsupplier', 'alpha'); $search_type = GETPOST('search_type', 'int'); $search_project = GETPOST('search_project', 'alpha'); $search_company = GETPOST('search_company', 'alpha'); +$search_company_alias = GETPOST('search_company_alias', 'alpha'); $search_montant_ht = GETPOST('search_montant_ht', 'alpha'); $search_montant_vat = GETPOST('search_montant_vat', 'alpha'); $search_montant_localtax1 = GETPOST('search_montant_localtax1', 'alpha'); @@ -178,6 +179,7 @@ $arrayfields = array( 'f.date_lim_reglement'=>array('label'=>"DateDue", 'checked'=>1), 'p.ref'=>array('label'=>"ProjectRef", 'checked'=>0), 's.nom'=>array('label'=>"ThirdParty", 'checked'=>1), + 's.name_alias'=>array('label'=>"AliasNameShort", 'checked'=>0), 's.town'=>array('label'=>"Town", 'checked'=>-1), 's.zip'=>array('label'=>"Zip", 'checked'=>1), 'state.nom'=>array('label'=>"StateShort", 'checked'=>0), @@ -252,6 +254,7 @@ if (empty($reshook)) { $search_label = ""; $search_project = ''; $search_company = ""; + $search_company_alias = ""; $search_amount_no_tax = ""; $search_amount_all_tax = ""; $search_montant_ht = ''; @@ -413,7 +416,7 @@ $sql .= " f.localtax1 as total_localtax1, f.localtax2 as total_localtax2,"; $sql .= ' f.fk_multicurrency, f.multicurrency_code, f.multicurrency_tx, f.multicurrency_total_ht, f.multicurrency_total_tva as multicurrency_total_vat, f.multicurrency_total_ttc,'; $sql .= " f.note_public, f.note_private,"; $sql .= " f.fk_user_author,"; -$sql .= " s.rowid as socid, s.nom as name, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta as code_compta_client, s.code_compta_fournisseur,"; +$sql .= " s.rowid as socid, s.nom as name, s.name_alias as alias, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta as code_compta_client, s.code_compta_fournisseur,"; $sql .= " typent.code as typent_code,"; $sql .= " state.code_departement as state_code, state.nom as state_name,"; $sql .= " country.code as country_code,"; @@ -518,6 +521,9 @@ if ($search_project) { if ($search_company) { $sql .= natural_search('s.nom', $search_company); } +if ($search_company_alias) { + $sql .= natural_search('s.name_alias', $search_company_alias); +} if ($search_town) { $sql .= natural_search('s.town', $search_town); } @@ -693,6 +699,7 @@ if ($resql) { $soc->fetch($socid); if (empty($search_company)) { $search_company = $soc->name; + $search_company_alias = $soc->name_alias; } } @@ -757,6 +764,9 @@ if ($resql) { if ($search_company) { $param .= '&search_company='.urlencode($search_company); } + if ($search_company_alias) { + $param .= '&search_company_alias='.urlencode($search_company_alias); + } if ($search_login) { $param .= '&search_login='.urlencode($search_login); } @@ -1004,6 +1014,10 @@ if ($resql) { if (!empty($arrayfields['s.nom']['checked'])) { print ''; } + // Alias + if (!empty($arrayfields['s.name_alias']['checked'])) { + print ''; + } // Town if (!empty($arrayfields['s.town']['checked'])) { print ''; @@ -1181,6 +1195,9 @@ if ($resql) { if (!empty($arrayfields['s.nom']['checked'])) { print_liste_field_titre($arrayfields['s.nom']['label'], $_SERVER['PHP_SELF'], 's.nom', '', $param, '', $sortfield, $sortorder); } + if (!empty($arrayfields['s.name_alias']['checked'])) { + print_liste_field_titre($arrayfields['s.name_alias']['label'], $_SERVER['PHP_SELF'], 's.name_alias', '', $param, '', $sortfield, $sortorder); + } if (!empty($arrayfields['s.town']['checked'])) { print_liste_field_titre($arrayfields['s.town']['label'], $_SERVER["PHP_SELF"], 's.town', '', $param, '', $sortfield, $sortorder); } @@ -1188,7 +1205,10 @@ if ($resql) { print_liste_field_titre($arrayfields['s.zip']['label'], $_SERVER["PHP_SELF"], 's.zip', '', $param, '', $sortfield, $sortorder, 'center '); } if (!empty($arrayfields['state.nom']['checked'])) { - print_liste_field_titre($arrayfields['state.nom']['label'], $_SERVER["PHP_SELF"], "state.nom", "", $param, '', $sortfield, $sortorder); + print_liste_field_titre($arrayfields['state.nom']['label'], $_SERVER["PHP_SELF"], "state.name_alias", "", $param, '', $sortfield, $sortorder); + } + if (!empty($arrayfields['state.name_alias']['checked'])) { + print_liste_field_titre($arrayfields['state.name_alias']['label'], $_SERVER["PHP_SELF"], "state.nom", "", $param, '', $sortfield, $sortorder); } if (!empty($arrayfields['country.code_iso']['checked'])) { print_liste_field_titre($arrayfields['country.code_iso']['label'], $_SERVER["PHP_SELF"], "country.code_iso", "", $param, '', $sortfield, $sortorder, 'center '); @@ -1293,6 +1313,7 @@ if ($resql) { $thirdparty->id = $obj->socid; $thirdparty->name = $obj->name; + $thirdparty->name_alias = $obj->alias; $thirdparty->client = $obj->client; $thirdparty->fournisseur = $obj->fournisseur; $thirdparty->code_client = $obj->code_client; @@ -1417,7 +1438,16 @@ if ($resql) { // Third party if (!empty($arrayfields['s.nom']['checked'])) { print ''; - print $thirdparty->getNomUrl(1, 'supplier'); + print $thirdparty->getNomUrl(1, 'supplier', 0, 0, -1, empty($arrayfields['s.name_alias']['checked']) ? 0 : 1); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Alias + if (!empty($arrayfields['s.name_alias']['checked'])) { + print ''; + print $thirdparty->name_alias; print ''; if (!$i) { $totalarray['nbfield']++; From 15abd76ef4a5e5f21d3efb7465036491b2c483e2 Mon Sep 17 00:00:00 2001 From: Faustin Date: Tue, 21 Jun 2022 20:04:35 +0200 Subject: [PATCH 077/826] NEW 21000 Added columns 'alias_name' on supplier propals list --- htdocs/supplier_proposal/list.php | 32 +++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/htdocs/supplier_proposal/list.php b/htdocs/supplier_proposal/list.php index 96f8a2b2cca..894c16cacf7 100644 --- a/htdocs/supplier_proposal/list.php +++ b/htdocs/supplier_proposal/list.php @@ -61,6 +61,7 @@ $search_user = GETPOST('search_user', 'int'); $search_sale = GETPOST('search_sale', 'int'); $search_ref = GETPOST('sf_ref') ?GETPOST('sf_ref', 'alpha') : GETPOST('search_ref', 'alpha'); $search_societe = GETPOST('search_societe', 'alpha'); +$search_societe_alias = GETPOST('search_societe_alias', 'alpha'); $search_login = GETPOST('search_login', 'alpha'); $search_town = GETPOST('search_town', 'alpha'); $search_zip = GETPOST('search_zip', 'alpha'); @@ -168,6 +169,7 @@ $checkedtypetiers = 0; $arrayfields = array( 'sp.ref'=>array('label'=>$langs->trans("Ref"), 'checked'=>1), 's.nom'=>array('label'=>$langs->trans("Supplier"), 'checked'=>1), + 's.name_alias'=>array('label'=>"AliasNameShort", 'checked'=>0), 's.town'=>array('label'=>$langs->trans("Town"), 'checked'=>1), 's.zip'=>array('label'=>$langs->trans("Zip"), 'checked'=>1), 'state.nom'=>array('label'=>$langs->trans("StateShort"), 'checked'=>0), @@ -224,6 +226,7 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x' $search_sale = ''; $search_ref = ''; $search_societe = ''; + $search_societe_alias = ''; $search_montant_ht = ''; $search_montant_vat = ''; $search_montant_ttc = ''; @@ -292,7 +295,7 @@ $sql = 'SELECT'; if ($sall || $search_product_category > 0 || $search_user > 0) { $sql = 'SELECT DISTINCT'; } -$sql .= ' s.rowid as socid, s.nom as name, s.town, s.zip, s.fk_pays, s.client, s.code_client,'; +$sql .= ' s.rowid as socid, s.nom as name, s.name_alias as alias, s.town, s.zip, s.fk_pays, s.client, s.code_client,'; $sql .= " typent.code as typent_code,"; $sql .= " state.code_departement as state_code, state.nom as state_name,"; $sql .= ' sp.rowid, sp.note_public, sp.note_private, sp.total_ht, sp.total_tva, sp.total_ttc, sp.localtax1, sp.localtax2, sp.ref, sp.fk_statut as status, sp.fk_user_author, sp.date_valid, sp.date_livraison as dp,'; @@ -363,6 +366,9 @@ if ($search_ref) { if ($search_societe) { $sql .= natural_search('s.nom', $search_societe); } +if ($search_societe_alias) { + $sql .= natural_search('s.name_alias', $search_societe_alias); +} if ($search_login) { $sql .= natural_search(array('u.lastname', 'u.firstname', 'u.login'), $search_login); } @@ -521,6 +527,9 @@ if ($resql) { if ($search_societe) { $param .= '&search_societe='.urlencode($search_societe); } + if ($search_societe_alias) { + $param .= '&search_societe_alias='.urlencode($search_societe_alias); + } if ($search_user > 0) { $param .= '&search_user='.urlencode($search_user); } @@ -677,6 +686,11 @@ if ($resql) { print ''; print ''; } + if (!empty($arrayfields['s.name_alias']['checked'])) { + print ''; + print ''; + print ''; + } if (!empty($arrayfields['s.town']['checked'])) { print ''; } @@ -816,6 +830,9 @@ if ($resql) { if (!empty($arrayfields['s.nom']['checked'])) { print_liste_field_titre($arrayfields['s.nom']['label'], $_SERVER["PHP_SELF"], 's.nom', '', $param, '', $sortfield, $sortorder); } + if (!empty($arrayfields['s.name_alias']['checked'])) { + print_liste_field_titre($arrayfields['s.name_alias']['label'], $_SERVER["PHP_SELF"], 's.name_alias', '', $param, '', $sortfield, $sortorder); + } if (!empty($arrayfields['s.town']['checked'])) { print_liste_field_titre($arrayfields['s.town']['label'], $_SERVER["PHP_SELF"], 's.town', '', $param, '', $sortfield, $sortorder); } @@ -904,6 +921,7 @@ if ($resql) { // Company $companystatic->id = $obj->socid; $companystatic->name = $obj->name; + $companystatic->name_alias = $obj->alias; $companystatic->client = $obj->client; $companystatic->code_client = $obj->code_client; @@ -942,7 +960,17 @@ if ($resql) { // Thirdparty if (!empty($arrayfields['s.nom']['checked'])) { print ''; - print $companystatic->getNomUrl(1, 'supplier'); + print $companystatic->getNomUrl(1, 'supplier', 0, 0, -1, empty($arrayfields['s.name_alias']['checked']) ? 0 : 1); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Alias + if (!empty($arrayfields['s.name_alias']['checked'])) { + print ''; + print $companystatic->name_alias; print ''; if (!$i) { $totalarray['nbfield']++; From 3eff91a6dc7cb259906cfd18d6dc59d6e5b1431f Mon Sep 17 00:00:00 2001 From: atm-steve Date: Wed, 22 Jun 2022 10:50:54 +0200 Subject: [PATCH 078/826] wip: popin with new fileds --- htdocs/contrat/card.php | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php index 87d6b98475b..df74c8dbf25 100644 --- a/htdocs/contrat/card.php +++ b/htdocs/contrat/card.php @@ -1261,7 +1261,24 @@ if ($action == 'create') { // Confirmation de la fermeture $formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=".$object->id, $langs->trans("CloseAContract"), $langs->trans("ConfirmCloseContract"), "confirm_close", '', 0, 1); } elseif ($action == 'activate') { - $formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=".$object->id, $langs->trans("ActivateAllOnContract"), $langs->trans("ConfirmActivateAllOnContract"), "confirm_activate", '', 0, 1); + //$sql = "SELECT date_ouverture, date_cloture, commentaire FROM " . MAIN_DB_PREFIX ."contratdet WHERE fk_contrat = " . $object->id; + ////$sql.= ""; +// + //$result = $db->query($sql); + //if ($result) { + // $objp = $db->fetch_object($result); + //} +// + //// Definie date debut et fin par defaut + //$dateactstart = $objp->date_ouverture; + //$dateactend = $objp->date_cloture; + //$comment = $objp->commentaire; + $formquestion = array( + array('type' => 'other', 'name' => 'active', 'label' => $langs->trans("DateServiceActivate"), 'value' => $form->selectDate('', '', $usehm, $usehm, '', "active", 1, 0), 'socid', '(s.client=1 OR s.client=2 OR s.client=3)'), + array('type' => 'other', 'name' => 'active', 'label' => $langs->trans("DateEndPlanned"), 'value' => $form->selectDate('', "end", $usehm, $usehm, '', "active", 1, 0), '', ''), + array('type' => 'text', 'comment' => 'active', 'label' => $langs->trans("Comment"), 'value' => '', '', '', 'class' => 'minwidth300') + ); + $formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=".$object->id, $langs->trans("ActivateAllOnContract"), $langs->trans("ConfirmActivateAllOnContract"), "confirm_activate", $formquestion, 'yes', 1, 280); } elseif ($action == 'clone') { // Clone confirmation $formquestion = array(array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', '(s.client=1 OR s.client=2 OR s.client=3)'))); From 3d7904c404f970a5523ee96d53d25d923ae18e62 Mon Sep 17 00:00:00 2001 From: atm-steve Date: Wed, 22 Jun 2022 12:05:39 +0200 Subject: [PATCH 079/826] feat: activate all services on contrat --- htdocs/contrat/card.php | 24 +++++++----------------- htdocs/contrat/class/contrat.class.php | 4 ++-- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php index df74c8dbf25..0254efdbe95 100644 --- a/htdocs/contrat/card.php +++ b/htdocs/contrat/card.php @@ -785,8 +785,10 @@ if (empty($reshook)) { setEventMessages($object->error, $object->errors, 'errors'); } } elseif ($action == 'confirm_activate' && $confirm == 'yes' && $user->rights->contrat->creer) { - // Close all lines - $result = $object->activateAll($user); + $date_start = dol_mktime(12, 0, 0, GETPOST('d_startmonth'), GETPOST('d_startday'), GETPOST('d_startyear')); + $date_end = dol_mktime(12, 0, 0, GETPOST('d_endmonth'), GETPOST('d_endday'), GETPOST('d_endyear')); + $comment = GETPOST('comment', 'alpha'); + $result = $object->activateAll($user, $date_start, 0, $comment, $date_end); if ($result < 0) { setEventMessages($object->error, $object->errors, 'errors'); } @@ -1261,22 +1263,10 @@ if ($action == 'create') { // Confirmation de la fermeture $formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=".$object->id, $langs->trans("CloseAContract"), $langs->trans("ConfirmCloseContract"), "confirm_close", '', 0, 1); } elseif ($action == 'activate') { - //$sql = "SELECT date_ouverture, date_cloture, commentaire FROM " . MAIN_DB_PREFIX ."contratdet WHERE fk_contrat = " . $object->id; - ////$sql.= ""; -// - //$result = $db->query($sql); - //if ($result) { - // $objp = $db->fetch_object($result); - //} -// - //// Definie date debut et fin par defaut - //$dateactstart = $objp->date_ouverture; - //$dateactend = $objp->date_cloture; - //$comment = $objp->commentaire; $formquestion = array( - array('type' => 'other', 'name' => 'active', 'label' => $langs->trans("DateServiceActivate"), 'value' => $form->selectDate('', '', $usehm, $usehm, '', "active", 1, 0), 'socid', '(s.client=1 OR s.client=2 OR s.client=3)'), - array('type' => 'other', 'name' => 'active', 'label' => $langs->trans("DateEndPlanned"), 'value' => $form->selectDate('', "end", $usehm, $usehm, '', "active", 1, 0), '', ''), - array('type' => 'text', 'comment' => 'active', 'label' => $langs->trans("Comment"), 'value' => '', '', '', 'class' => 'minwidth300') + array('type' => 'date', 'name' => 'd_start', 'label' => $langs->trans("DateServiceActivate"), /*'value' => $form->selectDate('', '', $usehm, $usehm, '', "active", 1, 0),*/ /*'socid', '(s.client=1 OR s.client=2 OR s.client=3)'*/), + array('type' => 'date', 'name' => 'd_end', 'label' => $langs->trans("DateEndPlanned"), /*'value' => $form->selectDate('', "end", $usehm, $usehm, '', "active", 1, 0),*/ '', ''), + array('type' => 'text', 'name' => 'comment', 'label' => $langs->trans("Comment"), 'value' => '', '', '', 'class' => 'minwidth300') ); $formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=".$object->id, $langs->trans("ActivateAllOnContract"), $langs->trans("ConfirmActivateAllOnContract"), "confirm_activate", $formquestion, 'yes', 1, 280); } elseif ($action == 'clone') { diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 4e4437c1b2c..87f728b18a4 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -369,7 +369,7 @@ class Contrat extends CommonObject * @return int <0 if KO, >0 if OK * @see () */ - public function activateAll($user, $date_start = '', $notrigger = 0, $comment = '') + public function activateAll($user, $date_start = '', $notrigger = 0, $comment = '', $date_end = '') { if (empty($date_start)) { $date_start = dol_now(); @@ -387,7 +387,7 @@ class Contrat extends CommonObject if ($contratline->statut != ContratLigne::STATUS_OPEN) { $contratline->context = $this->context; - $result = $contratline->active_line($user, $date_start, -1, $comment); // This call trigger LINECONTRACT_ACTIVATE + $result = $contratline->active_line($user, $date_start, !empty($date_end) ? $date_end : -1, $comment); // This call trigger LINECONTRACT_ACTIVATE if ($result < 0) { $error++; $this->error = $contratline->error; From 63cca2c7cfe0cfc664299a2b9948107e1dc46250 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Wed, 22 Jun 2022 10:16:27 +0000 Subject: [PATCH 080/826] Fixing style errors. --- htdocs/core/class/html.formfile.class.php | 1 - 1 file changed, 1 deletion(-) diff --git a/htdocs/core/class/html.formfile.class.php b/htdocs/core/class/html.formfile.class.php index 0b87823c38d..69c349616f5 100644 --- a/htdocs/core/class/html.formfile.class.php +++ b/htdocs/core/class/html.formfile.class.php @@ -1282,7 +1282,6 @@ class FormFile if ($file['name'] != '.' && $file['name'] != '..' && !preg_match('/\.meta$/i', $file['name'])) { - if (array_key_exists('rowid', $filearray[$key]) && $filearray[$key]['rowid'] > 0) { $lastrowid = $filearray[$key]['rowid']; } From fd0bbf8ebc94c27ba44f213e5c88ae8c6e5447af Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Wed, 22 Jun 2022 12:25:59 +0200 Subject: [PATCH 081/826] fix coments --- htdocs/core/tpl/filemanager.tpl.php | 4 +++- htdocs/ecm/dir_add_card.php | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/htdocs/core/tpl/filemanager.tpl.php b/htdocs/core/tpl/filemanager.tpl.php index 2290e9093d8..2c4b2f5dea8 100644 --- a/htdocs/core/tpl/filemanager.tpl.php +++ b/htdocs/core/tpl/filemanager.tpl.php @@ -53,8 +53,10 @@ if ($module == 'medias') { $permtoupload = ($user->rights->mailing->creer || $user->rights->website->write); $showroot = 1; } -$section = 0; +if (!isset($section)) { + $section = 0; +} // Confirm remove file (for non javascript users) if (($action == 'delete' || $action == 'file_manager_delete') && empty($conf->use_javascript_ajax)) { diff --git a/htdocs/ecm/dir_add_card.php b/htdocs/ecm/dir_add_card.php index a6c980e5908..e5df264e377 100644 --- a/htdocs/ecm/dir_add_card.php +++ b/htdocs/ecm/dir_add_card.php @@ -230,7 +230,7 @@ if ($action == 'create') { print ''; // Label - print ''."\n"; + print ''."\n"; print ''; + + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + // Action column + print ''; + } + if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER_IN_LIST)) { print ''; @@ -1528,13 +1537,20 @@ if ($resql) { print ''; } // Action column - print ''; + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } print "\n"; print ''; + + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', 'align="center"', $sortfield, $sortorder, 'maxwidthsearch '); + } + if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER_IN_LIST)) { print_liste_field_titre('#', $_SERVER['PHP_SELF'], '', '', $param, '', $sortfield, $sortorder); } @@ -1685,7 +1701,10 @@ if ($resql) { if (!empty($arrayfields['f.fk_statut']['checked'])) { print_liste_field_titre($arrayfields['f.fk_statut']['label'], $_SERVER["PHP_SELF"], "f.fk_statut,f.paye,f.type", "", $param, 'class="right"', $sortfield, $sortorder); } - print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', 'align="center"', $sortfield, $sortorder, 'maxwidthsearch '); + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', 'align="center"', $sortfield, $sortorder, 'maxwidthsearch '); + } + print "\n"; $projectstatic = new Project($db); @@ -1818,6 +1837,20 @@ if ($resql) { } print '>'; + + // Action column + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } + // No if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER_IN_LIST)) { print ''; @@ -2392,19 +2425,21 @@ if ($resql) { } // Action column (Show the massaction button only when this page is not opend from the Extended POS) - print ''; } - print ''; if (!$i) { $totalarray['nbfield']++; } - print "\n"; $i++; From 10a9ab5ed179a3c02f21d8d9d17544bc04481a74 Mon Sep 17 00:00:00 2001 From: Faustin Date: Fri, 24 Jun 2022 13:56:24 +0200 Subject: [PATCH 092/826] NEW #20650 enabled checkcolumn on left for commande list --- htdocs/commande/list.php | 55 ++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index 350674370e9..aa13e9607e6 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -1374,7 +1374,7 @@ if ($resql) { } $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; - $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields + $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')); // This also change content of $arrayfields $selectedfields .= $form->showCheckAddButtons('checkforselect', 1); if (GETPOST('autoselectall', 'int')) { @@ -1391,6 +1391,14 @@ if ($resql) { print '
'.$langs->trans("Label").'
'.$langs->trans("Label").'label).'" autofocus>
'.$langs->trans("AddIn").''; print $formecm->selectAllSections((GETPOST("catParent", 'alpha') ? GETPOST("catParent", 'alpha') : $ecmdir->fk_parent), 'catParent', $module); From ce7db0004bdf68664cc32f03a45f504189c32ee6 Mon Sep 17 00:00:00 2001 From: Quatadah Nasdami Date: Wed, 22 Jun 2022 14:41:46 +0200 Subject: [PATCH 082/826] two changes to feature request --- htdocs/core/class/commonobject.class.php | 3 +++ htdocs/core/lib/files.lib.php | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 4a95bb7d345..ff240501d1e 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -5516,6 +5516,9 @@ abstract class CommonObject if ($this->element == 'bank_account' && !empty($conf->global->BANK_ACCOUNT_ALLOW_EXTERNAL_DOWNLOAD)) { $setsharekey = true; } + if ($this->element == 'product' && !empty($conf->global->PRODUCT_ALLOW_EXTERNAL_DOWNLOAD)) { + $setsharekey = true; + } if ($this->element == 'contrat' && !empty($conf->global->CONTRACT_ALLOW_EXTERNAL_DOWNLOAD)) { $setsharekey = true; } diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index 482831191d6..e8134c6f0dd 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -1727,6 +1727,13 @@ function dol_add_file_process($upload_dir, $allowoverwrite = 0, $donotupdatesess } } + // Update table of files + if ($donotupdatesession == 1) { + $sharefile = 0; + if ($TFile['type'][$i] == 'application/pdf' && strpos($_SERVER["REQUEST_URI"], 'product') !== false && !empty($conf->global->PRODUCT_ALLOW_EXTERNAL_DOWNLOAD)) $sharefile = 1; + $result = addFileIntoDatabaseIndex($upload_dir, basename($destfile), $TFile['name'][$i], 'uploaded', $sharefile); + } + $nbok++; } else { $langs->load("errors"); From a14b7009002dd65071adebd5c386838e17101eba Mon Sep 17 00:00:00 2001 From: bagtaib Date: Wed, 22 Jun 2022 15:09:23 +0200 Subject: [PATCH 083/826] New #19511 --- htdocs/core/lib/functions.lib.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 13d44e1ec8a..c86cd4bd77b 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -3310,6 +3310,17 @@ function dol_print_phone($phone, $countrycode = '', $cid = 0, $socid = 0, $addli //ex: +61_A_BCDE_FGHI $newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 1).$separ.substr($newphone, 4, 4).$separ.substr($newphone, 8, 4); } + } elseif (strtoupper($countrycode) == "LU") { + // Luxembourg + if (dol_strlen($phone) == 10) {// fixe 6 chiffres +352_AA_BB_CC + $newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 2).$separ.substr($newphone, 6, 2).$separ.substr($newphone, 8, 2); + } elseif (dol_strlen($phone) == 11) {// fixe 7 chiffres +352_AA_BB_CC_D + $newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 2).$separ.substr($newphone, 6, 2).$separ.substr($newphone, 8, 2).$separ.substr($newphone, 10, 1); + } elseif (dol_strlen($phone) == 12) {// fixe 8 chiffres +352_AA_BB_CC_DD + $newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 2).$separ.substr($newphone, 6, 2).$separ.substr($newphone, 8, 2).$separ.substr($newphone, 10, 2); + } elseif (dol_strlen($phone) == 13) {// mobile +352_AAA_BB_CC_DD + $newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 3).$separ.substr($newphone, 7, 2).$separ.substr($newphone, 9, 2).$separ.substr($newphone, 11, 2); + } } if (!empty($addlink)) { // Link on phone number (+ link to add action if conf->global->AGENDA_ADDACTIONFORPHONE set) if ($conf->browser->layout == 'phone' || (!empty($conf->clicktodial->enabled) && !empty($conf->global->CLICKTODIAL_USE_TEL_LINK_ON_PHONE_NUMBERS))) { // If phone or option for, we use link of phone From e7858a97bf7c71cb3102b22c74de40a0535f4fc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?This=20Charl=C3=A8ne?= <1179011+defrance@users.noreply.github.com> Date: Thu, 23 Jun 2022 17:46:32 +0200 Subject: [PATCH 084/826] Delete llx_element_tag.sql --- .../install/mysql/tables/llx_element_tag.sql | 25 ------------------- 1 file changed, 25 deletions(-) delete mode 100644 htdocs/install/mysql/tables/llx_element_tag.sql diff --git a/htdocs/install/mysql/tables/llx_element_tag.sql b/htdocs/install/mysql/tables/llx_element_tag.sql deleted file mode 100644 index d43ced98130..00000000000 --- a/htdocs/install/mysql/tables/llx_element_tag.sql +++ /dev/null @@ -1,25 +0,0 @@ --- ============================================================================ --- Copyright (C) 2021 Maxime Kohlhaas --- --- This program is free software; you can redistribute it and/or modify --- it under the terms of the GNU General Public License as published by --- the Free Software Foundation; either version 3 of the License, or --- (at your option) any later version. --- --- This program is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU General Public License for more details. --- --- You should have received a copy of the GNU General Public License --- along with this program. If not, see . --- --- ============================================================================ - -create table llx_element_tag -( - rowid integer AUTO_INCREMENT PRIMARY KEY, - fk_categorie integer NOT NULL, - fk_element integer NOT NULL, - import_key varchar(14) -)ENGINE=innodb; From 7594c142360b82a4b483fe381653001bc54a3c5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?This=20Charl=C3=A8ne?= <1179011+defrance@users.noreply.github.com> Date: Thu, 23 Jun 2022 17:46:57 +0200 Subject: [PATCH 085/826] Delete llx_element_tag.key.sql --- .../mysql/tables/llx_element_tag.key.sql | 21 ------------------- 1 file changed, 21 deletions(-) delete mode 100644 htdocs/install/mysql/tables/llx_element_tag.key.sql diff --git a/htdocs/install/mysql/tables/llx_element_tag.key.sql b/htdocs/install/mysql/tables/llx_element_tag.key.sql deleted file mode 100644 index d3a0b38afa9..00000000000 --- a/htdocs/install/mysql/tables/llx_element_tag.key.sql +++ /dev/null @@ -1,21 +0,0 @@ --- ============================================================================ --- Copyright (C) 2021 Maxime Kohlhaas --- --- This program is free software; you can redistribute it and/or modify --- it under the terms of the GNU General Public License as published by --- the Free Software Foundation; either version 3 of the License, or --- (at your option) any later version. --- --- This program is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU General Public License for more details. --- --- You should have received a copy of the GNU General Public License --- along with this program. If not, see . --- --- ============================================================================ - -ALTER TABLE llx_element_tag ADD UNIQUE INDEX idx_element_tag_uk (fk_categorie, fk_element); - -ALTER TABLE llx_element_tag ADD CONSTRAINT fk_element_tag_categorie_rowid FOREIGN KEY (fk_categorie) REFERENCES llx_categorie (rowid); From f48c9903757771fc3897bbf4b5044eda1db70598 Mon Sep 17 00:00:00 2001 From: Quatadah Nasdami Date: Thu, 23 Jun 2022 17:47:56 +0200 Subject: [PATCH 086/826] adding dropdown menu in case of a lot of buttons in project --- htdocs/projet/card.php | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index 0cfe126d69b..3193c410679 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -1318,46 +1318,52 @@ if ($action == 'create' && $user->rights->projet->creer) { // Add button to create objects from project if (!empty($conf->global->PROJECT_SHOW_CREATE_OBJECT_BUTTON)) { + print''; + //print''; } // Clone From 205022b4c852d421e6b33bb5640303bbe158f47f Mon Sep 17 00:00:00 2001 From: Quatadah Nasdami Date: Thu, 23 Jun 2022 18:09:00 +0200 Subject: [PATCH 087/826] removing useless block --- htdocs/core/lib/files.lib.php | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index e8134c6f0dd..beb25a3d5fe 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -1717,7 +1717,9 @@ function dol_add_file_process($upload_dir, $allowoverwrite = 0, $donotupdatesess // Update index table of files (llx_ecm_files) if ($donotupdatesession == 1) { - $result = addFileIntoDatabaseIndex($upload_dir, basename($destfile).($resupload == 2 ? '.noexe' : ''), $TFile['name'][$i], 'uploaded', 0, $object); + $sharefile = 0; + if ($TFile['type'][$i] == 'application/pdf' && strpos($_SERVER["REQUEST_URI"], 'product') !== false && !empty($conf->global->PRODUCT_ALLOW_EXTERNAL_DOWNLOAD)) $sharefile = 1; + $result = addFileIntoDatabaseIndex($upload_dir, basename($destfile).($resupload == 2 ? '.noexe' : ''), $TFile['name'][$i], 'uploaded', $sharefile, $object); if ($result < 0) { if ($allowoverwrite) { // Do not show error message. We can have an error due to DB_ERROR_RECORD_ALREADY_EXISTS @@ -1727,13 +1729,6 @@ function dol_add_file_process($upload_dir, $allowoverwrite = 0, $donotupdatesess } } - // Update table of files - if ($donotupdatesession == 1) { - $sharefile = 0; - if ($TFile['type'][$i] == 'application/pdf' && strpos($_SERVER["REQUEST_URI"], 'product') !== false && !empty($conf->global->PRODUCT_ALLOW_EXTERNAL_DOWNLOAD)) $sharefile = 1; - $result = addFileIntoDatabaseIndex($upload_dir, basename($destfile), $TFile['name'][$i], 'uploaded', $sharefile); - } - $nbok++; } else { $langs->load("errors"); From d6330fd3f73137c493ed9bad5935889f348e7195 Mon Sep 17 00:00:00 2001 From: Quatadah Nasdami Date: Thu, 23 Jun 2022 19:15:05 +0200 Subject: [PATCH 088/826] initialising the smiley function --- htdocs/core/lib/website.lib.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/htdocs/core/lib/website.lib.php b/htdocs/core/lib/website.lib.php index e9de957e4a8..d9602379977 100644 --- a/htdocs/core/lib/website.lib.php +++ b/htdocs/core/lib/website.lib.php @@ -213,6 +213,18 @@ function dolWebsiteReplacementOfLinks($website, $content, $removephppart = 0, $c return $content; } +/** + * Converts smiley string into the utf8 sequence. + * @param string $content Content to replace + * @return string Replacement of all smiley strings with their utf8 code + * @see dolWebsiteOutput() + */ +function dolReplaceSmileyCodeWithUTF8($content) +{ + return $content; +} + + /** * Render a string of an HTML content and output it. * Used to ouput the page when viewed from a server (Dolibarr or Apache). @@ -369,6 +381,8 @@ function dolWebsiteOutput($content, $contenttype = 'html', $containerid = '') $content = str_replace(' Date: Thu, 23 Jun 2022 22:50:23 +0200 Subject: [PATCH 089/826] NEW #20650 thirdparty list : making the dropdown select appears on screen when checked boxes appears on left --- htdocs/core/class/html.form.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 88f7f7aaa9a..31d54797489 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -8366,7 +8366,7 @@ class Form
'; + $searchpicto = $form->showFilterButtons('left'); + print $searchpicto; + print ''; print ''; - $searchpicto = $form->showFilterButtons(); - print $searchpicto; - print ''; + $searchpicto = $form->showFilterButtons(); + print $searchpicto; + print '
'; + if (($massactionbutton || $massaction) && $contextpage != 'poslist') { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($obj->id, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print ''.(($offset * $limit) + $i).''; - if (($massactionbutton || $massaction) && $contextpage != 'poslist') { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined - $selected = 0; - if (in_array($obj->id, $arrayofselected)) { - $selected = 1; + + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + if (($massactionbutton || $massaction) && $contextpage != 'poslist') { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($obj->id, $arrayofselected)) { + $selected = 1; + } + print ''; } - print ''; + print '
'."\n"; print ''; + // Action column + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } + // Ref if (!empty($arrayfields['c.ref']['checked'])) { print ''; } // Action column - print ''; - + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } print "\n"; // Fields title print ''; + + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'maxwidthsearch center '); + } if (!empty($arrayfields['c.ref']['checked'])) { print_liste_field_titre($arrayfields['c.ref']['label'], $_SERVER["PHP_SELF"], 'c.ref', '', $param, '', $sortfield, $sortorder); } @@ -1794,7 +1807,9 @@ if ($resql) { if (!empty($arrayfields['c.fk_statut']['checked'])) { print_liste_field_titre($arrayfields['c.fk_statut']['label'], $_SERVER["PHP_SELF"], "c.fk_statut", "", $param, '', $sortfield, $sortorder, 'center '); } - print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'maxwidthsearch center '); + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'maxwidthsearch center '); + } print ''."\n"; $total = 0; @@ -1875,6 +1890,18 @@ if ($resql) { print ''; + // Action column + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; if (!$i) { From 6118cb69e6e7eb1bfa340b438b7854bfc97ca2fc Mon Sep 17 00:00:00 2001 From: Faustin Date: Fri, 24 Jun 2022 15:01:32 +0200 Subject: [PATCH 093/826] NEW #20650 enabled checkcolumn on left for propal list --- htdocs/comm/propal/list.php | 58 ++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/htdocs/comm/propal/list.php b/htdocs/comm/propal/list.php index e490a5ca7ac..722fbbd09e5 100644 --- a/htdocs/comm/propal/list.php +++ b/htdocs/comm/propal/list.php @@ -1096,13 +1096,22 @@ if ($resql) { } $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; - $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields + $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')); // This also change content of $arrayfields $selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : ''); print '
'; print '
'; + $searchpicto = $form->showFilterButtons('left'); + print $searchpicto; + print ''; @@ -1643,15 +1651,20 @@ if ($resql) { print ''; - $searchpicto = $form->showFilterButtons(); - print $searchpicto; - print ''; + $searchpicto = $form->showFilterButtons(); + print $searchpicto; + print '
'; + if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($obj->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; + } + } + // Ref if (!empty($arrayfields['c.ref']['checked'])) { print ''; @@ -2435,13 +2462,15 @@ if ($resql) { } // Action column - print ''; - if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined - $selected = 0; - if (in_array($obj->rowid, $arrayofselected)) { - $selected = 1; + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($obj->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; } - print ''; } print '
'."\n"; print ''; + + // Action column + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } + if (!empty($arrayfields['p.ref']['checked'])) { print ''; } // Action column - print ''; - + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } print "\n"; // Fields title print ''; + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', 'align="center"', $sortfield, $sortorder, 'maxwidthsearch '); + } if (!empty($arrayfields['p.ref']['checked'])) { print_liste_field_titre($arrayfields['p.ref']['label'], $_SERVER["PHP_SELF"], 'p.ref', '', $param, '', $sortfield, $sortorder); } @@ -1527,7 +1540,9 @@ if ($resql) { if (!empty($arrayfields['p.fk_statut']['checked'])) { print_liste_field_titre($arrayfields['p.fk_statut']['label'], $_SERVER["PHP_SELF"], "p.fk_statut", "", $param, 'class="right"', $sortfield, $sortorder); } - print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', 'align="center"', $sortfield, $sortorder, 'maxwidthsearch '); + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', 'align="center"', $sortfield, $sortorder, 'maxwidthsearch '); + } print ''."\n"; $now = dol_now(); @@ -1608,6 +1623,19 @@ if ($resql) { print ''; + // Action column + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } + if (!empty($arrayfields['p.ref']['checked'])) { print ''; } - print ''; if (!$i) { $totalarray['nbfield']++; } From 1cc9eda9a6a4168ecdcd2ac60dd66292da30cb0d Mon Sep 17 00:00:00 2001 From: Faustin Date: Fri, 24 Jun 2022 16:43:28 +0200 Subject: [PATCH 094/826] NEW #20650 completing checkcolumn on left for propal list --- htdocs/adherents/list.php | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/htdocs/adherents/list.php b/htdocs/adherents/list.php index 8bf7f7af6a6..3075225abb9 100644 --- a/htdocs/adherents/list.php +++ b/htdocs/adherents/list.php @@ -675,7 +675,7 @@ if (!empty($moreforfilter)) { } $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; -$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields +$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')); // This also change content of $arrayfields if ($massactionbutton) { $selectedfields .= $form->showCheckAddButtons('checkforselect', 1); } @@ -685,7 +685,13 @@ print '
'; + $searchpicto = $form->showFilterButtons('left'); + print $searchpicto; + print ''; print ''; @@ -1365,16 +1374,20 @@ if ($resql) { print ''; - $searchpicto = $form->showFilterButtons(); - print $searchpicto; - print ''; + $searchpicto = $form->showFilterButtons(); + print $searchpicto; + print '
'; + if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($obj->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print ''; @@ -2120,15 +2148,17 @@ if ($resql) { } } // Action column - print ''; - if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined - $selected = 0; - if (in_array($obj->rowid, $arrayofselected)) { - $selected = 1; + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($obj->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; } - print ''; + print '
'; - +// Action column +if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; +} // Line numbering if (!empty($conf->global->MAIN_SHOW_TECHNICAL_ID)) { print ''; @@ -962,6 +968,19 @@ while ($i < min($num, $limit)) { print ''; + // Action column + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } + if (!empty($conf->global->MAIN_SHOW_TECHNICAL_ID)) { print ''; if (!$i) { From 1db386c6956792e82bde64c298f90d3a83ee1255 Mon Sep 17 00:00:00 2001 From: Faustin Date: Fri, 24 Jun 2022 17:00:32 +0200 Subject: [PATCH 095/826] NEW #20650 completing checkcolumn on left for contact list --- htdocs/contact/list.php | 55 ++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/htdocs/contact/list.php b/htdocs/contact/list.php index e68274ecff2..ca948f8d1ab 100644 --- a/htdocs/contact/list.php +++ b/htdocs/contact/list.php @@ -772,7 +772,7 @@ print $hookmanager->resPrint; print ''; $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; -$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields +$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')); // This also change content of $arrayfields if ($massactionbutton) { $selectedfields .= $form->showCheckAddButtons('checkforselect', 1); } @@ -782,6 +782,13 @@ print '
'; + $searchpicto = $form->showFilterButtons('left'); + print $searchpicto; + print ' 
'; + if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($obj->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print ''.$obj->rowid.'
'; +// Action column +if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; +} if (!empty($arrayfields['p.rowid']['checked'])) { print ''; } // Action column -print ''; - +if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; +} print ''; // Ligne des titres print ''; +if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); +} if (!empty($arrayfields['p.rowid']['checked'])) { print_liste_field_titre($arrayfields['p.rowid']['label'], $_SERVER["PHP_SELF"], "p.rowid", "", $param, "", $sortfield, $sortorder); } @@ -1032,7 +1043,9 @@ if (!empty($arrayfields['p.statut']['checked'])) { if (!empty($arrayfields['p.import_key']['checked'])) { print_liste_field_titre($arrayfields['p.import_key']['label'], $_SERVER["PHP_SELF"], "p.import_key", "", $param, '', $sortfield, $sortorder, 'center '); } -print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); +if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); +} print "\n"; @@ -1064,6 +1077,18 @@ while ($i < min($num, $limit)) { print ''; + // Action column + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } // ID if (!empty($arrayfields['p.rowid']['checked'])) { print ''; } - print ''; if (!$i) { $totalarray['nbfield']++; } From 4b704e40e7a1fabfddd62cd49f8852d13c197255 Mon Sep 17 00:00:00 2001 From: Faustin Date: Fri, 24 Jun 2022 17:12:03 +0200 Subject: [PATCH 096/826] NEW #20650 completing checkcolumn on left for product list --- htdocs/product/list.php | 56 ++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/htdocs/product/list.php b/htdocs/product/list.php index 770c819ac3c..ff75416b13c 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -852,7 +852,7 @@ if ($resql) { $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; - $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields + $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')); // This also change content of $arrayfields if ($massactionbutton) { $selectedfields .= $form->showCheckAddButtons('checkforselect', 1); } @@ -862,6 +862,12 @@ if ($resql) { // Lines with input filters print ''; + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } if (!empty($arrayfields['p.rowid']['checked'])) { print ''; } - print ''; - + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } print ''; print ''; + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); + } if (!empty($arrayfields['p.rowid']['checked'])) { print_liste_field_titre($arrayfields['p.rowid']['label'], $_SERVER["PHP_SELF"], "p.rowid", "", $param, "", $sortfield, $sortorder); } @@ -1275,7 +1285,9 @@ if ($resql) { if (!empty($arrayfields['p.tobuy']['checked'])) { print_liste_field_titre($arrayfields['p.tobuy']['label'], $_SERVER["PHP_SELF"], "p.tobuy", "", $param, '', $sortfield, $sortorder, 'center '); } - print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); + } print "\n"; @@ -1352,6 +1364,18 @@ if ($resql) { print ''; + // Action column + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } // Ref if (!empty($arrayfields['p.rowid']['checked'])) { print ''; } - print ''; if (!$i) { $totalarray['nbfield']++; } From 1b81b5be5a114caaa5d0d6002907e3299e7d0623 Mon Sep 17 00:00:00 2001 From: Faustin Date: Fri, 24 Jun 2022 17:23:58 +0200 Subject: [PATCH 097/826] NEW #20650 completing checkcolumn on left for stock list --- htdocs/product/stock/list.php | 56 ++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/htdocs/product/stock/list.php b/htdocs/product/stock/list.php index 4271ac5d8c2..cc94ae303ec 100644 --- a/htdocs/product/stock/list.php +++ b/htdocs/product/stock/list.php @@ -443,7 +443,7 @@ if (!empty($moreforfilter)) { } $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; -$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields +$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')); // This also change content of $arrayfields $selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : ''); print '
'; @@ -452,7 +452,13 @@ print '
'; + $searchpicto = $form->showFilterButtons('left'); + print $searchpicto; + print ''; print ''; @@ -934,15 +941,19 @@ if (!empty($arrayfields['p.import_key']['checked'])) { print ''; -$searchpicto = $form->showFilterAndCheckAddButtons(0); -print $searchpicto; -print ''; + $searchpicto = $form->showFilterAndCheckAddButtons(0); + print $searchpicto; + print '
'; + if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($obj->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print ''; @@ -1292,15 +1317,17 @@ while ($i < min($num, $limit)) { } // Action column - print ''; - if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined - $selected = 0; - if (in_array($obj->rowid, $arrayofselected)) { - $selected = 1; + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($obj->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; } - print ''; + print '
'; + $searchpicto = $form->showFilterButtons('left'); + print $searchpicto; + print ''; print ''; @@ -1115,14 +1121,18 @@ if ($resql) { print $form->selectarray('search_tobuy', array('0'=>$langs->trans('ProductStatusNotOnBuyShort'), '1'=>$langs->trans('ProductStatusOnBuyShort')), $search_tobuy, 1); print ''; - $searchpicto = $form->showFilterButtons(); - print $searchpicto; - print ''; + $searchpicto = $form->showFilterButtons(); + print $searchpicto; + print '
'; + if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($obj->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print ''; @@ -1895,16 +1919,18 @@ if ($resql) { } } - // Action - print ''; - if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined - $selected = 0; - if (in_array($obj->rowid, $arrayofselected)) { - $selected = 1; + // Action column + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($obj->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; } - print ''; + print '
'; - +// Action column +if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; +} foreach ($object->fields as $key => $val) { if ($key == 'statut') { continue; @@ -508,16 +514,22 @@ if (!empty($arrayfields['t.statut']['checked'])) { } // Action column -print ''; +if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; +} print ''."\n"; // Fields title label // -------------------------------------------------------------------- print ''; +// Action column +if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; +} foreach ($object->fields as $key => $val) { if ($key == 'statut') { continue; @@ -562,7 +574,9 @@ if (!empty($arrayfields['t.statut']['checked'])) { } // Action column -print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; +if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; +} print ''."\n"; // Loop on record @@ -585,6 +599,18 @@ while ($i < min($num, $limit)) { // Show here line of result print ''; + // Action column + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } foreach ($warehouse->fields as $key => $val) { if ($key == 'statut') { continue; @@ -704,15 +730,17 @@ while ($i < min($num, $limit)) { } // Action column - print ''; } - print ''; if (!$i) { $totalarray['nbfield']++; } From 9ede77c0e773243eec4ce46e50eda4c9b4f86c3c Mon Sep 17 00:00:00 2001 From: Faustin Date: Fri, 24 Jun 2022 17:32:28 +0200 Subject: [PATCH 098/826] NEW #20650 completing checkcolumn on left for expedition list --- htdocs/expedition/list.php | 54 +++++++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 13 deletions(-) diff --git a/htdocs/expedition/list.php b/htdocs/expedition/list.php index 6b67f419da5..adc80e27b64 100644 --- a/htdocs/expedition/list.php +++ b/htdocs/expedition/list.php @@ -611,7 +611,7 @@ if (!empty($moreforfilter)) { } $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; -$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); +$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')); if ($massactionbutton) { $selectedfields .= $form->showCheckAddButtons('checkforselect', 1); // This also change content of $arrayfields } @@ -621,6 +621,13 @@ print '
'; + $searchpicto = $form->showFilterButtons('left'); + print $searchpicto; + print ''; -$searchpicto = $form->showFilterButtons(); -print $searchpicto; -print ''; + $searchpicto = $form->showFilterButtons(); + print $searchpicto; + print '
'; + if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($obj->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print ''; - if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined - $selected = 0; - if (in_array($obj->rowid, $arrayofselected)) { - $selected = 1; + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($obj->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; } - print ''; + print '
'; +// Action column +if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; +} // Ref if (!empty($arrayfields['e.ref']['checked'])) { print ''; } // Action column -print ''; +if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; +} print "\n"; print ''; +if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); +} if (!empty($arrayfields['e.ref']['checked'])) { print_liste_field_titre($arrayfields['e.ref']['label'], $_SERVER["PHP_SELF"], "e.ref", "", $param, '', $sortfield, $sortorder); } @@ -809,7 +821,9 @@ if (!empty($arrayfields['e.fk_statut']['checked'])) { if (!empty($arrayfields['e.billed']['checked'])) { print_liste_field_titre($arrayfields['e.billed']['label'], $_SERVER["PHP_SELF"], "e.billed", "", $param, '', $sortfield, $sortorder, 'center '); } -print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); +if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); +} print "\n"; $typenArray = $formcompany->typent_array(1); @@ -832,6 +846,18 @@ while ($i < min($num, $limit)) { print ''; + // Action column + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } // Ref if (!empty($arrayfields['e.ref']['checked'])) { print ''; } - print ''; if (!$i) { $totalarray['nbfield']++; } From d2e7ff3bfbe6b0877b63d699adf7fdfd8ea0f2db Mon Sep 17 00:00:00 2001 From: Faustin Date: Fri, 24 Jun 2022 17:38:58 +0200 Subject: [PATCH 099/826] NEW #20650 completing checkcolumn on left for reception list --- htdocs/reception/list.php | 57 +++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/htdocs/reception/list.php b/htdocs/reception/list.php index 5cdbb201d87..88c86168678 100644 --- a/htdocs/reception/list.php +++ b/htdocs/reception/list.php @@ -751,7 +751,7 @@ if (!empty($moreforfilter)) { } $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; -$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields +$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')); // This also change content of $arrayfields $selectedfields .= $form->showCheckAddButtons('checkforselect', 1); @@ -761,6 +761,13 @@ print '
'; + $searchpicto = $form->showFilterButtons('left'); + print $searchpicto; + print ''; @@ -742,13 +749,18 @@ if (!empty($arrayfields['e.billed']['checked'])) { print ''; -$searchpicto = $form->showFilterAndCheckAddButtons(0); -print $searchpicto; -print ''; + $searchpicto = $form->showFilterAndCheckAddButtons(0); + print $searchpicto; + print '
'; + if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($obj->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print ''; @@ -1008,15 +1034,17 @@ while ($i < min($num, $limit)) { } // Action column - print ''; - if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined - $selected = 0; - if (in_array($obj->rowid, $arrayofselected)) { - $selected = 1; + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($obj->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; } - print ''; + print '
'; +// Action column +if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; +} // Ref if (!empty($arrayfields['e.ref']['checked'])) { print ''; } // Action column -print ''; +if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; +} print "\n"; print ''; +if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); +} if (!empty($arrayfields['e.ref']['checked'])) { print_liste_field_titre($arrayfields['e.ref']['label'], $_SERVER["PHP_SELF"], "e.ref", "", $param, '', $sortfield, $sortorder); } @@ -907,7 +919,9 @@ if (!empty($arrayfields['e.fk_statut']['checked'])) { if (!empty($arrayfields['e.billed']['checked'])) { print_liste_field_titre($arrayfields['e.billed']['label'], $_SERVER["PHP_SELF"], "e.billed", "", $param, '', $sortfield, $sortorder, 'center '); } -print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); +if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); +} print "\n"; $i = 0; @@ -926,6 +940,19 @@ while ($i < min($num, $limit)) { print ''; + // Action column + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } // Ref if (!empty($arrayfields['e.ref']['checked'])) { print ''; } - print ''; if (!$i) { $totalarray['nbfield']++; } From 6b421823f55de7b9f4466e47164da54a037826dc Mon Sep 17 00:00:00 2001 From: Yoan Mollard Date: Sat, 25 Jun 2022 00:11:40 +0200 Subject: [PATCH 100/826] Use class instance instead of SQL req --- htdocs/compta/accounting-files.php | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/htdocs/compta/accounting-files.php b/htdocs/compta/accounting-files.php index e754af8c60e..24d0c191d33 100644 --- a/htdocs/compta/accounting-files.php +++ b/htdocs/compta/accounting-files.php @@ -474,14 +474,10 @@ if ($result && $action == "dl" && !$error) { $log .= ','.$langs->transnoentitiesnoconv("Sens")."\n"; $zipname = $dirfortmpfile.'/'.dol_print_date($date_start, 'dayrfc', 'tzuserrel')."-".dol_print_date($date_stop, 'dayrfc', 'tzuserrel'); if (!empty($projectid)) { - $sql = 'SELECT t.ref FROM '.MAIN_DB_PREFIX.'projet as t'; - $sql .= ' WHERE t.rowid = '.((int) $db->sanitize($projectid)); - $resql = $db->query($sql); - if ($resql) { - $obj = $db->fetch_object($resql); - $zipname .= '_'.$obj->ref; - } else { - dol_print_error($db); + $project = new Project($db); + $project->fetch($projectid); + if ($project->ref) { + $zipname .= '_'.$project->ref; } } $zipname .='_export.zip'; From acddc2a332bc57736dd1538e99194c1f3f6b9f90 Mon Sep 17 00:00:00 2001 From: Faustin Date: Sat, 25 Jun 2022 18:51:19 +0200 Subject: [PATCH 101/826] NEW #20650 completing checkcolumn on left for project list --- htdocs/projet/list.php | 55 +++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/htdocs/projet/list.php b/htdocs/projet/list.php index eaf9c5022a3..a24ee1fce65 100644 --- a/htdocs/projet/list.php +++ b/htdocs/projet/list.php @@ -854,7 +854,7 @@ if (!empty($moreforfilter)) { } $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; -$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields +$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')); // This also change content of $arrayfields $selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : ''); @@ -864,6 +864,13 @@ print '
'; + $searchpicto = $form->showFilterButtons('left'); + print $searchpicto; + print ''; @@ -849,13 +856,18 @@ if (!empty($arrayfields['e.billed']['checked'])) { print ''; -$searchpicto = $form->showFilterAndCheckAddButtons(0); -print $searchpicto; -print ''; + $searchpicto = $form->showFilterAndCheckAddButtons(0); + print $searchpicto; + print '
'; + if ($massactionbutton || $massaction) { + // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($obj->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print ''; @@ -1085,16 +1112,18 @@ while ($i < min($num, $limit)) { } // Action column - print ''; - if ($massactionbutton || $massaction) { - // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined - $selected = 0; - if (in_array($obj->rowid, $arrayofselected)) { - $selected = 1; + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + if ($massactionbutton || $massaction) { + // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($obj->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; } - print ''; + print '
'; +// Action column +if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; +} // Project ref if (!empty($arrayfields['p.ref']['checked'])) { print ''; } // Action column -print ''; - +if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; +} print ''."\n"; print ''; +if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); +} if (!empty($arrayfields['p.ref']['checked'])) { print_liste_field_titre($arrayfields['p.ref']['label'], $_SERVER["PHP_SELF"], "p.ref", "", $param, "", $sortfield, $sortorder); } @@ -1122,7 +1133,9 @@ if (!empty($arrayfields['p.email_msgid']['checked'])) { if (!empty($arrayfields['p.fk_statut']['checked'])) { print_liste_field_titre($arrayfields['p.fk_statut']['label'], $_SERVER["PHP_SELF"], "p.fk_statut", "", $param, '', $sortfield, $sortorder, 'right '); } -print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); +if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); +} print "\n"; $i = 0; @@ -1160,6 +1173,18 @@ while ($i < min($num, $limit)) { print ''; + // Action column + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } // Project url if (!empty($arrayfields['p.ref']['checked'])) { print ''; } - print ''; if (!$i) { $totalarray['nbfield']++; } From c387f1d57a167422d7d60dfa789043fe7a6504a5 Mon Sep 17 00:00:00 2001 From: Faustin Date: Sat, 25 Jun 2022 19:01:52 +0200 Subject: [PATCH 102/826] NEW #20650 completing checkcolumn on left for task list --- htdocs/projet/tasks/list.php | 54 +++++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 13 deletions(-) diff --git a/htdocs/projet/tasks/list.php b/htdocs/projet/tasks/list.php index bfda3ad31be..25b9452518f 100644 --- a/htdocs/projet/tasks/list.php +++ b/htdocs/projet/tasks/list.php @@ -274,7 +274,7 @@ if ($search_task_user > 0) { $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; -$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields +$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')); // This also change content of $arrayfields $title = $langs->trans("Activities"); @@ -708,6 +708,13 @@ print '
'; + $searchpicto = $form->showFilterButtons('left'); + print $searchpicto; + print ''; @@ -1033,14 +1040,18 @@ if (!empty($arrayfields['p.fk_statut']['checked'])) { print ''; -$searchpicto = $form->showFilterButtons(); -print $searchpicto; -print ''; + $searchpicto = $form->showFilterButtons(); + print $searchpicto; + print '
'; + if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($obj->id, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print ''; @@ -1512,15 +1537,17 @@ while ($i < min($num, $limit)) { } } // Action column - print ''; - if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined - $selected = 0; - if (in_array($obj->id, $arrayofselected)) { - $selected = 1; + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($obj->id, $arrayofselected)) { + $selected = 1; + } + print ''; } - print ''; + print '
'; +// Action column +if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; +} if (!empty($arrayfields['t.fk_task_parent']['checked'])) { print ''; } // Action column -print ''; +if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; +} print ''."\n"; $totalarray = array( @@ -854,6 +863,9 @@ $totalarray = array( // Fields title label // -------------------------------------------------------------------- print ''; +if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); +} if (!empty($arrayfields['t.fk_task_parent']['checked'])) { print_liste_field_titre($arrayfields['t.fk_task_parent']['label'], $_SERVER["PHP_SELF"], "t.fk_task_parent", "", $param, "", $sortfield, $sortorder); $totalarray['nbfield']++; @@ -946,7 +958,9 @@ if (!empty($arrayfields['t.tms']['checked'])) { print_liste_field_titre($arrayfields['t.tms']['label'], $_SERVER["PHP_SELF"], "t.tms", "", $param, '', $sortfield, $sortorder, 'center nowrap '); $totalarray['nbfield']++; } -print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); +if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); +} $totalarray['nbfield']++; print ''."\n"; @@ -1008,6 +1022,18 @@ while ($i < $imaxinloop) { if ($userAccess >= 0) { print ''; + // Action column + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } // Ref Parent if (!empty($arrayfields['t.fk_task_parent']['checked'])) { print ''; }*/ // Action column - print ''; } - print ''; if (!$i) { $totalarray['nbfield']++; } From 3d00c065aec07bfc437100160263e52aeef75aef Mon Sep 17 00:00:00 2001 From: Yoan Mollard Date: Sun, 26 Jun 2022 23:51:10 +0200 Subject: [PATCH 103/826] Missing label for excluded members --- .../interface_50_modAgenda_ActionsAuto.class.php | 12 ++++++++++++ htdocs/langs/en_US/agenda.lang | 1 + 2 files changed, 13 insertions(+) diff --git a/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php b/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php index 0e018514353..4e926050f24 100644 --- a/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php +++ b/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php @@ -798,6 +798,18 @@ class InterfaceActionsAuto extends DolibarrTriggers $object->actionmsg .= "\n".$langs->transnoentities("Member").': '.$object->getFullName($langs); $object->actionmsg .= "\n".$langs->transnoentities("Type").': '.$object->type; + $object->sendtoid = 0; + } elseif ($action == 'MEMBER_EXCLUDE') { + // Load translation files required by the page + $langs->loadLangs(array("agenda", "other", "members")); + + if (empty($object->actionmsg2)) { + $object->actionmsg2 = $langs->transnoentities("MemberExcludedInDolibarr", $object->getFullName($langs)); + } + $object->actionmsg = $langs->transnoentities("MemberExcludedInDolibarr", $object->getFullName($langs)); + $object->actionmsg .= "\n".$langs->transnoentities("Member").': '.$object->getFullName($langs); + $object->actionmsg .= "\n".$langs->transnoentities("Type").': '.$object->type; + $object->sendtoid = 0; } elseif ($action == 'PROJECT_CREATE') { // Projects diff --git a/htdocs/langs/en_US/agenda.lang b/htdocs/langs/en_US/agenda.lang index 272ec22df5c..b8f9ffa857b 100644 --- a/htdocs/langs/en_US/agenda.lang +++ b/htdocs/langs/en_US/agenda.lang @@ -57,6 +57,7 @@ MemberValidatedInDolibarr=Member %s validated MemberModifiedInDolibarr=Member %s modified MemberResiliatedInDolibarr=Member %s terminated MemberDeletedInDolibarr=Member %s deleted +MemberExcludedInDolibarr=Member %s excluded MemberSubscriptionAddedInDolibarr=Subscription %s for member %s added MemberSubscriptionModifiedInDolibarr=Subscription %s for member %s modified MemberSubscriptionDeletedInDolibarr=Subscription %s for member %s deleted From 6053f3e5f8228ebb557c90bfa05c0f95bdf30977 Mon Sep 17 00:00:00 2001 From: Yoan Mollard Date: Mon, 27 Jun 2022 00:27:00 +0200 Subject: [PATCH 104/826] Internationalize invoice lines for new memberships --- htdocs/langs/en_US/paypal.lang | 1 + htdocs/public/payment/paymentok.php | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/htdocs/langs/en_US/paypal.lang b/htdocs/langs/en_US/paypal.lang index beaf9a5ea3f..a935cd38434 100644 --- a/htdocs/langs/en_US/paypal.lang +++ b/htdocs/langs/en_US/paypal.lang @@ -34,3 +34,4 @@ ARollbackWasPerformedOnPostActions=A rollback was performed on all Post actions. ValidationOfPaymentFailed=Validation of payment has failed CardOwner=Card holder PayPalBalance=Paypal credit +OnlineSubscriptionPaymentLine=Online subscription recorded on %s
Paid via %s
Originating IP address: %s
Transaction ID: %s diff --git a/htdocs/public/payment/paymentok.php b/htdocs/public/payment/paymentok.php index c0b88736ce3..992e7ab403d 100644 --- a/htdocs/public/payment/paymentok.php +++ b/htdocs/public/payment/paymentok.php @@ -504,9 +504,13 @@ if ($ispaymentok) { $datesubend = dol_time_plus_duree($datesubend, -1, 'd'); } + // Set output language + $outputlangs = new Translate('', $conf); + $outputlangs->setDefaultLang(empty($object->thirdparty->default_lang) ? $mysoc->default_lang : $object->thirdparty->default_lang); $paymentdate = $now; $amount = $FinalPaymentAmt; - $label = 'Online subscription '.dol_print_date($now, 'standard').' using '.$paymentmethod.' from '.$ipaddress.' - Transaction ID = '.$TRANSACTIONID; + $formatteddate = dol_print_date($paymentdate, 'dayhour', 'auto', $outputlangs); + $label = $langs->trans("OnlineSubscriptionPaymentLine", $formatteddate, $paymentmethod, $ipaddress, $TRANSACTIONID); // Payment informations $accountid = 0; @@ -693,9 +697,6 @@ if ($ispaymentok) { // Send subscription email include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php'; $formmail = new FormMail($db); - // Set output language - $outputlangs = new Translate('', $conf); - $outputlangs->setDefaultLang(empty($object->thirdparty->default_lang) ? $mysoc->default_lang : $object->thirdparty->default_lang); // Load traductions files required by page $outputlangs->loadLangs(array("main", "members")); // Get email content from template From 10aa31a376fada47228daf78021b3c3d43a00d30 Mon Sep 17 00:00:00 2001 From: Yoan Mollard Date: Mon, 27 Jun 2022 00:31:59 +0200 Subject: [PATCH 105/826] Let users know that the PDF invoice is enclosed --- htdocs/langs/en_US/members.lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/langs/en_US/members.lang b/htdocs/langs/en_US/members.lang index 22060706a36..fafa1a60400 100644 --- a/htdocs/langs/en_US/members.lang +++ b/htdocs/langs/en_US/members.lang @@ -135,7 +135,7 @@ CardContent=Content of your member card # Text of email templates ThisIsContentOfYourMembershipRequestWasReceived=We want to let you know that your membership request was received.

ThisIsContentOfYourMembershipWasValidated=We want to let you know that your membership was validated with the following information:

-ThisIsContentOfYourSubscriptionWasRecorded=We want to let you know that your new subscription was recorded.

+ThisIsContentOfYourSubscriptionWasRecorded=We want to let you know that your new subscription was recorded. Please find your invoice here enclosed.

ThisIsContentOfSubscriptionReminderEmail=We want to let you know that your subscription is about to expire or has already expired (__MEMBER_LAST_SUBSCRIPTION_DATE_END__). We hope you will renew it.

ThisIsContentOfYourCard=This is a summary of the information we have about you. Please contact us if anything is incorrect.

DescADHERENT_AUTOREGISTER_NOTIF_MAIL_SUBJECT=Subject of the notification email received in case of auto-inscription of a guest From d7d02fee9a9eaf7b41c494041d18724cc6119114 Mon Sep 17 00:00:00 2001 From: Faustin Date: Mon, 27 Jun 2022 16:08:06 +0200 Subject: [PATCH 106/826] NEW #21395 : Added option for dark theme mode in display - color and theme --- htdocs/admin/ihm.php | 10 ++++++++++ htdocs/core/lib/usergroups.lib.php | 21 +++++++++++++++++++++ htdocs/langs/en_US/admin.lang | 9 +++++++-- htdocs/langs/fr_FR/admin.lang | 20 ++++++++++++-------- 4 files changed, 50 insertions(+), 10 deletions(-) diff --git a/htdocs/admin/ihm.php b/htdocs/admin/ihm.php index 959d881041d..5ad497205ab 100644 --- a/htdocs/admin/ihm.php +++ b/htdocs/admin/ihm.php @@ -104,6 +104,16 @@ if ($action == 'update') { dolibarr_set_const($db, "MAIN_THEME", GETPOST("main_theme", 'aZ09'), 'chaine', 0, '', $conf->entity); dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity); + if (GETPOSTISSET('THEME_DARKMODEENABLED')) { + $val = GETPOST('THEME_DARKMODEENABLED'); + if (!$val) { + dolibarr_del_const($db, "THEME_DARKMODEENABLED", $conf->entity); + } + if ($val) { + dolibarr_set_const($db, "THEME_DARKMODEENABLED", $val, 'chaine', 0, '', $conf->entity); + } + } + if (GETPOSTISSET('THEME_TOPMENU_DISABLE_IMAGE')) { $val=GETPOST('THEME_TOPMENU_DISABLE_IMAGE'); if (!$val) { diff --git a/htdocs/core/lib/usergroups.lib.php b/htdocs/core/lib/usergroups.lib.php index 538fc299564..eed9043afa6 100644 --- a/htdocs/core/lib/usergroups.lib.php +++ b/htdocs/core/lib/usergroups.lib.php @@ -455,6 +455,27 @@ function showSkins($fuser, $edit = 0, $foruserprofile = false) include DOL_DOCUMENT_ROOT.'/theme/'.$conf->theme.'/theme_vars.inc.php'; } + //Dark mode + if ($foruserprofile) { + //Nothing + } else { + $listofdarkmodes = array( + '0' => $langs->trans("AlwaysDisabled"), + '1' => $langs->trans("AccordingToBrowser"), + '2' => $langs->trans("AlwaysEnabled") + ); + print '
'; + print ''; + print ''; + } + + // TopMenuDisableImages if ($foruserprofile) { /* diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 95ed076f347..4c3d8c32799 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -897,7 +897,7 @@ Permission701=Read donations Permission702=Create/modify donations Permission703=Delete donations Permission771=Read expense reports (yours and your subordinates) -Permission772=Create/modify expense reports (for you and your subordinates) +Permission772=Create/modify expense reports (for you and your subordinates) Permission773=Delete expense reports Permission775=Approve expense reports Permission776=Pay expense reports @@ -2169,7 +2169,7 @@ EMailsWillHaveMessageID=Emails will have a tag 'References' matching this syntax PDF_SHOW_PROJECT=Show project on document ShowProjectLabel=Project Label PDF_INCLUDE_ALIAS_IN_THIRDPARTY_NAME=Include alias in thirdparty name -THIRDPARTY_ALIAS=Name thirdparty - Alias thirdparty +THIRDPARTY_ALIAS=Name thirdparty - Alias thirdparty ALIAS_THIRDPARTY=Alias thirdparty - Name thirdparty PDF_USE_ALSO_LANGUAGE_CODE=If you want to have some texts in your PDF duplicated in 2 different languages in the same generated PDF, you must set here this second language so generated PDF will contains 2 different languages in same page, the one chosen when generating PDF and this one (only few PDF templates support this). Keep empty for 1 language per PDF. PDF_USE_A=Gererate PDF documents with format PDF/A instead of defaut format PDF @@ -2277,3 +2277,8 @@ INVOICE_ADD_ZATCA_QR_CODEMore=Some Arabic countries need this QR Code on their i INVOICE_ADD_SWISS_QR_CODE=Show the swiss QR-Bill code on invoices UrlSocialNetworksDesc=Url link of social network. Use {socialid} for the variable part that contains the social network ID. IfThisCategoryIsChildOfAnother=If this category is a child of another one + +DarkThemeMode=Dark theme mode +AlwaysDisabled=Always disabled +AccordingToBrowser=According to browser +AlwaysEnabled=Always Enabled \ No newline at end of file diff --git a/htdocs/langs/fr_FR/admin.lang b/htdocs/langs/fr_FR/admin.lang index 7ac18213e1e..68aa93b7b5d 100644 --- a/htdocs/langs/fr_FR/admin.lang +++ b/htdocs/langs/fr_FR/admin.lang @@ -190,7 +190,7 @@ Compression=Compression CommandsToDisableForeignKeysForImport=Commande pour désactiver les clés étrangères à l'importation CommandsToDisableForeignKeysForImportWarning=Requis si vous voulez être en mesure de restaurer votre « dump » SQL plus tard ExportCompatibility=Compatibilité du fichier d'exportation généré -ExportUseMySQLQuickParameter=Utiliser le paramètre --quick +ExportUseMySQLQuickParameter=Utiliser le paramètre --quick ExportUseMySQLQuickParameterHelp=Le paramètre '--quick' aide à réduire la consommation de RAM pour les longues listes MySqlExportParameters=Paramètres de l'exportation MySQL PostgreSqlExportParameters= Paramètres de l'exportation PostgreSQL @@ -338,7 +338,7 @@ MenuHandlers=Gestionnaires de menu MenuAdmin=Édition menu DoNotUseInProduction=Ne pas utiliser en production ThisIsProcessToFollow=Procédure de mise à jour: -ThisIsAlternativeProcessToFollow=Voici une procédure de configuration alternative +ThisIsAlternativeProcessToFollow=Voici une procédure de configuration alternative StepNb=Étape %s FindPackageFromWebSite=Rechercher le paquet qui répond à votre besoin (par exemple sur le site web %s). DownloadPackageFromWebSite=Télécharger le package (par exemple depuis le site web officiel %s) @@ -1377,7 +1377,7 @@ NumberingModules=Modèles de numérotation DocumentModules=Modèles de documents ##### Module password generation PasswordGenerationStandard=Renvoie un mot de passe généré selon l'algorythme interne de Dolibarr :%s caractères contenant chiffres et minuscules -PasswordGenerationNone=Ne pas suggérer un mot de passe généré. Le mot de passe doit être entré manuellement. +PasswordGenerationNone=Ne pas suggérer un mot de passe généré. Le mot de passe doit être entré manuellement. PasswordGenerationPerso=Renvoie un mot de passe en fonction d'une configuration personnalisée. SetupPerso=Selon votre configuration PasswordPatternDesc=Description du masque du mot de passe @@ -1455,7 +1455,7 @@ OrdersNumberingModules=Modèles de numérotation des commandes OrdersModelModule=Modèles de document des commandes FreeLegalTextOnOrders=Mention complémentaire sur les commandes WatermarkOnDraftOrders=Filigrane sur les brouillons de commandes (aucun si vide) -ShippableOrderIconInList=Ajouter une icône dans la liste des commandes qui indique si la commande est expédiable. +ShippableOrderIconInList=Ajouter une icône dans la liste des commandes qui indique si la commande est expédiable. BANK_ASK_PAYMENT_BANK_DURING_ORDER=Demander le compte bancaire cible durant la commande ##### Interventions ##### InterventionsSetup=Configuration du module Interventions @@ -1645,7 +1645,7 @@ TestNotPossibleWithCurrentBrowsers=Une détection automatique n'est pas possible DefaultValuesDesc=Vous pouvez définir/forcer ici la valeur par défaut que vous voulez obtenir lorsque vous créez un nouvel enregistrement, et/ou les filtres par défaut ou ordre de tri des listes. DefaultCreateForm=Valeurs par défaut (sur les formulaires de création) DefaultSearchFilters=Filtres de recherche par défaut -DefaultSortOrder=Ordre de tri par défaut +DefaultSortOrder=Ordre de tri par défaut DefaultFocus=Champs par défaut ayant le focus DefaultMandatory=Champs de formulaire obligatoires ##### Products ##### @@ -1864,7 +1864,7 @@ ChequeReceiptsNumberingModule=Module de numérotation des bordereaux de remises MultiCompanySetup=Configuration du module Multi-société ##### Suppliers ##### SuppliersSetup=Configuration du module Fournisseurs -SuppliersCommandModel=Modèle de commande fournisseur complet +SuppliersCommandModel=Modèle de commande fournisseur complet SuppliersCommandModelMuscadet=Modèle de commande fournisseur complet (ancienne implémentation du modèle Cornas) SuppliersInvoiceModel=Modèle de facture fournisseur complet SuppliersInvoiceNumberingModel=Modèles de numérotation des factures fournisseur @@ -1899,7 +1899,7 @@ NbMajMin=Nombre minimal de caractères majuscules NbNumMin=Nombre minimal de caractères numériques NbSpeMin=Nombre minimal de caractères spéciaux NbIteConsecutive=Nombre maximal de répétition des mêmes caractères -NoAmbiCaracAutoGeneration=Ne pas utiliser des caractères ambigus ("1","l","i","|","0","O") pour la génération automatique +NoAmbiCaracAutoGeneration=Ne pas utiliser des caractères ambigus ("1","l","i","|","0","O") pour la génération automatique SalariesSetup=Configuration du module salaires SortOrder=Ordre de tri Format=Format @@ -1920,7 +1920,7 @@ GoOntoContactCardToAddMore=Rendez-vous sur l'onglet "Notifications" d'un tiers p Threshold=Seuil BackupDumpWizard=Assistant pour créer le fichier dump de la base de données BackupZipWizard=Assistant pour générer l'archive du répertoire documents -SomethingMakeInstallFromWebNotPossible=L'installation de module externe est impossible depuis l'interface web pour la raison suivante : +SomethingMakeInstallFromWebNotPossible=L'installation de module externe est impossible depuis l'interface web pour la raison suivante : SomethingMakeInstallFromWebNotPossible2=Pour cette raison, le processus de mise à jour décrit ici est une processus manuel que seul un utilisateur ayant des droits privilégiés peut réaliser. InstallModuleFromWebHasBeenDisabledByFile=L'installation de module externe depuis l'application a été désactivé par l'administrator. Vous devez lui demander de supprimer le fichier %s pour permettre cette fonctionnalité. ConfFileMustContainCustom=Installer ou créer un module externe à partir de l'application nécessite de sauvegarder les fichiers du module dans le répertoire %s. Pour que ce répertoire soit reconnu par Dolibarr, vous devez paramétrer le fichier de configuration conf/conf.php en ajoutant les 2 lignes suivantes :
$dolibarr_main_url_root_alt='/custom'
$dolibarr_main_document_root_alt='%s/custom'; @@ -2263,3 +2263,7 @@ IconOnly=Icon only - Text on tooltip only INVOICE_ADD_ZATCA_QR_CODE=Show the ZATCA QR code on invoices INVOICE_ADD_ZATCA_QR_CODEMore=Some Arabic countries need this QR Code on their invoices UrlSocialNetworksDesc=Url link of social network. Use {socialid} for the variable part that contains the social network ID. +DarkThemeMode=Mode thème sombre +AlwaysDisabled=Toujours désactivé +AccordingToBrowser=Selon le navigateur +AlwaysEnabled=Toujours activé \ No newline at end of file From 3e66ca1636dd80c64a79d2d033b3866ae88bf18a Mon Sep 17 00:00:00 2001 From: Faustin Date: Mon, 27 Jun 2022 16:18:54 +0200 Subject: [PATCH 107/826] NEW #21395 : Added picto text to inform that option does not work with all themes --- htdocs/core/lib/usergroups.lib.php | 1 + htdocs/langs/en_US/admin.lang | 3 ++- htdocs/langs/fr_FR/admin.lang | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/htdocs/core/lib/usergroups.lib.php b/htdocs/core/lib/usergroups.lib.php index eed9043afa6..4aa2942884d 100644 --- a/htdocs/core/lib/usergroups.lib.php +++ b/htdocs/core/lib/usergroups.lib.php @@ -472,6 +472,7 @@ function showSkins($fuser, $edit = 0, $foruserprofile = false) } else { print $listofdarkmodes[isset($conf->global->THEME_DARKMODEENABLED) ? $conf->global->THEME_DARKMODEENABLED : 0]; } + print $form->textwithpicto('', $langs->trans("DoesNotWorkWithAllThemes")); print ''; } diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 4c3d8c32799..bec98616b11 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -2281,4 +2281,5 @@ IfThisCategoryIsChildOfAnother=If this category is a child of another one DarkThemeMode=Dark theme mode AlwaysDisabled=Always disabled AccordingToBrowser=According to browser -AlwaysEnabled=Always Enabled \ No newline at end of file +AlwaysEnabled=Always Enabled +DoesNotWorkWithAllThemes=Will not work with all themes \ No newline at end of file diff --git a/htdocs/langs/fr_FR/admin.lang b/htdocs/langs/fr_FR/admin.lang index 68aa93b7b5d..3c653717801 100644 --- a/htdocs/langs/fr_FR/admin.lang +++ b/htdocs/langs/fr_FR/admin.lang @@ -2266,4 +2266,5 @@ UrlSocialNetworksDesc=Url link of social network. Use {socialid} for the variabl DarkThemeMode=Mode thème sombre AlwaysDisabled=Toujours désactivé AccordingToBrowser=Selon le navigateur -AlwaysEnabled=Toujours activé \ No newline at end of file +AlwaysEnabled=Toujours activé +DoesNotWorkWithAllThemes=Ne fonctionne pas avec tous les thèmes \ No newline at end of file From 0fca79529a782cacdd47387131d527e98aaf60d8 Mon Sep 17 00:00:00 2001 From: Yoan Mollard Date: Tue, 28 Jun 2022 01:51:14 +0200 Subject: [PATCH 108/826] Missing lib import --- htdocs/public/members/new.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/public/members/new.php b/htdocs/public/members/new.php index 31f1fa9f952..654fce78ccc 100644 --- a/htdocs/public/members/new.php +++ b/htdocs/public/members/new.php @@ -64,6 +64,7 @@ if (is_numeric($entity)) { require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php'; require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php'; require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent_type.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; From 5998999f18741ec3a7c9f439231054e59ef0aa8c Mon Sep 17 00:00:00 2001 From: Yoan Mollard Date: Tue, 28 Jun 2022 02:33:17 +0200 Subject: [PATCH 109/826] NEW: Add free membership amounts at the membership type level --- .../adherents/class/adherent_type.class.php | 10 +++++- htdocs/adherents/type.php | 10 +++++- htdocs/core/lib/payments.lib.php | 4 ++- .../install/mysql/migration/15.0.0-16.0.0.sql | 3 +- htdocs/langs/en_US/members.lang | 3 ++ htdocs/langs/fr_FR/members.lang | 3 ++ htdocs/public/members/new.php | 31 ++++++++++++++----- 7 files changed, 52 insertions(+), 12 deletions(-) diff --git a/htdocs/adherents/class/adherent_type.class.php b/htdocs/adherents/class/adherent_type.class.php index 3f857ce827b..38641c8664b 100644 --- a/htdocs/adherents/class/adherent_type.class.php +++ b/htdocs/adherents/class/adherent_type.class.php @@ -94,6 +94,11 @@ class AdherentType extends CommonObject */ public $amount; + /** + * @var int Amount can be choosen by the visitor during subscription (0 or 1) + */ + public $caneditamount; + /** * @var string Public note * @deprecated @@ -380,6 +385,7 @@ class AdherentType extends CommonObject $sql .= "morphy = '".$this->db->escape($this->morphy)."',"; $sql .= "subscription = '".$this->db->escape($this->subscription)."',"; $sql .= "amount = ".((empty($this->amount) && $this->amount == '') ? 'null' : ((float) $this->amount)).","; + $sql .= "caneditamount = '".$this->db->escape($this->caneditamount)."',"; $sql .= "duration = '".$this->db->escape($this->duration_value.$this->duration_unit)."',"; $sql .= "note = '".$this->db->escape($this->note_public)."',"; $sql .= "vote = ".(integer) $this->db->escape($this->vote).","; @@ -474,7 +480,7 @@ class AdherentType extends CommonObject { global $langs, $conf; - $sql = "SELECT d.rowid, d.libelle as label, d.morphy, d.statut as status, d.duration, d.subscription, d.amount, d.mail_valid, d.note as note_public, d.vote"; + $sql = "SELECT d.rowid, d.libelle as label, d.morphy, d.statut as status, d.duration, d.subscription, d.amount, d.caneditamount, d.mail_valid, d.note as note_public, d.vote"; $sql .= " FROM ".MAIN_DB_PREFIX."adherent_type as d"; $sql .= " WHERE d.rowid = ".(int) $rowid; @@ -495,6 +501,7 @@ class AdherentType extends CommonObject $this->duration_unit = substr($obj->duration, -1); $this->subscription = $obj->subscription; $this->amount = $obj->amount; + $this->caneditamount = $obj->caneditamount; $this->mail_valid = $obj->mail_valid; $this->note = $obj->note_public; // deprecated $this->note_public = $obj->note_public; @@ -850,6 +857,7 @@ class AdherentType extends CommonObject $this->note_public = 'This is a public note'; $this->mail_valid = 'This is welcome email'; $this->subscription = 1; + $this->caneditamount = 0; $this->vote = 0; $this->status = 1; diff --git a/htdocs/adherents/type.php b/htdocs/adherents/type.php index bcd6c99afbf..0b54132b5d0 100644 --- a/htdocs/adherents/type.php +++ b/htdocs/adherents/type.php @@ -122,6 +122,7 @@ if ($action == 'add' && $user->rights->adherent->configurer) { $object->status = (int) $status; $object->subscription = (int) $subscription; $object->amount = ($amount == '' ? '' : price2num($amount, 'MT')); + $object->caneditamount = (int) GETPOST("caneditamount", 'int'); $object->duration_value = $duration_value; $object->duration_unit = $duration_unit; $object->note = trim($comment); @@ -229,7 +230,7 @@ llxHeader('', $langs->trans("MembersTypeSetup"), $help_url); if (!$rowid && $action != 'create' && $action != 'edit') { //print dol_get_fiche_head(''); - $sql = "SELECT d.rowid, d.libelle as label, d.subscription, d.amount, d.vote, d.statut as status, d.morphy"; + $sql = "SELECT d.rowid, d.libelle as label, d.subscription, d.amount, d.caneditamount, d.vote, d.statut as status, d.morphy"; $sql .= " FROM ".MAIN_DB_PREFIX."adherent_type as d"; $sql .= " WHERE d.entity IN (".getEntity('member_type').")"; @@ -276,6 +277,7 @@ if (!$rowid && $action != 'create' && $action != 'edit') { print ''; print ''; print ''; + print ''; print ''; print ''; print ''; @@ -292,6 +294,7 @@ if (!$rowid && $action != 'create' && $action != 'edit') { $membertype->status = $objp->status; $membertype->subscription = $objp->subscription; $membertype->amount = $objp->amount; + $membertype->caneditamount = $objp->caneditamount; print ''; print ''; print ''; print ''; + print ''; print ''; print ''; if ($user->rights->adherent->configurer) { @@ -380,6 +384,10 @@ if ($action == 'create') { print ''; print ''; + print ''; + print ''; diff --git a/htdocs/core/lib/payments.lib.php b/htdocs/core/lib/payments.lib.php index 2911564adef..c006c4b9c9f 100644 --- a/htdocs/core/lib/payments.lib.php +++ b/htdocs/core/lib/payments.lib.php @@ -318,7 +318,9 @@ function getOnlinePaymentUrl($mode, $type, $ref = '', $amount = '9.99', $freetag } } elseif ($type == 'member' || $type == 'membersubscription') { $newtype = 'member'; - $out = $urltouse.'/public/payment/newpayment.php?source=member&ref='.($mode ? '' : ''); + $out = $urltouse.'/public/payment/newpayment.php?source=member'; + $out .= '&amount='.$amount; + $out .= '&ref='.($mode ? '' : ''); if ($mode == 1) { $out .= 'member_ref'; } diff --git a/htdocs/install/mysql/migration/15.0.0-16.0.0.sql b/htdocs/install/mysql/migration/15.0.0-16.0.0.sql index b57cab5b4eb..c465151f9c2 100644 --- a/htdocs/install/mysql/migration/15.0.0-16.0.0.sql +++ b/htdocs/install/mysql/migration/15.0.0-16.0.0.sql @@ -648,4 +648,5 @@ ALTER TABLE llx_paiement MODIFY COLUMN ext_payment_id varchar(255); ALTER TABLE llx_payment_donation MODIFY COLUMN ext_payment_id varchar(255); ALTER TABLE llx_prelevement_facture_demande MODIFY COLUMN ext_payment_id varchar(255); - +-- Allow users to make subscriptions of any amount during membership subscription +ALTER TABLE llx_adherent_type ADD COLUMN caneditamount varchar(3) DEFAULT 0 AFTER amount; diff --git a/htdocs/langs/en_US/members.lang b/htdocs/langs/en_US/members.lang index fafa1a60400..e552755f705 100644 --- a/htdocs/langs/en_US/members.lang +++ b/htdocs/langs/en_US/members.lang @@ -71,6 +71,9 @@ MemberTypeCanNotBeDeleted=Member type can not be deleted NewSubscription=New contribution NewSubscriptionDesc=This form allows you to record your subscription as a new member of the foundation. If you want to renew your subscription (if already a member), please contact foundation board instead by email %s. Subscription=Contribution +AnyAmountWithAdvisedAmount=Any amount with a recommended amount of %s %s +AnyAmountWithoutAdvisedAmount=Any amount +CanEditAmountShort=Any amount Subscriptions=Contributions SubscriptionLate=Late SubscriptionNotReceived=Contribution never received diff --git a/htdocs/langs/fr_FR/members.lang b/htdocs/langs/fr_FR/members.lang index a6f805daca6..5f67cc681ab 100644 --- a/htdocs/langs/fr_FR/members.lang +++ b/htdocs/langs/fr_FR/members.lang @@ -199,6 +199,9 @@ AmountOfSubscriptions=Montant des cotisations TurnoverOrBudget=Chiffre affaire (pour société) ou Budget (asso ou collectivité) DefaultAmount=Montant par défaut de la cotisation CanEditAmount=Le visiteur peut modifier / choisir le montant de sa cotisation +AnyAmountWithAdvisedAmount=Montant libre avec un montant recommandé de %s %s +AnyAmountWithoutAdvisedAmount=Montant libre +CanEditAmountShort=Montant libre MEMBER_NEWFORM_PAYONLINE=Rediriger sur la page intégrée de paiement en ligne ByProperties=Par nature MembersStatisticsByProperties=Statistiques des adhérents par nature diff --git a/htdocs/public/members/new.php b/htdocs/public/members/new.php index 654fce78ccc..f6957502284 100644 --- a/htdocs/public/members/new.php +++ b/htdocs/public/members/new.php @@ -692,16 +692,31 @@ if (!empty($conf->global->MEMBER_NEWFORM_PAYONLINE)) { // Clean the amount $amount = price2num($amount); - + $adht = new AdherentType($db); + $adht->fetch($typeid); + $caneditamount = $adht->caneditamount; + $showedamount = $amount>0? $amount: 0; // $conf->global->MEMBER_NEWFORM_PAYONLINE is 'paypal', 'paybox' or 'stripe' - print ''; } From 1ea8d47c844b6f422709ec84e7d978243560ee0e Mon Sep 17 00:00:00 2001 From: lvessiller Date: Tue, 28 Jun 2022 10:42:13 +0200 Subject: [PATCH 110/826] NEW join only the main document --- htdocs/core/tpl/card_presend.tpl.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/htdocs/core/tpl/card_presend.tpl.php b/htdocs/core/tpl/card_presend.tpl.php index 9a99faef526..9e0a38bee39 100644 --- a/htdocs/core/tpl/card_presend.tpl.php +++ b/htdocs/core/tpl/card_presend.tpl.php @@ -49,8 +49,6 @@ if ($action == 'presend') { // Special case if ($object->element == 'invoice_supplier') { $fileparams = dol_most_recent_file($diroutput.'/'.get_exdir($object->id, 2, 0, 0, $object, $object->element).$ref, preg_quote($ref, '/').'([^\-])+'); - } elseif ($object->element == 'societe') { - $fileparams = dol_most_recent_file($diroutput.'/'.$ref); } else { $fileparams = dol_most_recent_file($diroutput.'/'.$ref, preg_quote($ref, '/').'[^\-]+'); } @@ -102,8 +100,6 @@ if ($action == 'presend') { } if ($object->element == 'invoice_supplier') { $fileparams = dol_most_recent_file($diroutput.'/'.get_exdir($object->id, 2, 0, 0, $object, $object->element).$ref, preg_quote($ref, '/').'([^\-])+'); - } elseif ($object->element == 'societe') { - $fileparams = dol_most_recent_file($diroutput.'/'.$ref); } else { $fileparams = dol_most_recent_file($diroutput.'/'.$ref, preg_quote($ref, '/').'[^\-]+'); } From 2981b268aedca56124a633115eeeca89b0509058 Mon Sep 17 00:00:00 2001 From: Christian Foellmann Date: Tue, 28 Jun 2022 13:28:31 +0200 Subject: [PATCH 111/826] add hook "changeHelpURL" to modify target of the help button --- htdocs/main.inc.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 1d09b9f9887..03bc6bfa504 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -1309,7 +1309,7 @@ if (!function_exists("llxHeader")) { */ function llxHeader($head = '', $title = '', $help_url = '', $target = '', $disablejs = 0, $disablehead = 0, $arrayofjs = '', $arrayofcss = '', $morequerystring = '', $morecssonbody = '', $replacemainareaby = '', $disablenofollow = 0) { - global $conf; + global $conf, $hookmanager; // html header top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss, 0, $disablenofollow); @@ -1329,6 +1329,12 @@ if (!function_exists("llxHeader")) { print ''."\n"; + $parameters = array('help_url' => $help_url); + $reshook = $hookmanager->executeHooks('changeHelpURL', $parameters); + if ($reshook > 0) { + $help_url = $hookmanager->resPrint; + } + // top menu and left menu area if (empty($conf->dol_hide_topmenu) || GETPOST('dol_invisible_topmenu', 'int')) { top_menu($head, $title, $target, $disablejs, $disablehead, $arrayofjs, $arrayofcss, $morequerystring, $help_url); From 3c4183f7838efef3142d83f6dd98c6f4ff404aa0 Mon Sep 17 00:00:00 2001 From: Quatadah Nasdami Date: Tue, 28 Jun 2022 15:51:38 +0200 Subject: [PATCH 112/826] success --- htdocs/core/lib/website.lib.php | 35 +++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/htdocs/core/lib/website.lib.php b/htdocs/core/lib/website.lib.php index d9602379977..18bd7226400 100644 --- a/htdocs/core/lib/website.lib.php +++ b/htdocs/core/lib/website.lib.php @@ -221,6 +221,41 @@ function dolWebsiteReplacementOfLinks($website, $content, $removephppart = 0, $c */ function dolReplaceSmileyCodeWithUTF8($content) { + $map = array( + ":face_with_tears_of_joy:" => "\xF0\x9F\x98\x82", + ":grinning_face_with_smiling_eyes:" => "\xF0\x9F\x98\x81", + ":smiling_face_with_open_mouth:" => "\xF0\x9F\x98\x83", + ":smiling_face_with_open_mouth_and_cold_sweat:" => "\xF0\x9F\x98\x85", + ":smiling_face_with_open_mouth_and_tightly_closed_eyes:" => "\xF0\x9F\x98\x86", + ":winking_face:" => "\xF0\x9F\x98\x89", + ":smiling_face_with_smiling_eyes:" => "\xF0\x9F\x98\x8A", + ":face_savouring_delicious_food:" => "\xF0\x9F\x98\x8B", + ":relieved_face:" => "\xF0\x9F\x98\x8C", + ":smiling_face_with_heart_shaped_eyes:" => "\xF0\x9F\x98\x8D", + ":smiling_face_with_sunglasses:" => "\xF0\x9F\x98\x8E", + ":smirking_face:" => "\xF0\x9F\x98\x8F", + ":neutral_face:" => "\xF0\x9F\x98\x90", + ":expressionless_face:" => "\xF0\x9F\x98\x91", + ":unamused_face:" => "\xF0\x9F\x98\x92", + ":face_with_cold_sweat:" => "\xF0\x9F\x98\x93", + ":pensive_face:" => "\xF0\x9F\x98\x94", + ":confused_face:" => "\xF0\x9F\x98\x95", + ":confounded_face:" => "\xF0\x9F\x98\x96", + ":kissing_face:" => "\xF0\x9F\x98\x97", + ":face_throwing_a_kiss:" => "\xF0\x9F\x98\x98", + ":kissing_face_with_smiling_eyes:" => "\xF0\x9F\x98\x99", + ":kissing_face_with_closed_eyes:" => "\xF0\x9F\x98\x9A", + ":face_with_stuck_out_tongue:" => "\xF0\x9F\x98\x9B", + ":face_with_stuck_out_tongue_and_winking_eye:" => "\xF0\x9F\x98\x9C", + ":face_with_stuck_out_tongue_and_tightly_closed_eyes:" => "\xF0\x9F\x98\x9D", + ":disappointed_face:" => "\xF0\x9F\x98\x9E", + ":worried_face:" => "\xF0\x9F\x98\x9F", + ":angry_face:" => "\xF0\x9F\x98\xA0", + ":face_with_symbols_on_mouth:" => "\xF0\x9F\x98\xA1", + ); + foreach ($map as $key => $value) { + $content = str_replace($key, $value, $content); + } return $content; } From 811b11cab255c4bd45b73a53766ab66d800a8d03 Mon Sep 17 00:00:00 2001 From: Faustin Date: Tue, 28 Jun 2022 16:33:00 +0200 Subject: [PATCH 113/826] NEW #21397 : added option to auto define barcode numbers for third-parties in barcode module setup --- htdocs/admin/barcode.php | 81 +++- .../mod_barcode_thirdparty_standard.php | 354 ++++++++++++++++++ 2 files changed, 434 insertions(+), 1 deletion(-) create mode 100644 htdocs/core/modules/barcode/mod_barcode_thirdparty_standard.php diff --git a/htdocs/admin/barcode.php b/htdocs/admin/barcode.php index ee0fcd5d130..d03d227470a 100644 --- a/htdocs/admin/barcode.php +++ b/htdocs/admin/barcode.php @@ -55,6 +55,16 @@ if ($action == 'setbarcodeproducton') { $res = dolibarr_del_const($db, "BARCODE_PRODUCT_ADDON_NUM", $conf->entity); } +if ($action == 'setbarcodethirdpartyon') { + $barcodenumberingmodule = GETPOST('value', 'alpha'); + $res = dolibarr_set_const($db, "BARCODE_THIRDPARTY_ADDON_NUM", $barcodenumberingmodule, 'chaine', 0, '', $conf->entity); + if ($barcodenumberingmodule == 'mod_barcode_thirdparty_standard' && empty($conf->global->BARCODE_STANDARD_THIRDPARTY_MASK)) { + $res = dolibarr_set_const($db, "BARCODE_STANDARD_THIRDPARTY_MASK", '020{000000000}', 'chaine', 0, '', $conf->entity); + } +} elseif ($action == 'setbarcodethirdpartyoff') { + $res = dolibarr_del_const($db, "BARCODE_THIRDPARTY_ADDON_NUM", $conf->entity); +} + if ($action == 'setcoder') { $coder = GETPOST('coder', 'alpha'); $code_id = GETPOST('code_id', 'int'); @@ -241,6 +251,66 @@ if ($conf->product->enabled) { print ''; } +// Select barcode numbering module +if ($conf->societe->enabled) { + print load_fiche_titre($langs->trans("BarCodeNumberManager")." (".$langs->trans("ThirdParty").")", '', ''); + + print '
'; + print '
'; + $searchpicto = $form->showFilterButtons('left'); + print $searchpicto; + print ''; print ''; @@ -826,10 +833,12 @@ if (!empty($arrayfields['t.tms']['checked'])) { print ''; -$searchpicto = $form->showFilterButtons(); -print $searchpicto; -print ''; + $searchpicto = $form->showFilterButtons(); + print $searchpicto; + print '
'; + if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($object->id, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print ''; @@ -1318,15 +1344,17 @@ while ($i < $imaxinloop) { print ''.$projectstatic->getLibStatut(5).''; - if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined - $selected = 0; - if (in_array($object->id, $arrayofselected)) { - $selected = 1; + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($object->id, $arrayofselected)) { + $selected = 1; + } + print ''; } - print ''; + print '
'.$langs->trans("DarkThemeMode").''; + if ($edit) { + print $form->selectarray('THEME_DARKMODEENABLED', $listofdarkmodes, isset($conf->global->THEME_DARKMODEENABLED) ? $conf->global->THEME_DARKMODEENABLED : 0); + } else { + print $listofdarkmodes[isset($conf->global->THEME_DARKMODEENABLED) ? $conf->global->THEME_DARKMODEENABLED : 0]; + } + print '
'.$langs->trans("MembersNature").''.$langs->trans("SubscriptionRequired").''.$langs->trans("Amount").''.$langs->trans("CanEditAmountShort").''.$langs->trans("VoteAllowed").''.$langs->trans("Status").' 
'; @@ -310,6 +313,7 @@ if (!$rowid && $action != 'create' && $action != 'edit') { print ''.yn($objp->subscription).''.(is_null($objp->amount) || $objp->amount === '' ? '' : price($objp->amount)).''.yn($objp->caneditamount).''.yn($objp->vote).''.$membertype->getLibStatut(5).'
'.$langs->trans("CanEditAmountShort").''; + print $form->selectyesno("caneditamount", 0, 1); + print '
'.$langs->trans("VoteAllowed").''; print $form->selectyesno("vote", GETPOSTISSET("vote") ? GETPOST('vote', 'aZ09') : 1, 1); print '
'.$langs->trans("Subscription").''; - if (!empty($conf->global->MEMBER_NEWFORM_EDITAMOUNT)) { - print ''; - } else { - print ''; - print ''; + print '
'.$langs->trans("Subscription"); + if (!empty($conf->global->MEMBER_EXT_URL_SUBSCRIPTION_INFO)) { + print ' - '.$langs->trans("SeeHere").''; + } + print ''; + + if (empty($amount) && !empty($conf->global->MEMBER_NEWFORM_AMOUNT)) { + $amount = $conf->global->MEMBER_NEWFORM_AMOUNT; + } + + if (!empty($conf->global->MEMBER_NEWFORM_EDITAMOUNT) || $caneditamount) { + print ''; + print ' '.$langs->trans("Currency".$conf->currency).' – '; + print $amount>0? $langs->trans("AnyAmountWithAdvisedAmount", $amount, $langs->trans("Currency".$conf->currency)): $langs->trans("AnyAmountWithoutAdvisedAmount"); + print ''; + } else { + print ''; + print ''; + print ' '.$langs->trans("Currency".$conf->currency); } - print ' '.$langs->trans("Currency".$conf->currency); print '
'; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print "\n"; + + $dirbarcodenum = array_merge(array('/core/modules/barcode/'), $conf->modules_parts['barcode']); + + foreach ($dirbarcodenum as $dirroot) { + $dir = dol_buildpath($dirroot, 0); + + $handle = @opendir($dir); + if (is_resource($handle)) { + while (($file = readdir($handle)) !== false) { + if (preg_match('/^mod_barcode_thirdparty_.*php$/', $file)) { + $file = substr($file, 0, dol_strlen($file) - 4); + + try { + dol_include_once($dirroot.$file.'.php'); + } catch (Exception $e) { + dol_syslog($e->getMessage(), LOG_ERR); + } + + $modBarCode = new $file(); + print ''; + print ''; + print '\n"; + + if (!empty($conf->global->BARCODE_THIRDPARTY_ADDON_NUM) && $conf->global->BARCODE_THIRDPARTY_ADDON_NUM == "$file") { + print ''; + } else { + print ''; + } + print ''; + print "\n"; + } + } + closedir($handle); + } + } + print "
'.$langs->trans("Name").''.$langs->trans("Description").''.$langs->trans("Example").''.$langs->trans("Status").''.$langs->trans("ShortInfo").'
'.(isset($modBarCode->name) ? $modBarCode->name : $modBarCode->nom)."\n"; + print $modBarCode->info($langs); + print ''.$modBarCode->getExample($langs)."'; + print img_picto($langs->trans("Activated"), 'switch_on'); + print ''; + print img_picto($langs->trans("Disabled"), 'switch_off'); + print ''; + $s = $modBarCode->getToolTip($langs, null, -1); + print $form->textwithpicto('', $s, 1); + print '
\n"; + print '
'; +} /* * CHOIX ENCODAGE @@ -251,7 +321,16 @@ print load_fiche_titre($langs->trans("BarcodeEncodeModule"), '', ''); if (empty($conf->use_javascript_ajax)) { print ''; - print ''; + print '';if ($module->encodingIsSupported($obj->encoding)) { + // Build barcode on disk (not used, this is done to make debug easier) + $result = $module->writeBarCode($obj->example, $obj->encoding, 'Y'); + // Generate on the fly and output barcode with generator + $url = DOL_URL_ROOT.'/viewimage.php?modulepart=barcode&generator='.urlencode($obj->coder).'&code='.urlencode($obj->example).'&encoding='.urlencode($obj->encoding); + //print $url; + print ''; + } else { + print $langs->trans("FormatNotSupportedByGenerator"); + } print ''; } diff --git a/htdocs/core/modules/barcode/mod_barcode_thirdparty_standard.php b/htdocs/core/modules/barcode/mod_barcode_thirdparty_standard.php new file mode 100644 index 00000000000..42f8d9c3b50 --- /dev/null +++ b/htdocs/core/modules/barcode/mod_barcode_thirdparty_standard.php @@ -0,0 +1,354 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * or see https://www.gnu.org/ + */ + +/** + * \file htdocs/core/modules/barcode/mod_barcode_thirdparty_standard.php + * \ingroup barcode + * \brief File of class to manage barcode numbering with standard rule + */ + +require_once DOL_DOCUMENT_ROOT.'/core/modules/barcode/modules_barcode.class.php'; + + +/** + * Class to manage barcode with standard rule + */ +class mod_barcode_thirdparty_standard extends ModeleNumRefBarCode +{ + public $name = 'Standard'; // Model Name + + public $code_modifiable; // Editable code + + public $code_modifiable_invalide; // Modified code if it is invalid + + public $code_modifiable_null; // Modified code if it is null + + public $code_null; // Optional code + + /** + * Dolibarr version of the loaded document + * @var string + */ + public $version = 'dolibarr'; // 'development', 'experimental', 'dolibarr' + + /** + * @var int Automatic numbering + */ + public $code_auto; + + public $searchcode; // Search string + + public $numbitcounter; // Number of digits the counter + + public $prefixIsRequired; // The prefix field of third party must be filled when using {pre} + + + /** + * Constructor + */ + public function __construct() + { + $this->code_null = 0; + $this->code_modifiable = 1; + $this->code_modifiable_invalide = 1; + $this->code_modifiable_null = 1; + $this->code_auto = 1; + $this->prefixIsRequired = 0; + } + + + /** Return description of module + * + * @param Translate $langs Object langs + * @return string Description of module + */ + public function info($langs) + { + global $conf, $mc; + global $form; + + $langs->load("thirdparties"); + + $disabled = ((!empty($mc->sharings['referent']) && $mc->sharings['referent'] != $conf->entity) ? ' disabled' : ''); + + $texte = $langs->trans('GenericNumRefModelDesc')."
\n"; + $texte .= ''; + $texte .= ''; + $texte .= ''; + $texte .= ''; + $texte .= ''; + $texte .= ''; + + $tooltip = $langs->trans("GenericMaskCodes", $langs->transnoentities("BarCode"), $langs->transnoentities("BarCode")); + $tooltip .= $langs->trans("GenericMaskCodes3EAN"); + $tooltip .= ''.$langs->trans("Example").':
'; + $tooltip .= '020{000000000}? (for internal use)
'; + $tooltip .= '9771234{00000}? (example of ISSN code with prefix 1234)
'; + $tooltip .= '9791234{00000}? (example of ISMN code with prefix 1234)
'; + //$tooltip.=$langs->trans("GenericMaskCodes5"); + + // Mask parameter + //$texte.= ''; + $texte .= ''; + $texte .= ''; + $texte .= ''; + $texte .= ''; + + $texte .= '
'.$langs->trans("Mask").' ('.$langs->trans("BarCodeModel").'):
'.$langs->trans("Mask").':'.$form->textwithpicto('', $tooltip, 1, 1).' 
'; + $texte .= ''; + + return $texte; + } + + + /** + * Return an example of result returned by getNextValue + * + * @param Translate $langs Object langs + * @param Societe $objthirdparty Object third-party + * @return string Return string example + */ + public function getExample($langs, $objthirdparty = 0) + { + $examplebarcode = $this->getNextValue($objthirdparty, ''); + if (!$examplebarcode) { + $examplebarcode = $langs->trans('NotConfigured'); + } + if ($examplebarcode == "ErrorBadMask") { + $langs->load("errors"); + $examplebarcode = $langs->trans($examplebarcode); + } + + return $examplebarcode; + } + /** + * Return literal barcode type code from numerical rowid type of barcode + * + * @param Database $db Database + * @param int $type Type of barcode (EAN, ISBN, ...) as rowid + * @return string + */ + public function literalBarcodeType($db, $type = '') + { + global $conf; + $out = ''; + + $sql = "SELECT rowid, code, libelle as label"; + $sql .= " FROM ".MAIN_DB_PREFIX."c_barcode_type"; + $sql .= " WHERE rowid = '".$db->escape($type)."'"; + $sql .= " AND entity = ".((int) $conf->entity); + $result = $db->query($sql); + if ($result) { + $num = $db->num_rows($result); + + if ($num > 0) { + $obj = $db->fetch_object($result); + $out .= $obj->label; //take the label corresponding to the type rowid in the database + } + } else { + dol_print_error($db); + } + + return $out; + } + /** + * Return next value + * + * @param Societe $objthirdparty Object third-party + * @param string $type Type of barcode (EAN, ISBN, ...) + * @return string Value if OK, '' if module not configured, <0 if KO + */ + public function getNextValue($objthirdparty, $type = '') + { + global $db, $conf; + + require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; + require_once DOL_DOCUMENT_ROOT.'/core/lib/barcode.lib.php'; // to be able to call function barcode_gen_ean_sum($ean) + + if (empty($type)) { + $type = $conf->global->GENBARCODE_BARCODETYPE_THIRDPARTY; + } //get barcode type configuration for companies if $type not set + + // TODO + + // Get Mask value + $mask = ''; + if (!empty($conf->global->BARCODE_STANDARD_THIRDPARTY_MASK)) { + $mask = $conf->global->BARCODE_STANDARD_THIRDPARTY_MASK; + } + + if (empty($mask)) { + $this->error = 'NotConfigured'; + return ''; + } + + $field = 'barcode'; + $where = ''; + + $now = dol_now(); + + $numFinal = get_next_value($db, $mask, 'societe', $field, $where, '', $now); + //Begin barcode with key: for barcode with key (EAN13...) calculate and substitute the last character (* or ?) used in the mask by the key + if ((substr($numFinal, -1)=='*') or (substr($numFinal, -1)=='?')) { // if last mask character is * or ? a joker, probably we have to calculate a key as last character (EAN13...) + $literaltype = ''; + $literaltype = $this->literalBarcodeType($db, $type);//get literal_Barcode_Type + switch ($literaltype) { + case 'EAN13': //EAN13 rowid = 2 + if (strlen($numFinal)==13) {// be sure that the mask length is correct for EAN13 + $ean = substr($numFinal, 0, 12); //take first 12 digits + $eansum = barcode_gen_ean_sum($ean); + $ean .= $eansum; //substitute the las character by the key + $numFinal = $ean; + } + break; + // Other barcode cases with key could be written here + default: + break; + } + } + //End barcode with key + return $numFinal; + } + + + /** + * Check validity of code according to its rules + * + * @param DoliDB $db Database handler + * @param string $code Code to check/correct + * @param Societe $thirdparty Object third-party + * @param int $thirdparty_type 0 = customer/prospect , 1 = supplier + * @param string $type type of barcode (EAN, ISBN, ...) + * @return int 0 if OK + * -1 ErrorBadCustomerCodeSyntax + * -2 ErrorCustomerCodeRequired + * -3 ErrorCustomerCodeAlreadyUsed + * -4 ErrorPrefixRequired + */ + public function verif($db, &$code, $thirdparty, $thirdparty_type, $type) + { + global $conf; + + //var_dump($code.' '.$thirdparty->ref.' '.$thirdparty_type);exit; + + require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; + + $result = 0; + $code = strtoupper(trim($code)); + + if (empty($code) && $this->code_null && empty($conf->global->BARCODE_STANDARD_THIRDPARTY_MASK)) { + $result = 0; + } elseif (empty($code) && (!$this->code_null || !empty($conf->global->BARCODE_STANDARD_THIRDPARTY_MASK))) { + $result = -2; + } else { + if ($this->verif_syntax($code, $type) >= 0) { + $is_dispo = $this->verif_dispo($db, $code, $thirdparty); + if ($is_dispo <> 0) { + $result = -3; + } else { + $result = 0; + } + } else { + if (dol_strlen($code) == 0) { + $result = -2; + } else { + $result = -1; + } + } + } + + dol_syslog(get_class($this)."::verif type=".$thirdparty_type." result=".$result); + return $result; + } + + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Return if a code is used (by other element) + * + * @param DoliDB $db Handler acces base + * @param string $code Code to check + * @param Societe $thirdparty Objet third-party + * @return int 0 if available, <0 if KO + */ + public function verif_dispo($db, $code, $thirdparty) + { + // phpcs:enable + $sql = "SELECT barcode FROM ".MAIN_DB_PREFIX."societe"; + $sql .= " WHERE barcode = '".$db->escape($code)."'"; + if ($thirdparty->id > 0) { + $sql .= " AND rowid <> ".$thirdparty->id; + } + + $resql = $db->query($sql); + if ($resql) { + if ($db->num_rows($resql) == 0) { + return 0; + } else { + return -1; + } + } else { + return -2; + } + } + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Return if a barcode value match syntax + * + * @param string $codefortest Code to check syntax + * @param string $typefortest Type of barcode (ISBN, EAN, ...) + * @return int 0 if OK, <0 if KO + */ + public function verif_syntax($codefortest, $typefortest) + { + // phpcs:enable + global $conf; + + $result = 0; + + // Get Mask value + $mask = empty($conf->global->BARCODE_STANDARD_THIRDPARTY_MASK) ? '' : $conf->global->BARCODE_STANDARD_THIRDPARTY_MASK; + if (!$mask) { + $this->error = 'NotConfigured'; + return -1; + } + + dol_syslog(get_class($this).'::verif_syntax codefortest='.$codefortest." typefortest=".$typefortest); + + $newcodefortest = $codefortest; + + // Special case, if mask is on 12 digits instead of 13, we remove last char into code to test + if (in_array($typefortest, array('EAN13', 'ISBN'))) { // We remove the CRC char not included into mask + if (preg_match('/\{(0+)([@\+][0-9]+)?([@\+][0-9]+)?\}/i', $mask, $reg)) { + if (strlen($reg[1]) == 12) { + $newcodefortest = substr($newcodefortest, 0, 12); + } + dol_syslog(get_class($this).'::verif_syntax newcodefortest='.$newcodefortest); + } + } + + $result = check_value($mask, $newcodefortest); + if (is_string($result)) { + $this->error = $result; + return -1; + } + + return $result; + } +} From 3f7fe8d68894d371939be286b15cb00e69e79012 Mon Sep 17 00:00:00 2001 From: Faustin Date: Tue, 28 Jun 2022 16:39:34 +0200 Subject: [PATCH 114/826] NEW #21397 : small fix --- htdocs/admin/barcode.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/admin/barcode.php b/htdocs/admin/barcode.php index d03d227470a..ce394f24d76 100644 --- a/htdocs/admin/barcode.php +++ b/htdocs/admin/barcode.php @@ -321,7 +321,8 @@ print load_fiche_titre($langs->trans("BarcodeEncodeModule"), '', ''); if (empty($conf->use_javascript_ajax)) { print '
'; - print '';if ($module->encodingIsSupported($obj->encoding)) { + print ''; + if ($module->encodingIsSupported($obj->encoding)) { // Build barcode on disk (not used, this is done to make debug easier) $result = $module->writeBarCode($obj->example, $obj->encoding, 'Y'); // Generate on the fly and output barcode with generator From 23cbb5212d1eed8e8fe067a8f0e6829a9304354c Mon Sep 17 00:00:00 2001 From: Faustin Date: Tue, 28 Jun 2022 16:40:59 +0200 Subject: [PATCH 115/826] NEW #21397 : code intrusion --- htdocs/admin/barcode.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/htdocs/admin/barcode.php b/htdocs/admin/barcode.php index ce394f24d76..57c32d79318 100644 --- a/htdocs/admin/barcode.php +++ b/htdocs/admin/barcode.php @@ -322,16 +322,6 @@ print load_fiche_titre($langs->trans("BarcodeEncodeModule"), '', ''); if (empty($conf->use_javascript_ajax)) { print ''; print ''; - if ($module->encodingIsSupported($obj->encoding)) { - // Build barcode on disk (not used, this is done to make debug easier) - $result = $module->writeBarCode($obj->example, $obj->encoding, 'Y'); - // Generate on the fly and output barcode with generator - $url = DOL_URL_ROOT.'/viewimage.php?modulepart=barcode&generator='.urlencode($obj->coder).'&code='.urlencode($obj->example).'&encoding='.urlencode($obj->encoding); - //print $url; - print ''; - } else { - print $langs->trans("FormatNotSupportedByGenerator"); - } print ''; } From bc66c37a083b6b185d834078329a25b5443a78b5 Mon Sep 17 00:00:00 2001 From: Faustin Date: Tue, 28 Jun 2022 18:52:20 +0200 Subject: [PATCH 116/826] hook fix --- htdocs/barcode/codeinit.php | 177 +++++++++++++++--- .../mod_barcode_thirdparty_standard.php | 6 +- 2 files changed, 159 insertions(+), 24 deletions(-) diff --git a/htdocs/barcode/codeinit.php b/htdocs/barcode/codeinit.php index b4e365fe018..65ca10a8794 100644 --- a/htdocs/barcode/codeinit.php +++ b/htdocs/barcode/codeinit.php @@ -35,7 +35,8 @@ $month = dol_print_date($now, '%m'); $day = dol_print_date($now, '%d'); $forbarcode = GETPOST('forbarcode'); $fk_barcode_type = GETPOST('fk_barcode_type'); -$eraseallbarcode = GETPOST('eraseallbarcode'); +$eraseallproductbarcode = GETPOST('eraseallproductbarcode'); +$eraseallthirdpartybarcode = GETPOST('eraseallthirdpartybarcode'); $action = GETPOST('action', 'aZ09'); @@ -43,6 +44,7 @@ $producttmp = new Product($db); $thirdpartytmp = new Societe($db); $modBarCodeProduct = ''; +$modBarCodeThirdparty = ''; $maxperinit = 1000; @@ -51,6 +53,106 @@ $maxperinit = 1000; * Actions */ +// Define barcode template for third-party +if (!empty($conf->global->BARCODE_THIRDPARTY_ADDON_NUM)) { + $dirbarcodenum = array_merge(array('/core/modules/barcode/'), $conf->modules_parts['barcode']); + + foreach ($dirbarcodenum as $dirroot) { + $dir = dol_buildpath($dirroot, 0); + + $handle = @opendir($dir); + if (is_resource($handle)) { + while (($file = readdir($handle)) !== false) { + if (preg_match('/^mod_barcode_thirdparty_.*php$/', $file)) { + $file = substr($file, 0, dol_strlen($file) - 4); + + try { + dol_include_once($dirroot.$file.'.php'); + } catch (Exception $e) { + dol_syslog($e->getMessage(), LOG_ERR); + } + + $modBarCodeThirdparty = new $file(); + break; + } + } + closedir($handle); + } + } +} + +if ($action == 'initbarcodethirdparties') { + if (!is_object($modBarCodeThirdparty)) { + $error++; + setEventMessages($langs->trans("NoBarcodeNumberingTemplateDefined"), null, 'errors'); + } + + if (!$error) { + $thirdpartystatic = new Societe($db); + + $db->begin(); + + $nbok = 0; + if (!empty($eraseallthirdpartybarcode)) { + $sql = "UPDATE ".MAIN_DB_PREFIX."societe"; + $sql .= " SET barcode = NULL"; + $resql = $db->query($sql); + if ($resql) { + setEventMessages($langs->trans("AllBarcodeReset"), null, 'mesgs'); + } else { + $error++; + dol_print_error($db); + } + } else { + $sql = "SELECT rowid"; + $sql .= " FROM ".MAIN_DB_PREFIX."societe"; + $sql .= " WHERE barcode IS NULL or barcode = ''"; + $sql .= $db->order("datec", "ASC"); + $sql .= $db->plimit($maxperinit); + + dol_syslog("codeinit", LOG_DEBUG); + $resql = $db->query($sql); + if ($resql) { + $num = $db->num_rows($resql); + + $i = 0; $nbok = $nbtry = 0; + while ($i < min($num, $maxperinit)) { + $obj = $db->fetch_object($resql); + if ($obj) { + $thirdpartystatic->id = $obj->rowid; + $nextvalue = $modBarCodeThirdparty->getNextValue($thirdpartystatic, ''); + + $result = $thirdpartystatic->setValueFrom('barcode', $nextvalue, '', '', 'text', '', $user, 'THIRDPARTY_MODIFY'); + + $nbtry++; + if ($result > 0) { + $nbok++; + } + } + + $i++; + } + } else { + $error++; + dol_print_error($db); + } + + if (!$error) { + setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs'); + } + } + + if (!$error) { + //$db->rollback(); + $db->commit(); + } else { + $db->rollback(); + } + } + + $action = ''; +} + // Define barcode template for products if (!empty($conf->global->BARCODE_PRODUCT_ADDON_NUM)) { $dirbarcodenum = array_merge(array('/core/modules/barcode/'), $conf->modules_parts['barcode']); @@ -91,7 +193,7 @@ if ($action == 'initbarcodeproducts') { $db->begin(); $nbok = 0; - if (!empty($eraseallbarcode)) { + if (!empty($eraseallproductbarcode)) { $sql = "UPDATE ".MAIN_DB_PREFIX."product"; $sql .= " SET barcode = NULL"; $resql = $db->query($sql); @@ -155,7 +257,6 @@ if ($action == 'initbarcodeproducts') { } - /* * View */ @@ -189,7 +290,11 @@ print '
'; // For thirdparty if (isModEnabled('societe')) { - $nbno = $nbtotal = 0; + print ''; + print ''; + print ''; + print ''; + $nbthirdpartyno = $nbthirdpartytotal = 0; print load_fiche_titre($langs->trans("BarcodeInitForThirdparties"), '', 'company'); @@ -198,7 +303,7 @@ if (isModEnabled('societe')) { $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); - $nbno = $obj->nb; + $nbthirdpartyno = $obj->nb; } else { dol_print_error($db); } @@ -207,22 +312,46 @@ if (isModEnabled('societe')) { $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); - $nbtotal = $obj->nb; + $nbthirdpartytotal = $obj->nb; } else { dol_print_error($db); } - print $langs->trans("CurrentlyNWithoutBarCode", $nbno, $nbtotal, $langs->transnoentitiesnoconv("ThirdParties")).'
'."\n"; + print $langs->trans("CurrentlyNWithoutBarCode", $nbthirdpartyno, $nbthirdpartytotal, $langs->transnoentitiesnoconv("ThirdParties")).'
'."\n"; - print '
'; + $disabledthirdparty = $disabledthirdparty1 = 0; + + if (is_object($modBarCodeThirdparty)) { + print $langs->trans("BarCodeNumberManager").": "; + $objthirdparty = new Societe($db); + print ''.(isset($modBarCodeThirdparty->name) ? $modBarCodeThirdparty->name : $modBarCodeThirdparty->nom).' - '.$langs->trans("NextValue").': '.$modBarCodeThirdparty->getNextValue($objthirdparty).'
'; + $disabledthirdparty = 0; + } else { + $disabledthirdparty = 1; + $titleno = $langs->trans("NoBarcodeNumberingTemplateDefined"); + print ''.$langs->trans("NoBarcodeNumberingTemplateDefined").' ('.$langs->trans("ToGenerateCodeDefineAutomaticRuleFirst").')
'; + } + if (empty($nbthirdpartyno)) { + $disabledthirdparty1 = 1; + } + + $moretagsthirdparty1 = (($disabledthirdparty || $disabledthirdparty1) ? ' disabled title="'.dol_escape_htmltag($titleno).'"' : ''); + print '
'; + $moretagsthirdparty2 = (($nbthirdpartyno == $nbthirdpartytotal) ? ' disabled' : ''); + print '   '; + print ''; print '



'; + print ''; } // For products if ($conf->product->enabled || $conf->product->service) { + print '
'; + print ''; + print ''; + print ''; + // Example 1 : Adding jquery code print ''; - $nbno = $nbtotal = 0; + $nbproductno = $nbproducttotal = 0; print load_fiche_titre($langs->trans("BarcodeInitForProductsOrServices"), '', 'product'); print '
'."\n"; @@ -247,7 +376,7 @@ if ($conf->product->enabled || $conf->product->service) { $i = 0; while ($i < $num) { $obj = $db->fetch_object($resql); - $nbno += $obj->nb; + $nbproductno += $obj->nb; $i++; } @@ -259,35 +388,38 @@ if ($conf->product->enabled || $conf->product->service) { $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); - $nbtotal = $obj->nb; + $nbproducttotal = $obj->nb; } else { dol_print_error($db); } - print $langs->trans("CurrentlyNWithoutBarCode", $nbno, $nbtotal, $langs->transnoentitiesnoconv("ProductsOrServices")).'
'."\n"; + print $langs->trans("CurrentlyNWithoutBarCode", $nbproductno, $nbproducttotal, $langs->transnoentitiesnoconv("ProductsOrServices")).'
'."\n"; + + $disabledproduct = $disabledproduct1 = 0; if (is_object($modBarCodeProduct)) { print $langs->trans("BarCodeNumberManager").": "; $objproduct = new Product($db); print ''.(isset($modBarCodeProduct->name) ? $modBarCodeProduct->name : $modBarCodeProduct->nom).' - '.$langs->trans("NextValue").': '.$modBarCodeProduct->getNextValue($objproduct).'
'; - $disabled = 0; + $disabledproduct = 0; } else { - $disabled = 1; + $disabledproduct = 1; $titleno = $langs->trans("NoBarcodeNumberingTemplateDefined"); print ''.$langs->trans("NoBarcodeNumberingTemplateDefined").' ('.$langs->trans("ToGenerateCodeDefineAutomaticRuleFirst").')
'; } - if (empty($nbno)) { - $disabled1 = 1; + if (empty($nbproductno)) { + $disabledproduct1 = 1; } print '
'; //print ' '.$langs->trans("ResetBarcodeForAllRecords").'
'; - $moretags1 = (($disabled || $disabled1) ? ' disabled title="'.dol_escape_htmltag($titleno).'"' : ''); - print ''; - $moretags2 = (($nbno == $nbtotal) ? ' disabled' : ''); + $moretagsproduct1 = (($disabledproduct || $disabledproduct1) ? ' disabled title="'.dol_escape_htmltag($titleno).'"' : ''); + print ''; + $moretagsproduct2 = (($nbproductno == $nbproducttotal) ? ' disabled' : ''); print '   '; - print ''; + print ''; print '



'; + print '
'; } @@ -297,7 +429,6 @@ print $langs->trans("ClickHereToGoTo").' : '; //print '
'; -print '
'; -print ''; -print ''; -print ''; - print '
'; + + +// Example 1 : Adding jquery code +print ''; + + // For thirdparty if (isModEnabled('societe')) { print ''; @@ -352,13 +357,6 @@ if ($conf->product->enabled || $conf->product->service) { print ''; print ''; - // Example 1 : Adding jquery code - print ''; - $nbproductno = $nbproducttotal = 0; print load_fiche_titre($langs->trans("BarcodeInitForProductsOrServices"), '', 'product'); From ea0c710104d7b6cc7f0d31d30c14d939234989e6 Mon Sep 17 00:00:00 2001 From: Yoan Mollard Date: Wed, 29 Jun 2022 00:23:27 +0200 Subject: [PATCH 118/826] dopayment string fix --- htdocs/public/payment/newpayment.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index b61a2e22a06..ff53ccf0e09 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -1596,7 +1596,7 @@ if ($source == 'member' || $source == 'membersubscription') { print ''; print $form->selectarray("typeid", $adht->liste_array(1), $member->typeid, 0, 0, 0, 'onchange="window.location.replace(\''.$urlwithroot.'/public/payment/newpayment.php?source='.urlencode($source).'&ref='.urlencode($ref).'&amount='.urlencode($amount).'&typeid=\' + this.value + \'&securekey='.urlencode($SECUREKEY).'\');"', 0, 0, 0, '', '', 1); print "\n"; - } elseif ($action == dopayment) { + } elseif ($action == 'dopayment') { print ''.$langs->trans("NewMemberType"); print ''.dol_escape_htmltag($member->type); print ''; From 759900bccee95b31e7684b2d69d93370d0e176ed Mon Sep 17 00:00:00 2001 From: Yoan Mollard Date: Wed, 29 Jun 2022 00:27:18 +0200 Subject: [PATCH 119/826] No longer allow to edit amount in the payment step If amount is editable, edition has been done in the previous screen in public/members/new.php It also allows the possibility to prevent the visitor from doing a >0 payment if this is not wanted. --- htdocs/langs/en_US/members.lang | 1 + htdocs/langs/fr_FR/members.lang | 1 + htdocs/public/payment/newpayment.php | 61 ++++++---------------------- 3 files changed, 15 insertions(+), 48 deletions(-) diff --git a/htdocs/langs/en_US/members.lang b/htdocs/langs/en_US/members.lang index e552755f705..d9af9c9c350 100644 --- a/htdocs/langs/en_US/members.lang +++ b/htdocs/langs/en_US/members.lang @@ -202,6 +202,7 @@ AmountOfSubscriptions=Amount collected from contributions TurnoverOrBudget=Turnover (for a company) or Budget (for a foundation) DefaultAmount=Default amount of contribution CanEditAmount=Visitor can choose/edit amount of its contribution +AmountIsLowerToMinimumNotice=sur un dû total de %s MEMBER_NEWFORM_PAYONLINE=Jump on integrated online payment page ByProperties=By nature MembersStatisticsByProperties=Members statistics by nature diff --git a/htdocs/langs/fr_FR/members.lang b/htdocs/langs/fr_FR/members.lang index 5f67cc681ab..9cf2f25a2b0 100644 --- a/htdocs/langs/fr_FR/members.lang +++ b/htdocs/langs/fr_FR/members.lang @@ -199,6 +199,7 @@ AmountOfSubscriptions=Montant des cotisations TurnoverOrBudget=Chiffre affaire (pour société) ou Budget (asso ou collectivité) DefaultAmount=Montant par défaut de la cotisation CanEditAmount=Le visiteur peut modifier / choisir le montant de sa cotisation +AmountIsLowerToMinimumNotice=sur un dû total de %s AnyAmountWithAdvisedAmount=Montant libre avec un montant recommandé de %s %s AnyAmountWithoutAdvisedAmount=Montant libre CanEditAmountShort=Montant libre diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index ff53ccf0e09..1c3c0202b23 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -1500,7 +1500,7 @@ if ($source == 'member' || $source == 'membersubscription') { $amount = $adht->amount; } - $amount = price2num($amount, 'MT'); + $amount = max(0, price2num($amount, 'MT')); } if (GETPOST('fulltag', 'alpha')) { @@ -1611,57 +1611,22 @@ if ($source == 'member' || $source == 'membersubscription') { // Amount print ''.$langs->trans("Amount"); - if (empty($amount)) { - if (empty($conf->global->MEMBER_NEWFORM_AMOUNT)) { - print ' ('.$langs->trans("ToComplete"); - } - if (!empty($conf->global->MEMBER_EXT_URL_SUBSCRIPTION_INFO)) { - print ' -
'.$langs->trans("SeeHere").''; - } - if (empty($conf->global->MEMBER_NEWFORM_AMOUNT)) { - print ')'; - } + // This place no longer allows amount edition + if (!empty($conf->global->MEMBER_EXT_URL_SUBSCRIPTION_INFO)) { + print ' - '.$langs->trans("SeeHere").''; } print ''; - $valtoshow = ''; - if (empty($amount) || !is_numeric($amount)) { - $valtoshow = price2num(GETPOST("newamount", 'alpha'), 'MT'); - // force default subscription amount to value defined into constant... - if (empty($valtoshow)) { - if (!empty($conf->global->MEMBER_NEWFORM_EDITAMOUNT)) { - if (!empty($conf->global->MEMBER_NEWFORM_AMOUNT)) { - $valtoshow = $conf->global->MEMBER_NEWFORM_AMOUNT; - } - } else { - if (!empty($conf->global->MEMBER_NEWFORM_AMOUNT)) { - $amount = $conf->global->MEMBER_NEWFORM_AMOUNT; - } - } - } + if (!empty($conf->global->MEMBER_MIN_AMOUNT) && $amount) { + $amount = max(0, $conf->global->MEMBER_MIN_AMOUNT, $amount); } - if (empty($amount) || !is_numeric($amount)) { - //$valtoshow=price2num(GETPOST("newamount",'alpha'),'MT'); - if (!empty($conf->global->MEMBER_MIN_AMOUNT) && $valtoshow) { - $valtoshow = max($conf->global->MEMBER_MIN_AMOUNT, $valtoshow); - } - print ''; - if (empty($conf->global->MEMBER_NEWFORM_EDITAMOUNT)) { - print ''; - print ''; - } else { - print ''; - } - print ' '.$langs->trans("Currency".$currency).''; - } else { - $valtoshow = $amount; - if (!empty($conf->global->MEMBER_MIN_AMOUNT) && $valtoshow) { - $valtoshow = max($conf->global->MEMBER_MIN_AMOUNT, $valtoshow); - $amount = $valtoshow; - } - print ''.price($valtoshow, 1, $langs, 1, -1, -1, $currency).''; // Price with currency - print ''; - print ''; + print ''.price($amount, 1, $langs, 1, -1, -1, $currency).''; // Price with currency + $caneditamount = !empty($conf->global->MEMBER_NEWFORM_EDITAMOUNT) || $adht->caneditamount; + $minimumamount = empty($conf->global->MEMBER_MIN_AMOUNT)? $adht->amount : max($conf->global->MEMBER_MIN_AMOUNT, $adht->amount > $amount); + if(!$caneditamount && $minimumamount > $amount) { + print ' '. $langs->trans("AmountIsLowerToMinimumNotice", price($adht->amount, 1, $langs, 1, -1, -1, $currency)); } + + print ''; print ''; print ''."\n"; From f8af181cee81767fd2f0f68cbd30c59f438951d5 Mon Sep 17 00:00:00 2001 From: Yoan Mollard Date: Wed, 29 Jun 2022 00:28:33 +0200 Subject: [PATCH 120/826] Label clarification following the new per-type setting "CanEditAmount" --- htdocs/langs/en_US/members.lang | 2 +- htdocs/langs/fr_FR/members.lang | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/langs/en_US/members.lang b/htdocs/langs/en_US/members.lang index d9af9c9c350..70b207c2b88 100644 --- a/htdocs/langs/en_US/members.lang +++ b/htdocs/langs/en_US/members.lang @@ -201,7 +201,7 @@ NbOfSubscriptions=Number of contributions AmountOfSubscriptions=Amount collected from contributions TurnoverOrBudget=Turnover (for a company) or Budget (for a foundation) DefaultAmount=Default amount of contribution -CanEditAmount=Visitor can choose/edit amount of its contribution +CanEditAmount=Visitor can choose/edit amount of its contribution regardless of the member type AmountIsLowerToMinimumNotice=sur un dû total de %s MEMBER_NEWFORM_PAYONLINE=Jump on integrated online payment page ByProperties=By nature diff --git a/htdocs/langs/fr_FR/members.lang b/htdocs/langs/fr_FR/members.lang index 9cf2f25a2b0..9c3c51d52c6 100644 --- a/htdocs/langs/fr_FR/members.lang +++ b/htdocs/langs/fr_FR/members.lang @@ -198,7 +198,7 @@ NbOfSubscriptions=Nombre de cotisations AmountOfSubscriptions=Montant des cotisations TurnoverOrBudget=Chiffre affaire (pour société) ou Budget (asso ou collectivité) DefaultAmount=Montant par défaut de la cotisation -CanEditAmount=Le visiteur peut modifier / choisir le montant de sa cotisation +CanEditAmount=Le visiteur peut modifier / choisir le montant de sa cotisation quel que soit le type d'adhésion AmountIsLowerToMinimumNotice=sur un dû total de %s AnyAmountWithAdvisedAmount=Montant libre avec un montant recommandé de %s %s AnyAmountWithoutAdvisedAmount=Montant libre From e7058c253e6b5014bec7e77b44a3e80301048038 Mon Sep 17 00:00:00 2001 From: Yoan Mollard Date: Wed, 29 Jun 2022 03:25:33 +0200 Subject: [PATCH 121/826] NEW: Table of membership types --- htdocs/langs/en_US/members.lang | 3 + htdocs/langs/fr_FR/members.lang | 3 + htdocs/public/members/new.php | 580 ++++++++++++++++++-------------- 3 files changed, 339 insertions(+), 247 deletions(-) diff --git a/htdocs/langs/en_US/members.lang b/htdocs/langs/en_US/members.lang index 70b207c2b88..972be559eec 100644 --- a/htdocs/langs/en_US/members.lang +++ b/htdocs/langs/en_US/members.lang @@ -74,6 +74,9 @@ Subscription=Contribution AnyAmountWithAdvisedAmount=Any amount with a recommended amount of %s %s AnyAmountWithoutAdvisedAmount=Any amount CanEditAmountShort=Any amount +CanEditAmountShortForValues=recommended, any amount +MembershipDuration=Duration +GetMembershipButtonLabel=Get membership Subscriptions=Contributions SubscriptionLate=Late SubscriptionNotReceived=Contribution never received diff --git a/htdocs/langs/fr_FR/members.lang b/htdocs/langs/fr_FR/members.lang index 9c3c51d52c6..a5a76c9be55 100644 --- a/htdocs/langs/fr_FR/members.lang +++ b/htdocs/langs/fr_FR/members.lang @@ -202,6 +202,9 @@ CanEditAmount=Le visiteur peut modifier / choisir le montant de sa cotisation qu AmountIsLowerToMinimumNotice=sur un dû total de %s AnyAmountWithAdvisedAmount=Montant libre avec un montant recommandé de %s %s AnyAmountWithoutAdvisedAmount=Montant libre +CanEditAmountShortForValues=conseillé, montant libre +MembershipDuration=Durée +GetMembershipButtonLabel=Adhérer CanEditAmountShort=Montant libre MEMBER_NEWFORM_PAYONLINE=Rediriger sur la page intégrée de paiement en ligne ByProperties=Par nature diff --git a/htdocs/public/members/new.php b/htdocs/public/members/new.php index f6957502284..6f490ca5b66 100644 --- a/htdocs/public/members/new.php +++ b/htdocs/public/members/new.php @@ -69,6 +69,7 @@ require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php'; require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent_type.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/cunits.class.php'; // Init vars $errmsg = ''; @@ -474,268 +475,353 @@ dol_htmloutput_errors($errmsg); print ''."\n"; print ''; print ''; -print ''; -print ''; -print '
'; +if (!empty($conf->global->MEMBER_NEWFORM_FORCETYPE) || $action == 'create') { + print ''; + print '
'; + print '
'.$langs->trans("FieldsWithAreMandatory", '*').'
'; + //print $langs->trans("FieldsWithIsForPublic",'**').'
'; -print '
'.$langs->trans("FieldsWithAreMandatory", '*').'
'; -//print $langs->trans("FieldsWithIsForPublic",'**').'
'; - -print dol_get_fiche_head(''); - -print ''; - - -print ''."\n"; - -// Type -if (empty($conf->global->MEMBER_NEWFORM_FORCETYPE)) { - $listoftype = $adht->liste_array(); - $tmp = array_keys($listoftype); - $defaulttype = ''; - $isempty = 1; - if (count($listoftype) == 1) { - $defaulttype = $tmp[0]; - $isempty = 0; - } - print ''."\n"; -} else { - $adht->fetch($conf->global->MEMBER_NEWFORM_FORCETYPE); - print ''; -} - -// Moral/Physic attribute -$morphys["phy"] = $langs->trans("Physical"); -$morphys["mor"] = $langs->trans("Moral"); -if (empty($conf->global->MEMBER_NEWFORM_FORCEMORPHY)) { - print ''."\n"; -} else { - print $morphys[$conf->global->MEMBER_NEWFORM_FORCEMORPHY]; - print ''; -} - -// Company -print ''."\n"; -// Title -print ''."\n"; -// Lastname -print ''."\n"; -// Firstname -print ''."\n"; -// EMail -print ''."\n"; -// Login -if (empty($conf->global->ADHERENT_LOGIN_NOT_REQUIRED)) { - print ''."\n"; - print ''."\n"; - print ''."\n"; -} -// Gender -print ''; -print ''; -// Address -print ''."\n"; -// Zip / Town -print ''; -// Country -print ''; -// State -if (empty($conf->global->SOCIETE_DISABLE_STATE)) { - print ''; -} -// Birthday -print ''."\n"; -// Photo -print ''."\n"; -// Public -print ''."\n"; -// Other attributes -$tpl_context = 'public'; // define template context to public -include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_add.tpl.php'; -// Comments -print ''; -print ''; -print ''; -print ''."\n"; - -// Add specific fields used by Dolibarr foundation for example -// TODO Move this into generic feature. -if (!empty($conf->global->MEMBER_NEWFORM_DOLIBARRTURNOVER)) { - $arraybudget = array('50'=>'<= 100 000', '100'=>'<= 200 000', '200'=>'<= 500 000', '300'=>'<= 1 500 000', '600'=>'<= 3 000 000', '1000'=>'<= 5 000 000', '2000'=>'5 000 000+'); - print ''."\n"; -} + jQuery(document).ready(function () { + jQuery(document).ready(function () { + function initmorphy() + { + console.log("Call initmorphy"); + if (jQuery("#morphy").val() == \'phy\') { + jQuery("#trcompany").hide(); + } + if (jQuery("#morphy").val() == \'mor\') { + jQuery("#trcompany").show(); + } + }; + initmorphy(); + jQuery("#morphy").change(function() { + initmorphy(); + }); + jQuery("#selectcountry_id").change(function() { + document.newmember.action.value="create"; + document.newmember.submit(); + }); + jQuery("#typeid").change(function() { + document.newmember.action.value="create"; + document.newmember.submit(); + }); + }); + }); + '; -if (!empty($conf->global->MEMBER_NEWFORM_PAYONLINE)) { - $amount = 0; - $typeid = $conf->global->MEMBER_NEWFORM_FORCETYPE ? $conf->global->MEMBER_NEWFORM_FORCETYPE : GETPOST('typeid', 'int'); - // Set amount for the subscription: - // - First check the amount of the member type. - $amountbytype = $adht->amountByType(1); // Load the array of amount per type - $amount = empty($amountbytype[$typeid]) ? (isset($amount) ? $amount : 0) : $amountbytype[$typeid]; - // - If not found, take the default amount - if (empty($amount) && !empty($conf->global->MEMBER_NEWFORM_AMOUNT)) { - $amount = $conf->global->MEMBER_NEWFORM_AMOUNT; - } - // - If not set, we accept ot have amount defined as parameter (for backward compatibility). - if (empty($amount)) { - $amount = (GETPOST('amount') ? price2num(GETPOST('amount', 'alpha'), 'MT', 2) : ''); - } + print '
'.$langs->trans("Type").' *'; - print $form->selectarray("typeid", $adht->liste_array(1), GETPOST('typeid') ? GETPOST('typeid') : $defaulttype, $isempty); - print '
'.$langs->trans('MemberNature').' *'."\n"; - print $form->selectarray("morphy", $morphys, GETPOST('morphy'), 1); - print '
'.$langs->trans("Company").''; -print img_picto('', 'company', 'class="pictofixedwidth"'); -print '
'.$langs->trans('UserTitle').''; -print $formcompany->select_civility(GETPOST('civility_id'), 'civility_id').'
'.$langs->trans("Lastname").' *
'.$langs->trans("Firstname").' *
'.$langs->trans("Email").($conf->global->ADHERENT_MAIL_REQUIRED ? ' *' : '').''; -//print img_picto('', 'email', 'class="pictofixedwidth"'); -print '
'.$langs->trans("Login").' *
'.$langs->trans("Password").' *
'.$langs->trans("PasswordAgain").' *
'.$langs->trans("Gender").''; -$arraygender = array('man'=>$langs->trans("Genderman"), 'woman'=>$langs->trans("Genderwoman")); -print $form->selectarray('gender', $arraygender, GETPOST('gender') ?GETPOST('gender') : $object->gender, 1); -print '
'.$langs->trans("Address").''."\n"; -print '
'.$langs->trans('Zip').' / '.$langs->trans('Town').''; -print $formcompany->select_ziptown(GETPOST('zipcode'), 'zipcode', array('town', 'selectcountry_id', 'state_id'), 0, 1, '', 'width75'); -print ' / '; -print $formcompany->select_ziptown(GETPOST('town'), 'town', array('zipcode', 'selectcountry_id', 'state_id'), 0, 1); -print '
'.$langs->trans('Country').''; -print img_picto('', 'country', 'class="pictofixedwidth"'); -$country_id = GETPOST('country_id', 'int'); -if (!$country_id && !empty($conf->global->MEMBER_NEWFORM_FORCECOUNTRYCODE)) { - $country_id = getCountry($conf->global->MEMBER_NEWFORM_FORCECOUNTRYCODE, 2, $db, $langs); -} -if (!$country_id && !empty($conf->geoipmaxmind->enabled)) { - $country_code = dol_user_country(); - //print $country_code; - if ($country_code) { - $new_country_id = getCountry($country_code, 3, $db, $langs); - //print 'xxx'.$country_code.' - '.$new_country_id; - if ($new_country_id) { - $country_id = $new_country_id; - } - } -} -$country_code = getCountry($country_id, 2, $db, $langs); -print $form->select_country($country_id, 'country_id'); -print '
'.$langs->trans('State').''; - if ($country_code) { - print $formcompany->select_state(GETPOST("state_id"), $country_code); - } - print '
'.$langs->trans("DateOfBirth").''; -print $form->selectDate($birthday, 'birth', 0, 0, 1, "newmember", 1, 0); -print '
'.$langs->trans("URLPhoto").'
'.$langs->trans("Public").'
'.$langs->trans("Comments").'
'.$langs->trans("TurnoverOrBudget").' *'; - print $form->selectarray('budget', $arraybudget, GETPOST('budget'), 1); - print ' € or $'; + print dol_get_fiche_head(''); print ''; - print '
'."\n"; - // Clean the amount - $amount = price2num($amount); - $adht = new AdherentType($db); - $adht->fetch($typeid); - $caneditamount = $adht->caneditamount; - $showedamount = $amount>0? $amount: 0; - // $conf->global->MEMBER_NEWFORM_PAYONLINE is 'paypal', 'paybox' or 'stripe' - print ''."\n"; } else { - print ''; - print ''; - print ' '.$langs->trans("Currency".$conf->currency); + $adht->fetch($conf->global->MEMBER_NEWFORM_FORCETYPE); + print ''; } + + // Moral/Physic attribute + $morphys["phy"] = $langs->trans("Physical"); + $morphys["mor"] = $langs->trans("Moral"); + if (empty($conf->global->MEMBER_NEWFORM_FORCEMORPHY)) { + print ''."\n"; + } else { + print $morphys[$conf->global->MEMBER_NEWFORM_FORCEMORPHY]; + print ''; + } + + // Company + print ''."\n"; + // Title + print ''."\n"; + // Lastname + print ''."\n"; + // Firstname + print ''."\n"; + // EMail + print ''."\n"; + // Login + if (empty($conf->global->ADHERENT_LOGIN_NOT_REQUIRED)) { + print ''."\n"; + print ''."\n"; + print ''."\n"; + } + // Gender + print ''; + print ''; + // Address + print ''."\n"; + // Zip / Town + print ''; + // Country + print ''; + // State + if (empty($conf->global->SOCIETE_DISABLE_STATE)) { + print ''; + } + // Birthday + print ''."\n"; + // Photo + print ''."\n"; + // Public + print ''."\n"; + // Other attributes + $tpl_context = 'public'; // define template context to public + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_add.tpl.php'; + // Comments + print ''; + print ''; + print ''; + print ''."\n"; + + // Add specific fields used by Dolibarr foundation for example + // TODO Move this into generic feature. + if (!empty($conf->global->MEMBER_NEWFORM_DOLIBARRTURNOVER)) { + $arraybudget = array('50'=>'<= 100 000', '100'=>'<= 200 000', '200'=>'<= 500 000', '300'=>'<= 1 500 000', '600'=>'<= 3 000 000', '1000'=>'<= 5 000 000', '2000'=>'5 000 000+'); + print ''."\n"; + } + + if (!empty($conf->global->MEMBER_NEWFORM_PAYONLINE)) { + $amount = 0; + $typeid = $conf->global->MEMBER_NEWFORM_FORCETYPE ? $conf->global->MEMBER_NEWFORM_FORCETYPE : GETPOST('typeid', 'int'); + + // Set amount for the subscription: + // - First check the amount of the member type. + $amountbytype = $adht->amountByType(1); // Load the array of amount per type + $amount = empty($amountbytype[$typeid]) ? (isset($amount) ? $amount : 0) : $amountbytype[$typeid]; + // - If not found, take the default amount + if (empty($amount) && !empty($conf->global->MEMBER_NEWFORM_AMOUNT)) { + $amount = $conf->global->MEMBER_NEWFORM_AMOUNT; + } + // - If not set, we accept ot have amount defined as parameter (for backward compatibility). + if (empty($amount)) { + $amount = (GETPOST('amount') ? price2num(GETPOST('amount', 'alpha'), 'MT', 2) : ''); + } + + // Clean the amount + $amount = price2num($amount); + $adht = new AdherentType($db); + $adht->fetch($typeid); + $caneditamount = $adht->caneditamount; + $showedamount = $amount>0? $amount: 0; + // $conf->global->MEMBER_NEWFORM_PAYONLINE is 'paypal', 'paybox' or 'stripe' + print ''; + } + + print "
'.$langs->trans("Subscription"); - if (!empty($conf->global->MEMBER_EXT_URL_SUBSCRIPTION_INFO)) { - print ' - '.$langs->trans("SeeHere").''; - } - print ''; - - if (empty($amount) && !empty($conf->global->MEMBER_NEWFORM_AMOUNT)) { - $amount = $conf->global->MEMBER_NEWFORM_AMOUNT; - } - - if (!empty($conf->global->MEMBER_NEWFORM_EDITAMOUNT) || $caneditamount) { - print ''; - print ' '.$langs->trans("Currency".$conf->currency).' – '; - print $amount>0? $langs->trans("AnyAmountWithAdvisedAmount", $amount, $langs->trans("Currency".$conf->currency)): $langs->trans("AnyAmountWithoutAdvisedAmount"); - print ''; + // Type + if (empty($conf->global->MEMBER_NEWFORM_FORCETYPE)) { + $listoftype = $adht->liste_array(); + $tmp = array_keys($listoftype); + $defaulttype = ''; + $isempty = 1; + if (count($listoftype) == 1) { + $defaulttype = $tmp[0]; + $isempty = 0; + } + print '
'.$langs->trans("Type").' *'; + print $form->selectarray("typeid", $adht->liste_array(1), GETPOST('typeid') ? GETPOST('typeid') : $defaulttype, $isempty); + print '
'.$langs->trans('MemberNature').' *'."\n"; + print $form->selectarray("morphy", $morphys, GETPOST('morphy'), 1); + print '
'.$langs->trans("Company").''; + print img_picto('', 'company', 'class="pictofixedwidth"'); + print '
'.$langs->trans('UserTitle').''; + print $formcompany->select_civility(GETPOST('civility_id'), 'civility_id').'
'.$langs->trans("Lastname").' *
'.$langs->trans("Firstname").' *
'.$langs->trans("Email").($conf->global->ADHERENT_MAIL_REQUIRED ? ' *' : '').''; + //print img_picto('', 'email', 'class="pictofixedwidth"'); + print '
'.$langs->trans("Login").' *
'.$langs->trans("Password").' *
'.$langs->trans("PasswordAgain").' *
'.$langs->trans("Gender").''; + $arraygender = array('man'=>$langs->trans("Genderman"), 'woman'=>$langs->trans("Genderwoman")); + print $form->selectarray('gender', $arraygender, GETPOST('gender') ?GETPOST('gender') : $object->gender, 1); print '
'.$langs->trans("Address").''."\n"; + print '
'.$langs->trans('Zip').' / '.$langs->trans('Town').''; + print $formcompany->select_ziptown(GETPOST('zipcode'), 'zipcode', array('town', 'selectcountry_id', 'state_id'), 0, 1, '', 'width75'); + print ' / '; + print $formcompany->select_ziptown(GETPOST('town'), 'town', array('zipcode', 'selectcountry_id', 'state_id'), 0, 1); + print '
'.$langs->trans('Country').''; + print img_picto('', 'country', 'class="pictofixedwidth"'); + $country_id = GETPOST('country_id', 'int'); + if (!$country_id && !empty($conf->global->MEMBER_NEWFORM_FORCECOUNTRYCODE)) { + $country_id = getCountry($conf->global->MEMBER_NEWFORM_FORCECOUNTRYCODE, 2, $db, $langs); + } + if (!$country_id && !empty($conf->geoipmaxmind->enabled)) { + $country_code = dol_user_country(); + //print $country_code; + if ($country_code) { + $new_country_id = getCountry($country_code, 3, $db, $langs); + //print 'xxx'.$country_code.' - '.$new_country_id; + if ($new_country_id) { + $country_id = $new_country_id; + } + } + } + $country_code = getCountry($country_id, 2, $db, $langs); + print $form->select_country($country_id, 'country_id'); + print '
'.$langs->trans('State').''; + if ($country_code) { + print $formcompany->select_state(GETPOST("state_id"), $country_code); + } + print '
'.$langs->trans("DateOfBirth").''; + print $form->selectDate($birthday, 'birth', 0, 0, 1, "newmember", 1, 0); + print '
'.$langs->trans("URLPhoto").'
'.$langs->trans("Public").'
'.$langs->trans("Comments").'
'.$langs->trans("TurnoverOrBudget").' *'; + print $form->selectarray('budget', $arraybudget, GETPOST('budget'), 1); + print ' € or $'; + + print ''; + print '
'.$langs->trans("Subscription"); + if (!empty($conf->global->MEMBER_EXT_URL_SUBSCRIPTION_INFO)) { + print ' - '.$langs->trans("SeeHere").''; + } + print ''; + + if (empty($amount) && !empty($conf->global->MEMBER_NEWFORM_AMOUNT)) { + $amount = $conf->global->MEMBER_NEWFORM_AMOUNT; + } + + if (!empty($conf->global->MEMBER_NEWFORM_EDITAMOUNT) || $caneditamount) { + print ''; + print ' '.$langs->trans("Currency".$conf->currency).' – '; + print $amount>0? $langs->trans("AnyAmountWithAdvisedAmount", $amount, $langs->trans("Currency".$conf->currency)): $langs->trans("AnyAmountWithoutAdvisedAmount"); + print ''; + } else { + print ''; + print ''; + print ' '.$langs->trans("Currency".$conf->currency); + } + print '
\n"; + + print dol_get_fiche_end(); + + // Save + print '
'; + print ''; + if (!empty($backtopage)) { + print '     '; + } + print '
'; + + + print "\n"; + print "
"; + print '
'; } +else { // Show the table of membership types + // Get units + $measuringUnits = new CUnits($db); + $result = $measuringUnits->fetchAll('', '', 0, 0, array('t.active' => 1)); + $units = array(); + foreach ($measuringUnits->records as $lines) + $units[$lines->short_label] = $langs->trans(ucfirst($lines->label)); -print "\n"; + $sql = "SELECT d.rowid, d.libelle as label, d.subscription, d.amount, d.caneditamount, d.vote, d.note, d.duration, d.statut as status, d.morphy"; + $sql .= " FROM ".MAIN_DB_PREFIX."adherent_type as d"; + $sql .= " WHERE d.entity IN (".getEntity('member_type').")"; + $sql .= " AND d.statut=1"; -print dol_get_fiche_end(); + $result = $db->query($sql); + if ($result) { + $num = $db->num_rows($result); + + print '
'; + print ''."\n"; + print ''; -// Save -print '
'; -print ''; -if (!empty($backtopage)) { - print '     '; + print '
'; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print "\n"; + + $i = 0; + while ($i < $num) { + $objp = $db->fetch_object($result); + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ""; + $i++; + } + + // If no record found + if ($num == 0) { + $colspan = 8; + print ''; + } + + print "
'.$langs->trans("Label").''.$langs->trans("MembershipDuration").''.$langs->trans("Amount").''.$langs->trans("MembersNature").''.$langs->trans("VoteAllowed").''.$langs->trans("NewSubscription").'
'.dol_escape_htmltag($objp->label).''; + $unit = preg_replace("/[^a-zA-Z]+/", "", $objp->duration); + print max(1, intval($objp->duration)).' '.$units[$unit]; + print ''; + $displayedamount = max(intval($objp->amount), intval($conf->global->MEMBER_MIN_AMOUNT)); + $caneditamount = !empty($conf->global->MEMBER_NEWFORM_EDITAMOUNT) || $objp->caneditamount; + if($objp->subscription) { + print $displayedamount.' '.strtoupper($conf->currency); + if ($caneditamount && $displayedamount>0) { + print $form->textwithpicto('', $langs->transnoentities("CanEditAmountShortForValues"), 1, 'help', '', 0, 3); + } + elseif ($caneditamount) { + print $langs->transnoentities("CanEditAmountShort"); + } + } + else { + print "–"; // No subscription required + } + print ''; + if ($objp->morphy == 'phy') { + print $langs->trans("Physical"); + } elseif ($objp->morphy == 'mor') { + print $langs->trans("Moral"); + } else { + print $langs->trans("MorAndPhy"); + } + print ''.yn($objp->vote).'
'.$langs->trans("NoRecordFound").'
"; + print '
'; + + print ''; + } else { + dol_print_error($db); + } } -print ''; - - -print "\n"; -print "
"; -print ''; llxFooterVierge(); From f4d5962254504ae5df37bfc031537ef0969a6e16 Mon Sep 17 00:00:00 2001 From: Yoan Mollard Date: Wed, 29 Jun 2022 03:27:48 +0200 Subject: [PATCH 122/826] Allow to skip membership table for retrocompatibility --- htdocs/public/members/new.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/public/members/new.php b/htdocs/public/members/new.php index 6f490ca5b66..04ae3cdd7bd 100644 --- a/htdocs/public/members/new.php +++ b/htdocs/public/members/new.php @@ -476,7 +476,7 @@ print '
'. print ''; print ''; -if (!empty($conf->global->MEMBER_NEWFORM_FORCETYPE) || $action == 'create') { +if (!empty($conf->global->MEMBER_SKIP_TABLE) || !empty($conf->global->MEMBER_NEWFORM_FORCETYPE) || $action == 'create') { print ''; print '
'; print '
'.$langs->trans("FieldsWithAreMandatory", '*').'
'; From 253799eb1edbbec1ae65a90da9c0e52e3dcf70a3 Mon Sep 17 00:00:00 2001 From: bagtaib Date: Wed, 29 Jun 2022 05:07:32 +0200 Subject: [PATCH 123/826] NEW #21399 --- htdocs/core/lib/xcal.lib.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/htdocs/core/lib/xcal.lib.php b/htdocs/core/lib/xcal.lib.php index 97ada3e3d4f..cd300546e46 100644 --- a/htdocs/core/lib/xcal.lib.php +++ b/htdocs/core/lib/xcal.lib.php @@ -301,7 +301,7 @@ function build_calfile($format, $title, $desc, $events_array, $outputfile) * @param string $format "rss" * @param string $title Title of export * @param string $desc Description of export - * @param array $events_array Array of events ("uid","startdate","summary","url","desc","author","category") or Array of WebsitePage + * @param array $events_array Array of events ("uid","startdate","summary","url","desc","author","category","image") or Array of WebsitePage * @param string $outputfile Output file * @param string $filter (optional) Filter * @param string $url Url (If empty, forge URL for agenda RSS export) @@ -377,6 +377,7 @@ function build_rssfile($format, $title, $desc, $events_array, $outputfile, $filt $tmpevent['author'] = $event->author_alias ? $event->author_alias : 'unknown'; //$tmpevent['category'] = ''; $tmpevent['desc'] = $event->description; + $tmpevent['image'] = $event->image; $event = $tmpevent; } @@ -387,7 +388,9 @@ function build_rssfile($format, $title, $desc, $events_array, $outputfile, $filt $url = $event["url"]; $author = $event["author"]; $category = $event["category"]; - + if (!empty($event["image"])) { + $image = $event["image"]; + } /* No place inside a RSS $priority = $event["priority"]; $fulldayevent = $event["fulldayevent"]; @@ -404,6 +407,10 @@ function build_rssfile($format, $title, $desc, $events_array, $outputfile, $filt fwrite($fichier, "\n"); fwrite($fichier, "

'); + } + if ($description) { fwrite($fichier, $description); } From f4c7c03dc10fea94957c40f1bde99d305ca8996f Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Wed, 29 Jun 2022 14:38:43 +0000 Subject: [PATCH 124/826] Fixing style errors. --- htdocs/public/members/new.php | 14 ++++++-------- htdocs/public/payment/newpayment.php | 4 ++-- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/htdocs/public/members/new.php b/htdocs/public/members/new.php index 04ae3cdd7bd..7f3687cc006 100644 --- a/htdocs/public/members/new.php +++ b/htdocs/public/members/new.php @@ -702,7 +702,7 @@ if (!empty($conf->global->MEMBER_SKIP_TABLE) || !empty($conf->global->MEMBER_NEW print ' - '.$langs->trans("SeeHere").''; } print ''; - + if (empty($amount) && !empty($conf->global->MEMBER_NEWFORM_AMOUNT)) { $amount = $conf->global->MEMBER_NEWFORM_AMOUNT; } @@ -753,7 +753,7 @@ else { // Show the table of membership types $result = $db->query($sql); if ($result) { $num = $db->num_rows($result); - + print '
'; print ''."\n"; print ''; @@ -766,7 +766,7 @@ else { // Show the table of membership types print ''; print ''; print "\n"; - + $i = 0; while ($i < $num) { $objp = $db->fetch_object($result); @@ -780,16 +780,14 @@ else { // Show the table of membership types print ''; diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index 1c3c0202b23..a6b190bfc66 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -1622,10 +1622,10 @@ if ($source == 'member' || $source == 'membersubscription') { print ''.price($amount, 1, $langs, 1, -1, -1, $currency).''; // Price with currency $caneditamount = !empty($conf->global->MEMBER_NEWFORM_EDITAMOUNT) || $adht->caneditamount; $minimumamount = empty($conf->global->MEMBER_MIN_AMOUNT)? $adht->amount : max($conf->global->MEMBER_MIN_AMOUNT, $adht->amount > $amount); - if(!$caneditamount && $minimumamount > $amount) { + if (!$caneditamount && $minimumamount > $amount) { print ' '. $langs->trans("AmountIsLowerToMinimumNotice", price($adht->amount, 1, $langs, 1, -1, -1, $currency)); } - + print ''; print ''; print ''."\n"; From 371b4ac94e284943bb95e269b18da123eb3a7757 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9=20GDSOFT?= Date: Wed, 29 Jun 2022 16:56:07 +0200 Subject: [PATCH 125/826] invoice export : add accounting affectation --- htdocs/core/modules/modFacture.class.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/htdocs/core/modules/modFacture.class.php b/htdocs/core/modules/modFacture.class.php index 2cdc8229e51..498ff55da74 100644 --- a/htdocs/core/modules/modFacture.class.php +++ b/htdocs/core/modules/modFacture.class.php @@ -517,7 +517,8 @@ class modFacture extends DolibarrModules 'fd.subprice'=>"LineUnitPrice", 'fd.tva_tx'=>"LineVATRate", 'fd.qty'=>"LineQty", 'fd.total_ht'=>"LineTotalHT", 'fd.total_tva'=>"LineTotalVAT", 'fd.total_ttc'=>"LineTotalTTC", 'fd.date_start'=>"DateStart", 'fd.date_end'=>"DateEnd", 'fd.special_code'=>'SpecialCode', 'fd.product_type'=>"TypeOfLineServiceOrProduct", 'fd.fk_product'=>'ProductId', 'p.ref'=>'ProductRef', 'p.label'=>'ProductLabel', - $alias_product_perentity . '.accountancy_code_sell'=>'ProductAccountancySellCode' + $alias_product_perentity . '.accountancy_code_sell'=>'ProductAccountancySellCode', + 'aa.account_number' => 'AccountingAffectation' ); if (!empty($conf->multicurrency->enabled)) { $this->export_fields_array[$r]['f.multicurrency_code'] = 'Currency'; @@ -549,6 +550,7 @@ class modFacture extends DolibarrModules 'fd.special_code'=>'Numeric', 'fd.product_type'=>"Numeric", 'fd.fk_product'=>'List:product:label', 'p.ref'=>'Text', 'p.label'=>'Text', $alias_product_perentity . '.accountancy_code_sell'=>'Text', 'f.entity'=>'List:entity:label:rowid', + 'aa.account_number' => 'Text' ); if (!empty($conf->cashdesk->enabled) || !empty($conf->takepos->enabled) || !empty($conf->global->INVOICE_SHOW_POS)) { $this->export_TypeFields_array[$r]['f.module_source'] = 'Text'; @@ -561,7 +563,8 @@ class modFacture extends DolibarrModules 'fd.subprice'=>"invoice_line", 'fd.total_ht'=>"invoice_line", 'fd.total_tva'=>"invoice_line", 'fd.total_ttc'=>"invoice_line", 'fd.tva_tx'=>"invoice_line", 'fd.qty'=>"invoice_line", 'fd.date_start'=>"invoice_line", 'fd.date_end'=>"invoice_line", 'fd.special_code'=>'invoice_line', 'fd.product_type'=>'invoice_line', 'fd.fk_product'=>'product', 'p.ref'=>'product', 'p.label'=>'product', $alias_product_perentity . '.accountancy_code_sell'=>'product', - 'f.fk_user_author'=>'user', 'uc.login'=>'user', 'f.fk_user_valid'=>'user', 'uv.login'=>'user' + 'f.fk_user_author'=>'user', 'uc.login'=>'user', 'f.fk_user_valid'=>'user', 'uv.login'=>'user', + 'aa.account_number' => "invoice_line", ); $this->export_special_array[$r] = array('none.rest'=>'getRemainToPay'); $this->export_dependencies_array[$r] = array('invoice_line'=>'fd.rowid', 'product'=>'fd.rowid', 'none.rest'=>array('f.rowid', 'f.total_ttc', 'f.close_code')); // To add unique key if we ask a field of a child to avoid the DISTINCT to discard them @@ -602,6 +605,7 @@ class modFacture extends DolibarrModules $this->export_sql_end[$r] .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity); } $this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_extrafields as extra3 on p.rowid = extra3.fk_object'; + $this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'accounting_account as aa on fd.fk_code_ventilation = aa.rowid'; $this->export_sql_end[$r] .= ' WHERE f.fk_soc = s.rowid AND f.rowid = fd.fk_facture'; $this->export_sql_end[$r] .= ' AND f.entity IN ('.getEntity('invoice').')'; if (empty($user->rights->societe->client->voir)) { From 7fcbe97b9c90a50b2f39eff211ccf8039e98456e Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Wed, 29 Jun 2022 17:32:50 +0200 Subject: [PATCH 126/826] NEW Project - Add author on list --- htdocs/projet/list.php | 53 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/htdocs/projet/list.php b/htdocs/projet/list.php index eaf9c5022a3..2c111a30c2c 100644 --- a/htdocs/projet/list.php +++ b/htdocs/projet/list.php @@ -108,6 +108,7 @@ $search_accept_conference_suggestions = GETPOST('search_accept_conference_sugges $search_accept_booth_suggestions = GETPOST('search_accept_booth_suggestions', 'int'); $search_price_registration = GETPOST("search_price_registration", 'alpha'); $search_price_booth = GETPOST("search_price_booth", 'alpha'); +$search_login = GETPOST('search_login', 'alpha'); $optioncss = GETPOST('optioncss', 'alpha'); $mine = ((GETPOST('mode') == 'mine') ? 1 : 0); @@ -201,6 +202,7 @@ $arrayfields['s.nom'] = array('label'=>$langs->trans("ThirdParty"), 'checked'=>1 $arrayfields['commercial'] = array('label'=>$langs->trans("SaleRepresentativesOfThirdParty"), 'checked'=>0, 'position'=>23); $arrayfields['c.assigned'] = array('label'=>$langs->trans("AssignedTo"), 'checked'=>-1, 'position'=>120); $arrayfields['opp_weighted_amount'] = array('label'=>$langs->trans('OpportunityWeightedAmountShort'), 'checked'=>0, 'position'=> 116, 'enabled'=>(empty($conf->global->PROJECT_USE_OPPORTUNITIES) ? 0 : 1), 'position'=>106); +$arrayfields['u.login'] = array('label'=>"Author", 'checked'=>1, 'position'=>165); // Force some fields according to search_usage filter... if (GETPOST('search_usage_opportunity')) { //$arrayfields['p.usage_opportunity']['visible'] = 1; // Not require, filter on search_opp_status is enough @@ -285,6 +287,7 @@ if (empty($reshook)) { $search_accept_booth_suggestions = ''; $search_price_registration = ''; $search_price_booth = ''; + $search_login = ''; $toselect = array(); $search_array_options = array(); $search_category_array = array(); @@ -390,10 +393,11 @@ $sql = "SELECT ".$distinct." p.rowid as id, p.ref, p.title, p.fk_statut as statu $sql .= " p.datec as date_creation, p.dateo as date_start, p.datee as date_end, p.opp_amount, p.opp_percent, (p.opp_amount*p.opp_percent/100) as opp_weighted_amount, p.tms as date_update, p.budget_amount,"; $sql .= " p.usage_opportunity, p.usage_task, p.usage_bill_time, p.usage_organize_event,"; $sql .= " p.email_msgid,"; -$sql .= " accept_conference_suggestions, accept_booth_suggestions, price_registration, price_booth,"; +$sql .= " p.accept_conference_suggestions, p.accept_booth_suggestions, p.price_registration, p.price_booth,"; $sql .= " s.rowid as socid, s.nom as name, s.name_alias as alias, s.email, s.email, s.phone, s.fax, s.address, s.town, s.zip, s.fk_pays, s.client, s.code_client,"; $sql .= " country.code as country_code,"; -$sql .= " cls.code as opp_status_code"; +$sql .= " cls.code as opp_status_code,"; +$sql .= ' u.login, u.lastname, u.firstname, u.email as user_email, u.statut as user_statut, u.entity, u.photo, u.office_phone, u.office_fax, u.user_mobile, u.job, u.gender'; // Add fields from extrafields if (!empty($extrafields->attributes[$object->table_element]['label'])) { foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { @@ -415,6 +419,7 @@ if (!empty($extrafields->attributes[$object->table_element]['label']) &&is_array $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on p.fk_soc = s.rowid"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as country on (country.rowid = s.fk_pays)"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_lead_status as cls on p.fk_opp_status = cls.rowid"; +$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'user AS u ON p.fk_user_creat = u.rowid'; // We'll need this table joined to the select in order to filter by sale // No check is done on company permission because readability is managed by public status of project and assignement. //if ($search_sale > 0 || (! $user->rights->societe->client->voir && ! $socid)) $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON sc.fk_soc = s.rowid"; @@ -544,6 +549,9 @@ if ($search_price_registration != '') { if ($search_price_booth != '') { $sql .= natural_search('p.price_booth', $search_price_booth, 1); } +if ($search_login) { + $sql .= natural_search(array('u.login', 'u.firstname', 'u.lastname'), $search_login); +} // Add where from extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; // Add where from hooks @@ -735,6 +743,9 @@ if ($search_price_registration != '') { if ($search_price_booth != '') { $param .= '&search_price_booth='.urlencode($search_price_booth); } +if ($search_login) { + $param .= '&search_login='.urlencode($search_login); +} if ($optioncss != '') { $param .= '&optioncss='.urlencode($optioncss); } @@ -999,6 +1010,12 @@ if (!empty($arrayfields['p.price_booth']['checked'])) { print ''; print ''; } +if (!empty($arrayfields['u.login']['checked'])) { + // Author + print ''; +} // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; @@ -1104,6 +1121,9 @@ if (!empty($arrayfields['p.price_registration']['checked'])) { if (!empty($arrayfields['p.price_booth']['checked'])) { print_liste_field_titre($arrayfields['p.price_booth']['label'], $_SERVER["PHP_SELF"], 'p.price_booth', "", $param, '', $sortfield, $sortorder, 'right '); } +if (!empty($arrayfields['u.login']['checked'])) { + print_liste_field_titre($arrayfields['u.login']['label'], $_SERVER["PHP_SELF"], 'u.login', '', $param, 'align="center"', $sortfield, $sortorder); +} // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; // Hook fields @@ -1125,6 +1145,8 @@ if (!empty($arrayfields['p.fk_statut']['checked'])) { print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); print "\n"; +$userstatic = new User($db); + $i = 0; $totalarray = array( 'nbfield' => 0, @@ -1473,6 +1495,33 @@ while ($i < min($num, $limit)) { $totalarray['pos'][$totalarray['nbfield']] = 'p.price_booth'; } } + // Author + $userstatic->id = $obj->fk_user_creat; + $userstatic->login = $obj->login; + $userstatic->lastname = $obj->lastname; + $userstatic->firstname = $obj->firstname; + $userstatic->email = $obj->user_email; + $userstatic->statut = $obj->user_statut; + $userstatic->entity = $obj->entity; + $userstatic->photo = $obj->photo; + $userstatic->office_phone = $obj->office_phone; + $userstatic->office_fax = $obj->office_fax; + $userstatic->user_mobile = $obj->user_mobile; + $userstatic->job = $obj->job; + $userstatic->gender = $obj->gender; + + if (!empty($arrayfields['u.login']['checked'])) { + print '\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; // Fields from hook From 6a8882b60ddd36072345bb19154865e7adc7f3d4 Mon Sep 17 00:00:00 2001 From: Yoan Mollard Date: Thu, 30 Jun 2022 00:39:13 +0200 Subject: [PATCH 127/826] Bugfix: regression, keep newamount equal to amount for the payment Follows 759900bccee95b31e7684b2d69d93370d0e176ed --- htdocs/public/payment/newpayment.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index a6b190bfc66..faf3cafc59a 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -1627,6 +1627,7 @@ if ($source == 'member' || $source == 'membersubscription') { } print ''; + print ''; print ''; print ''."\n"; From c989ea1ad6b2acfd2b89f3d0ae3bb901a6772519 Mon Sep 17 00:00:00 2001 From: kamel Date: Fri, 1 Jul 2022 14:59:11 +0200 Subject: [PATCH 128/826] NEW: Add new global variable for keeping the previous signature information on proposale (case of reopen a proposale) --- htdocs/comm/propal/class/propal.class.php | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index cafca0d05a9..ba39e8a6d40 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -2614,8 +2614,22 @@ class Propal extends CommonObject $newprivatenote = dol_concatdesc($this->note_private, $note); + if (empty($conf->global->PROPALE_KEEP_OLD_SIGNATURE_INFO)) { + $date_signature = $now; + $fk_user_signature = $user->id; + } else { + $this->info($this->id); + if (!isset($this->date_signature) || $this->date_signature == '') { + $date_signature = $now; + $fk_user_signature = $user->id; + } else { + $date_signature = $this->date_signature; + $fk_user_signature = $this->user_signature->id; + } + } + $sql = "UPDATE ".MAIN_DB_PREFIX."propal"; - $sql .= " SET fk_statut = ".((int) $status).", note_private = '".$this->db->escape($newprivatenote)."', date_signature='".$this->db->idate($now)."', fk_user_signature=".$user->id; + $sql .= " SET fk_statut = ".((int) $status).", note_private = '".$this->db->escape($newprivatenote)."', date_signature='".$this->db->idate($date_signature)."', fk_user_signature=".$fk_user_signature; $sql .= " WHERE rowid = ".((int) $this->id); $resql = $this->db->query($sql); @@ -2662,7 +2676,7 @@ class Propal extends CommonObject $this->oldcopy= clone $this; $this->statut = $status; $this->status = $status; - $this->date_signature = $now; + $this->date_signature = $date_signature; $this->note_private = $newprivatenote; } From 5af4e811404f35928ee8053d5ac887bcce013eb2 Mon Sep 17 00:00:00 2001 From: Yoan Mollard Date: Fri, 1 Jul 2022 17:39:56 +0200 Subject: [PATCH 129/826] Delay caneditamount feature to v17 --- .../install/mysql/migration/16.0.0-17.0.0.sql | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 htdocs/install/mysql/migration/16.0.0-17.0.0.sql diff --git a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql new file mode 100644 index 00000000000..67402464199 --- /dev/null +++ b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql @@ -0,0 +1,36 @@ +-- +-- Be carefull to requests order. +-- This file must be loaded by calling /install/index.php page +-- when current version is 15.0.0 or higher. +-- +-- To restrict request to Mysql version x.y minimum use -- VMYSQLx.y +-- To restrict request to Pgsql version x.y minimum use -- VPGSQLx.y +-- To rename a table: ALTER TABLE llx_table RENAME TO llx_table_new; +-- To add a column: ALTER TABLE llx_table ADD COLUMN newcol varchar(60) NOT NULL DEFAULT '0' AFTER existingcol; +-- To rename a column: ALTER TABLE llx_table CHANGE COLUMN oldname newname varchar(60); +-- To drop a column: ALTER TABLE llx_table DROP COLUMN oldname; +-- To change type of field: ALTER TABLE llx_table MODIFY COLUMN name varchar(60); +-- To drop a foreign key: ALTER TABLE llx_table DROP FOREIGN KEY fk_name; +-- To create a unique index ALTER TABLE llx_table ADD UNIQUE INDEX uk_table_field (field); +-- To drop an index: -- VMYSQL4.1 DROP INDEX nomindex on llx_table; +-- To drop an index: -- VPGSQL8.2 DROP INDEX nomindex; +-- To make pk to be auto increment (mysql): +-- -- VMYSQL4.3 ALTER TABLE llx_table ADD PRIMARY KEY(rowid); +-- -- VMYSQL4.3 ALTER TABLE llx_table CHANGE COLUMN rowid rowid INTEGER NOT NULL AUTO_INCREMENT; +-- To make pk to be auto increment (postgres): +-- -- VPGSQL8.2 CREATE SEQUENCE llx_table_rowid_seq OWNED BY llx_table.rowid; +-- -- VPGSQL8.2 ALTER TABLE llx_table ADD PRIMARY KEY (rowid); +-- -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN rowid SET DEFAULT nextval('llx_table_rowid_seq'); +-- -- VPGSQL8.2 SELECT setval('llx_table_rowid_seq', MAX(rowid)) FROM llx_table; +-- To set a field as NULL: -- VMYSQL4.3 ALTER TABLE llx_table MODIFY COLUMN name varchar(60) NULL; +-- To set a field as NULL: -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN name DROP NOT NULL; +-- To set a field as NOT NULL: -- VMYSQL4.3 ALTER TABLE llx_table MODIFY COLUMN name varchar(60) NOT NULL; +-- To set a field as NOT NULL: -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN name SET NOT NULL; +-- To set a field as default NULL: -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN name SET DEFAULT NULL; +-- Note: fields with type BLOB/TEXT can't have default value. +-- To rebuild sequence for postgresql after insert by forcing id autoincrement fields: +-- -- VPGSQL8.2 SELECT dol_util_rebuild_sequences(); + + +-- Allow users to make subscriptions of any amount during membership subscription +ALTER TABLE llx_adherent_type ADD COLUMN caneditamount varchar(3) DEFAULT 0 AFTER amount; From 259224c3bef96b19f4d63a88d3502800b4bf6b8f Mon Sep 17 00:00:00 2001 From: Faustin Date: Sat, 2 Jul 2022 18:48:35 +0200 Subject: [PATCH 130/826] NEW : Recurrent events on agenda v1 --- htdocs/comm/action/card.php | 322 +++++++++++++++++---------------- htdocs/langs/en_US/agenda.lang | 4 +- htdocs/langs/fr_FR/agenda.lang | 4 +- 3 files changed, 177 insertions(+), 153 deletions(-) diff --git a/htdocs/comm/action/card.php b/htdocs/comm/action/card.php index 351ab9212bc..ac943350819 100644 --- a/htdocs/comm/action/card.php +++ b/htdocs/comm/action/card.php @@ -409,93 +409,130 @@ if (empty($reshook) && $action == 'add') { $error++; } + + if (!$error) { $db->begin(); - // Creation of action/event - $idaction = $object->create($user); + $dayoffset = 0; + $monthoffset = 0; - if ($idaction > 0) { - if (!$object->error) { - // Category association - $categories = GETPOST('categories', 'array'); - $object->setCategories($categories); + // If event is recurrent + $userepeatevent = ($conf->global->MAIN_FEATURES_LEVEL == 2 ? 1 : 0); + if ($userepeatevent && GETPOSTISSET('recurrulefreq') && GETPOST('recurrulefreq') != 'no' && GETPOSTISSET("limityear") && GETPOSTISSET("limitmonth") && GETPOSTISSET("limitday")) { + $repeateventlimitdate = dol_mktime('23', '59', '59', GETPOST("limitmonth", 'int'), GETPOST("limitday", 'int'), GETPOST("limityear", 'int') < 2100 ? GETPOST("limityear", 'int') : 2100, $tzforfullday ? $tzforfullday : 'tzuser'); + if (GETPOST('recurrulefreq') == 'DAILY') { + $dayoffset = 1; + } elseif (GETPOST('recurrulefreq') == 'WEEKLY') { + $dayoffset = 7; + } elseif (GETPOST('recurrulefreq') == 'MONTHLY') { + $monthoffset = 1; + } + } else { // If event is not recurrent, limit date is the date of the event + $repeateventlimitdate = $datep; + } - unset($_SESSION['assignedtouser']); + while ($datep <= $repeateventlimitdate) { + $finalobject = clone $object; - $moreparam = ''; - if ($user->id != $object->userownerid) { - $moreparam = "filtert=-1"; // We force to remove filter so created record is visible when going back to per user view. - } - // Create reminders - if ($addreminder == 'on') { - $actionCommReminder = new ActionCommReminder($db); + $finalobject->datep = $datep; + $finalobject->datef = $datef; + // Creation of action/event + $idaction = $finalobject->create($user); - $dateremind = dol_time_plus_duree($datep, -$offsetvalue, $offsetunit); + if ($idaction > 0) { + if (!$finalobject->error) { + // Category association + $categories = GETPOST('categories', 'array'); + $finalobject->setCategories($categories); - $actionCommReminder->dateremind = $dateremind; - $actionCommReminder->typeremind = $remindertype; - $actionCommReminder->offsetunit = $offsetunit; - $actionCommReminder->offsetvalue = $offsetvalue; - $actionCommReminder->status = $actionCommReminder::STATUS_TODO; - $actionCommReminder->fk_actioncomm = $object->id; - if ($remindertype == 'email') { - $actionCommReminder->fk_email_template = $modelmail; + unset($_SESSION['assignedtouser']); + + $moreparam = ''; + if ($user->id != $finalobject->userownerid) { + $moreparam = "filtert=-1"; // We force to remove filter so created record is visible when going back to per user view. } - // the notification must be created for every user assigned to the event - foreach ($object->userassigned as $userassigned) { - $actionCommReminder->fk_user = $userassigned['id']; - $res = $actionCommReminder->create($user); + // Create reminders + if ($addreminder == 'on') { + $actionCommReminder = new ActionCommReminder($db); - if ($res <= 0) { - // If error - $db->rollback(); - $langs->load("errors"); - $error = $langs->trans('ErrorReminderActionCommCreation'); - setEventMessages($error, null, 'errors'); - $action = 'create'; $donotclearsession = 1; - break; + $dateremind = dol_time_plus_duree($datep, -$offsetvalue, $offsetunit); + + $actionCommReminder->dateremind = $dateremind; + $actionCommReminder->typeremind = $remindertype; + $actionCommReminder->offsetunit = $offsetunit; + $actionCommReminder->offsetvalue = $offsetvalue; + $actionCommReminder->status = $actionCommReminder::STATUS_TODO; + $actionCommReminder->fk_actioncomm = $finalobject->id; + if ($remindertype == 'email') { + $actionCommReminder->fk_email_template = $modelmail; + } + + // the notification must be created for every user assigned to the event + foreach ($finalobject->userassigned as $userassigned) { + $actionCommReminder->fk_user = $userassigned['id']; + $res = $actionCommReminder->create($user); + + if ($res <= 0) { + // If error + $db->rollback(); + $langs->load("errors"); + $error = $langs->trans('ErrorReminderActionCommCreation'); + setEventMessages($error, null, 'errors'); + $action = 'create'; $donotclearsession = 1; + break; + } } } - } - // Modify $moreparam so we are sure to see the event we have just created, whatever are the default value of filter on next page. - /*$moreparam .= ($moreparam ? '&' : '').'search_actioncode=0'; - $moreparam .= ($moreparam ? '&' : '').'search_status=-1'; - $moreparam .= ($moreparam ? '&' : '').'search_filtert='.$object->userownerid; - */ - $moreparam .= ($moreparam ? '&' : '').'disabledefaultvalues=1'; + // Modify $moreparam so we are sure to see the event we have just created, whatever are the default value of filter on next page. + /*$moreparam .= ($moreparam ? '&' : '').'search_actioncode=0'; + $moreparam .= ($moreparam ? '&' : '').'search_status=-1'; + $moreparam .= ($moreparam ? '&' : '').'search_filtert='.$object->userownerid; + */ + $moreparam .= ($moreparam ? '&' : '').'disabledefaultvalues=1'; - if ($error) { + if ($error) { + $db->rollback(); + } else { + $db->commit(); + } + } else { + // If error $db->rollback(); - } else { - $db->commit(); + $langs->load("errors"); + $error = $langs->trans($finalobject->error); + setEventMessages($error, null, 'errors'); + $action = 'create'; $donotclearsession = 1; } - - if (!empty($backtopage)) { - dol_syslog("Back to ".$backtopage.($moreparam ? (preg_match('/\?/', $backtopage) ? '&'.$moreparam : '?'.$moreparam) : '')); - header("Location: ".$backtopage.($moreparam ? (preg_match('/\?/', $backtopage) ? '&'.$moreparam : '?'.$moreparam) : '')); - } elseif ($idaction) { - header("Location: ".DOL_URL_ROOT.'/comm/action/card.php?id='.$idaction.($moreparam ? '&'.$moreparam : '')); - } else { - header("Location: ".DOL_URL_ROOT.'/comm/action/index.php'.($moreparam ? '?'.$moreparam : '')); - } - exit; } else { - // If error $db->rollback(); - $langs->load("errors"); - $error = $langs->trans($object->error); - setEventMessages($error, null, 'errors'); + setEventMessages($finalobject->error, $finalobject->errors, 'errors'); $action = 'create'; $donotclearsession = 1; } - } else { - $db->rollback(); - setEventMessages($object->error, $object->errors, 'errors'); - $action = 'create'; $donotclearsession = 1; + + // If event is not recurrent, we stop here + if (!($userepeatevent && GETPOSTISSET('recurrulefreq') && GETPOST('recurrulefreq') != 'no' && GETPOSTISSET("limityear") && GETPOSTISSET("limitmonth") && GETPOSTISSET("limitday"))) { + break; + } + + // increment date for recurrent events + $datep = dol_time_plus_duree($datep, $dayoffset, 'd'); + $datep = dol_time_plus_duree($datep, $monthoffset, 'm'); + $datef = dol_time_plus_duree($datef, $dayoffset, 'd'); + $datef = dol_time_plus_duree($datef, $monthoffset, 'm'); } + if (!empty($backtopage)) { + dol_syslog("Back to ".$backtopage.($moreparam ? (preg_match('/\?/', $backtopage) ? '&'.$moreparam : '?'.$moreparam) : '')); + header("Location: ".$backtopage.($moreparam ? (preg_match('/\?/', $backtopage) ? '&'.$moreparam : '?'.$moreparam) : '')); + } elseif ($idaction) { + header("Location: ".DOL_URL_ROOT.'/comm/action/card.php?id='.$idaction.($moreparam ? '&'.$moreparam : '')); + } else { + header("Location: ".DOL_URL_ROOT.'/comm/action/index.php'.($moreparam ? '?'.$moreparam : '')); + } + exit; } } @@ -917,9 +954,10 @@ $arrayrecurrulefreq = array( 'no'=>$langs->trans("OnceOnly"), 'MONTHLY'=>$langs->trans("EveryMonth"), 'WEEKLY'=>$langs->trans("EveryWeek"), - //'DAYLY'=>$langs->trans("EveryDay") + 'DAILY'=>$langs->trans("EveryDay") ); + $help_url = 'EN:Module_Agenda_En|FR:Module_Agenda|ES:M&omodulodulo_Agenda'; llxHeader('', $langs->trans("Agenda"), $help_url); @@ -1038,44 +1076,26 @@ if ($action == 'create') { print img_picto($langs->trans("Recurrence"), 'recurring', 'class="paddingright2"'); print ''; $selectedrecurrulefreq = 'no'; - $selectedrecurrulebymonthday = ''; - $selectedrecurrulebyday = ''; - if ($object->recurrule && preg_match('/FREQ=([A-Z]+)/i', $object->recurrule, $reg)) { - $selectedrecurrulefreq = $reg[1]; - } - if ($object->recurrule && preg_match('/FREQ=MONTHLY.*BYMONTHDAY=(\d+)/i', $object->recurrule, $reg)) { - $selectedrecurrulebymonthday = $reg[1]; - } - if ($object->recurrule && preg_match('/FREQ=WEEKLY.*BYDAY(\d+)/i', $object->recurrule, $reg)) { - $selectedrecurrulebyday = $reg[1]; - } print $form->selectarray('recurrulefreq', $arrayrecurrulefreq, $selectedrecurrulefreq, 0, 0, 0, '', 0, 0, 0, '', 'marginrightonly'); - // If recurrulefreq is MONTHLY - print ''; - // If recurrulefreq is WEEKLY - print ''; - //print ''; - } + // // Recurring event + // $userepeatevent = ($conf->global->MAIN_FEATURES_LEVEL == 2 ? 1 : 0); + // if ($userepeatevent) { + // // Repeat + // //print ''; + // } print ''; // Date start - end diff --git a/htdocs/langs/en_US/agenda.lang b/htdocs/langs/en_US/agenda.lang index 272ec22df5c..410537acbc1 100644 --- a/htdocs/langs/en_US/agenda.lang +++ b/htdocs/langs/en_US/agenda.lang @@ -135,7 +135,7 @@ AgendaUrlOptionsNotAdmin=logina=!%s to restrict output to actions not own AgendaUrlOptions4=logint=%s to restrict output to actions assigned to user %s (owner and others). AgendaUrlOptionsProject=project=__PROJECT_ID__ to restrict output to actions linked to project __PROJECT_ID__. AgendaUrlOptionsNotAutoEvent=notactiontype=systemauto to exclude automatic events. -AgendaUrlOptionsIncludeHolidays=includeholidays=1 to include events of holidays. +AgendaUrlOptionsIncludeHolidays=includeholidays=1 to include events of holidays. AgendaShowBirthdayEvents=Birthdays of contacts AgendaHideBirthdayEvents=Hide birthdays of contacts Busy=Busy @@ -159,6 +159,7 @@ DateActionBegin=Start event date ConfirmCloneEvent=Are you sure you want to clone the event %s? RepeatEvent=Repeat event OnceOnly=Once only +EveryDay=Every day EveryWeek=Every week EveryMonth=Every month DayOfMonth=Day of month @@ -174,3 +175,4 @@ AddReminder=Create an automatic reminder notification for this event ErrorReminderActionCommCreation=Error creating the reminder notification for this event BrowserPush=Browser Popup Notification ActiveByDefault=Enabled by default +Until=until \ No newline at end of file diff --git a/htdocs/langs/fr_FR/agenda.lang b/htdocs/langs/fr_FR/agenda.lang index 65e06587e88..a589163dfad 100644 --- a/htdocs/langs/fr_FR/agenda.lang +++ b/htdocs/langs/fr_FR/agenda.lang @@ -96,7 +96,7 @@ PRODUCT_MODIFYInDolibarr=Produit %s modifié PRODUCT_DELETEInDolibarr=Produit%ssupprimé HOLIDAY_CREATEInDolibarr=Demande de congé %s créée HOLIDAY_MODIFYInDolibarr=Demande de congé %s modifiée -HOLIDAY_APPROVEInDolibarr=Demande de congé %s approuvée +HOLIDAY_APPROVEInDolibarr=Demande de congé %s approuvée HOLIDAY_VALIDATEInDolibarr=Demande de congé %s validée HOLIDAY_DELETEInDolibarr=Demande de congé %s supprimée EXPENSE_REPORT_CREATEInDolibarr=Note de frais %s créée @@ -157,6 +157,7 @@ DateActionBegin=Date début événément ConfirmCloneEvent=Êtes-vous sûr de vouloir cloner cet événement %s ? RepeatEvent=Evénement répétitif OnceOnly=Une seule fois +EveryDay=Chaque jour EveryWeek=Chaque semaine EveryMonth=Chaque mois DayOfMonth=Jour du mois @@ -172,3 +173,4 @@ AddReminder=Créer une notification de rappel automatique pour cet événement ErrorReminderActionCommCreation=Erreur lors de la création de la notification de rappel pour cet événement BrowserPush=Notification par Popup navigateur ActiveByDefault=Activé par défaut +Until=jusqu'à From a6fd9203fa42631abd0e867c3693868c4a77ffcc Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Sun, 3 Jul 2022 00:26:01 +0200 Subject: [PATCH 131/826] on going --- htdocs/projet/tasks/time.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index ab93e3561b0..b237afcb5b1 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -73,6 +73,7 @@ $search_task_ref = GETPOST('search_task_ref', 'alpha'); $search_task_label = GETPOST('search_task_label', 'alpha'); $search_user = GETPOST('search_user', 'int'); $search_valuebilled = GETPOST('search_valuebilled', 'int'); +$search_thirdparty = GETPOST('search_thirdparty', 'alpha'); $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; $sortfield = GETPOST('sortfield', 'aZ09comma'); @@ -164,6 +165,7 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x' $search_task_label = ''; $search_user = 0; $search_valuebilled = ''; + $search_thirdparty = ''; $toselect = array(); $search_array_options = array(); $action = ''; @@ -1071,6 +1073,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser // Definition of fields for list $arrayfields = array(); $arrayfields['t.task_date'] = array('label'=>$langs->trans("Date"), 'checked'=>1); + $arrayfields['p.fk_soc'] = array('label'=>$langs->trans("Thirdparty"), 'type'=>'integer:Societe:/societe/class/societe.class.php:1','checked'=>1); if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task $arrayfields['t.task_ref'] = array('label'=>$langs->trans("RefTask"), 'checked'=>1); $arrayfields['t.task_label'] = array('label'=>$langs->trans("LabelTask"), 'checked'=>1); @@ -1113,6 +1116,9 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser if ($search_duration != '') { $param .= '&search_field2='.urlencode($search_duration); } + if ($search_thirdparty != '') { + $param .= '&search_thirdparty='.urlencode($search_thirdparty); + } if ($optioncss != '') { $param .= '&optioncss='.urlencode($optioncss); } @@ -1624,6 +1630,9 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser if (!empty($arrayfields['t.task_date']['checked'])) { print_liste_field_titre($arrayfields['t.task_date']['label'], $_SERVER['PHP_SELF'], 't.task_date,t.task_datehour,t.rowid', '', $param, '', $sortfield, $sortorder); } + if (!empty($arrayfields['p.fk_soc']['checked'])) { + print_liste_field_titre($arrayfields['p.fk_soc']['label'], $_SERVER['PHP_SELF'], 't.task_date,t.task_datehour,t.rowid', '', $param, '', $sortfield, $sortorder); + } if (!empty($allprojectforuser)) { print_liste_field_titre("Project", $_SERVER['PHP_SELF'], '', '', $param, '', $sortfield, $sortorder); } @@ -1714,6 +1723,9 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser } } + if (!empty($arrayfields['p.fk_soc']['checked'])) { + } + // Task ref if (!empty($arrayfields['t.task_ref']['checked'])) { if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task From 1216294667035a9cef4fc04ced7b985c373816fb Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Sun, 3 Jul 2022 13:02:42 +0200 Subject: [PATCH 132/826] new: Add thirdparty column to task time list --- htdocs/projet/tasks/time.php | 52 +++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index b237afcb5b1..e674246b6a9 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -38,7 +38,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formintervention.class.php'; // Load translation files required by the page -$langsLoad=array('projects', 'bills', 'orders'); +$langsLoad=array('projects', 'bills', 'orders', 'companies'); if (!empty($conf->eventorganization->enabled)) { $langsLoad[]='eventorganization'; } @@ -73,7 +73,7 @@ $search_task_ref = GETPOST('search_task_ref', 'alpha'); $search_task_label = GETPOST('search_task_label', 'alpha'); $search_user = GETPOST('search_user', 'int'); $search_valuebilled = GETPOST('search_valuebilled', 'int'); -$search_thirdparty = GETPOST('search_thirdparty', 'alpha'); +$search_company = GETPOST('$search_company', 'alpha'); $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; $sortfield = GETPOST('sortfield', 'aZ09comma'); @@ -162,10 +162,10 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x' $search_date_creation = ''; $search_date_update = ''; $search_task_ref = ''; + $search_company = ''; $search_task_label = ''; $search_user = 0; $search_valuebilled = ''; - $search_thirdparty = ''; $toselect = array(); $search_array_options = array(); $action = ''; @@ -1073,7 +1073,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser // Definition of fields for list $arrayfields = array(); $arrayfields['t.task_date'] = array('label'=>$langs->trans("Date"), 'checked'=>1); - $arrayfields['p.fk_soc'] = array('label'=>$langs->trans("Thirdparty"), 'type'=>'integer:Societe:/societe/class/societe.class.php:1','checked'=>1); + $arrayfields['p.fk_soc'] = array('label'=>$langs->trans("ThirdParty"), 'type'=>'integer:Societe:/societe/class/societe.class.php:1','checked'=>1); if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task $arrayfields['t.task_ref'] = array('label'=>$langs->trans("RefTask"), 'checked'=>1); $arrayfields['t.task_label'] = array('label'=>$langs->trans("LabelTask"), 'checked'=>1); @@ -1107,6 +1107,9 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser if ($search_task_ref != '') { $param .= '&search_task_ref='.urlencode($search_task_ref); } + if ($search_company != '') { + $param .= '&$search_company='.urlencode($search_company); + } if ($search_task_label != '') { $param .= '&search_task_label='.urlencode($search_task_label); } @@ -1116,9 +1119,6 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser if ($search_duration != '') { $param .= '&search_field2='.urlencode($search_duration); } - if ($search_thirdparty != '') { - $param .= '&search_thirdparty='.urlencode($search_thirdparty); - } if ($optioncss != '') { $param .= '&optioncss='.urlencode($optioncss); } @@ -1310,6 +1310,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser $sql .= " pt.ref, pt.label, pt.fk_projet,"; $sql .= " u.lastname, u.firstname, u.login, u.photo, u.statut as user_status,"; $sql .= " il.fk_facture as invoice_id, inv.fk_statut,"; + $sql .= " p.fk_soc,"; // Add fields from hooks $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object); // Note that $action and $object may have been modified by hook @@ -1318,13 +1319,16 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser $sql .= " FROM ".MAIN_DB_PREFIX."projet_task_time as t"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facturedet as il ON il.rowid = t.invoice_line_id"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facture as inv ON inv.rowid = il.fk_facture"; + $sql .= " INNER JOIN ".MAIN_DB_PREFIX."projet_task as pt ON pt.rowid = t.fk_task"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u ON t.fk_user = u.rowid"; + $sql .= " INNER JOIN ".MAIN_DB_PREFIX."projet as p ON p.rowid = pt.fk_projet"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = p.fk_soc"; + // Add table from hooks $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; - $sql .= ", ".MAIN_DB_PREFIX."projet_task as pt, ".MAIN_DB_PREFIX."user as u"; - $sql .= " WHERE t.fk_user = u.rowid AND t.fk_task = pt.rowid"; - + $sql .= " WHERE 1 = 1 "; if (empty($projectidforalltimes) && empty($allprojectforuser)) { // Limit on one task $sql .= " AND t.fk_task =".((int) $object->id); @@ -1345,6 +1349,9 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser if ($search_task_ref) { $sql .= natural_search('pt.ref', $search_task_ref); } + if ($search_company) { + $sql .= natural_search('s.nom', $search_company); + } if ($search_task_label) { $sql .= natural_search('pt.label', $search_task_label); } @@ -1578,6 +1585,11 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser print $formother->selectyear($search_year, 'search_year', 1, 20, 5); print ''; } + // Thirdparty + if (!empty($arrayfields['p.fk_soc']['checked'])) { + print ''; + } + if (!empty($allprojectforuser)) { print ''; } @@ -1706,6 +1718,23 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser } } + // Thirdparty + if (!empty($arrayfields['p.fk_soc']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Project ref if (!empty($allprojectforuser)) { print ''; print ''; + print ''; + + print ''; + print ''; - print ''; - - print ''; - print '
'.$langs->trans("VoteAllowed").''.$langs->trans("NewSubscription").'
'; $displayedamount = max(intval($objp->amount), intval($conf->global->MEMBER_MIN_AMOUNT)); $caneditamount = !empty($conf->global->MEMBER_NEWFORM_EDITAMOUNT) || $objp->caneditamount; - if($objp->subscription) { + if ($objp->subscription) { print $displayedamount.' '.strtoupper($conf->currency); if ($caneditamount && $displayedamount>0) { print $form->textwithpicto('', $langs->transnoentities("CanEditAmountShortForValues"), 1, 'help', '', 0, 3); - } - elseif ($caneditamount) { + } elseif ($caneditamount) { print $langs->transnoentities("CanEditAmountShort"); } - } - else { + } else { print "–"; // No subscription required } print '
'; + print ''; + print '
'; + if ($userstatic->id) { + print $userstatic->getNomUrl(-1); + } else { + print ' '; + } + print "
'; + // print '        
'; + // print img_picto($langs->trans("Recurrence"), 'recurring', 'class="paddingright2"'); + // print ''; + // $selectedrecurrulefreq = 'no'; + // $selectedrecurrulebymonthday = ''; + // $selectedrecurrulebyday = ''; + // if ($object->recurrule && preg_match('/FREQ=([A-Z]+)/i', $object->recurrule, $reg)) { + // $selectedrecurrulefreq = $reg[1]; + // } + // if ($object->recurrule && preg_match('/FREQ=MONTHLY.*BYMONTHDAY=(\d+)/i', $object->recurrule, $reg)) { + // $selectedrecurrulebymonthday = $reg[1]; + // } + // if ($object->recurrule && preg_match('/FREQ=WEEKLY.*BYDAY(\d+)/i', $object->recurrule, $reg)) { + // $selectedrecurrulebyday = $reg[1]; + // } + // print $form->selectarray('recurrulefreq', $arrayrecurrulefreq, $selectedrecurrulefreq, 0, 0, 0, '', 0, 0, 0, '', 'marginrightonly'); + // // If recurrulefreq is MONTHLY + // print ''; + // // If recurrulefreq is WEEKLY + // print ''; + // print ''; + // print '
'; + // //print '
'; + if (empty($conf->cache['thridparty'][$task_time->fk_soc])) { + $tmpsociete = new Societe($db); + $tmpsociete->fetch($task_time->fk_soc); + $conf->cache['thridparty'][$task_time->fk_soc] = $tmpsociete; + } else { + $tmpsociete = $conf->cache['thridparty'][$task_time->fk_soc]; + } + print $tmpsociete->getNomUrl(1); + print ''; @@ -1723,9 +1752,6 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser } } - if (!empty($arrayfields['p.fk_soc']['checked'])) { - } - // Task ref if (!empty($arrayfields['t.task_ref']['checked'])) { if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task From eab3541ca56dad38d24078d6167295fb02ab81b4 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Sun, 3 Jul 2022 13:07:25 +0200 Subject: [PATCH 133/826] better sql request --- htdocs/projet/tasks/time.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index e674246b6a9..801e0cb0a00 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -1320,7 +1320,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facturedet as il ON il.rowid = t.invoice_line_id"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facture as inv ON inv.rowid = il.fk_facture"; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."projet_task as pt ON pt.rowid = t.fk_task"; - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u ON t.fk_user = u.rowid"; + $sql .= " INNER JOIN ".MAIN_DB_PREFIX."user as u ON t.fk_user = u.rowid"; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."projet as p ON p.rowid = pt.fk_projet"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = p.fk_soc"; From f105883b4fe603c8ff4bf1b5b6cec72d2d113d29 Mon Sep 17 00:00:00 2001 From: BB2A Anthony Berton Date: Mon, 4 Jul 2022 10:01:17 +0200 Subject: [PATCH 134/826] FIX - php V8 user class --- htdocs/user/class/user.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index b47781a9db4..ee6d0e7bd14 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -3796,7 +3796,7 @@ class User extends CommonObject foreach ($filter as $key => $value) { if ($key == 't.rowid') { $sqlwhere[] = $key." = ".((int) $value); - } elseif (in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { + } elseif (isset($this->fields[$key]['type']) && in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { $sqlwhere[] = $key." = '".$this->db->idate($value)."'"; } elseif ($key == 'customsql') { $sqlwhere[] = $value; From b5c0f1ac29cdd66bb20ab92ff96e5e9192d70a6e Mon Sep 17 00:00:00 2001 From: bagtaib Date: Mon, 4 Jul 2022 14:32:40 +0200 Subject: [PATCH 135/826] corrected the url of the image --- htdocs/core/lib/xcal.lib.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/htdocs/core/lib/xcal.lib.php b/htdocs/core/lib/xcal.lib.php index cd300546e46..6b5c92881c5 100644 --- a/htdocs/core/lib/xcal.lib.php +++ b/htdocs/core/lib/xcal.lib.php @@ -377,8 +377,7 @@ function build_rssfile($format, $title, $desc, $events_array, $outputfile, $filt $tmpevent['author'] = $event->author_alias ? $event->author_alias : 'unknown'; //$tmpevent['category'] = ''; $tmpevent['desc'] = $event->description; - $tmpevent['image'] = $event->image; - + $tmpevent['image'] = $GLOBALS['website']->virtualhost.'/medias/'.$event->image; $event = $tmpevent; } From eab2865765b3e5bc3d5037c98a85d6d850f659bf Mon Sep 17 00:00:00 2001 From: lvessiller Date: Tue, 5 Jul 2022 11:39:49 +0200 Subject: [PATCH 136/826] NEW substitue project title in mail template --- htdocs/core/lib/functions.lib.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index df4fe39bcfd..63bacdc1085 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -7298,6 +7298,7 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, if ($onlykey) { $substitutionarray['__ID__'] = '__ID__'; $substitutionarray['__REF__'] = '__REF__'; + $substitutionarray['__NAME__'] = '__NAME__'; $substitutionarray['__NEWREF__'] = '__NEWREF__'; $substitutionarray['__REF_CLIENT__'] = '__REF_CLIENT__'; $substitutionarray['__REF_SUPPLIER__'] = '__REF_SUPPLIER__'; @@ -7392,6 +7393,7 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, } else { $substitutionarray['__ID__'] = $object->id; $substitutionarray['__REF__'] = $object->ref; + $substitutionarray['__NAME__'] = $object->title; $substitutionarray['__NEWREF__'] = $object->newref; $substitutionarray['__REF_CLIENT__'] = (isset($object->ref_client) ? $object->ref_client : (isset($object->ref_customer) ? $object->ref_customer : null)); $substitutionarray['__REF_SUPPLIER__'] = (isset($object->ref_supplier) ? $object->ref_supplier : null); From 51de3d195cfaa79249af30f87fa3ed4503adf669 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 5 Jul 2022 14:02:47 +0200 Subject: [PATCH 137/826] css --- htdocs/compta/facture/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index a886f8a49c8..28597b90247 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -4182,7 +4182,7 @@ if ($action == 'create') { // Cree un tableau formulaire $formquestion = array('text' => $langs->trans("ConfirmClassifyPaidPartiallyQuestion"), array('type' => 'radio', 'name' => 'close_code', 'label' => $langs->trans("Reason"), 'values' => $arrayreasons), array('type' => 'text', 'name' => 'close_note', 'label' => $langs->trans("Comment"), 'value' => '', 'morecss' => 'minwidth300')); // Paiement incomplet. On demande si motif = escompte ou autre - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?facid='.$object->id, $langs->trans('ClassifyPaid'), $langs->trans('ConfirmClassifyPaidPartially', $object->ref), 'confirm_paid_partially', $formquestion, "yes", 1, 310); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?facid='.$object->id, $langs->trans('ClassifyPaid'), $langs->trans('ConfirmClassifyPaidPartially', $object->ref), 'confirm_paid_partially', $formquestion, "yes", 1, 340, 600); } // Confirmation du classement abandonne From 7e855eac52e9415c2bbe80155c1725b197457423 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 5 Jul 2022 20:22:32 +0200 Subject: [PATCH 138/826] Add field close_missing_amount on invoices --- .../install/mysql/migration/16.0.0-17.0.0.sql | 45 +++++++++++++++++++ htdocs/install/mysql/tables/llx_facture.sql | 1 + .../mysql/tables/llx_facture_fourn.sql | 1 + 3 files changed, 47 insertions(+) create mode 100644 htdocs/install/mysql/migration/16.0.0-17.0.0.sql diff --git a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql new file mode 100644 index 00000000000..dad3712d3f3 --- /dev/null +++ b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql @@ -0,0 +1,45 @@ +-- +-- Be carefull to requests order. +-- This file must be loaded by calling /install/index.php page +-- when current version is 16.0.0 or higher. +-- +-- To restrict request to Mysql version x.y minimum use -- VMYSQLx.y +-- To restrict request to Pgsql version x.y minimum use -- VPGSQLx.y +-- To rename a table: ALTER TABLE llx_table RENAME TO llx_table_new; +-- To add a column: ALTER TABLE llx_table ADD COLUMN newcol varchar(60) NOT NULL DEFAULT '0' AFTER existingcol; +-- To rename a column: ALTER TABLE llx_table CHANGE COLUMN oldname newname varchar(60); +-- To drop a column: ALTER TABLE llx_table DROP COLUMN oldname; +-- To change type of field: ALTER TABLE llx_table MODIFY COLUMN name varchar(60); +-- To drop a foreign key: ALTER TABLE llx_table DROP FOREIGN KEY fk_name; +-- To create a unique index ALTER TABLE llx_table ADD UNIQUE INDEX uk_table_field (field); +-- To drop an index: -- VMYSQL4.1 DROP INDEX nomindex on llx_table; +-- To drop an index: -- VPGSQL8.2 DROP INDEX nomindex; +-- To make pk to be auto increment (mysql): +-- -- VMYSQL4.3 ALTER TABLE llx_table ADD PRIMARY KEY(rowid); +-- -- VMYSQL4.3 ALTER TABLE llx_table CHANGE COLUMN rowid rowid INTEGER NOT NULL AUTO_INCREMENT; +-- To make pk to be auto increment (postgres): +-- -- VPGSQL8.2 CREATE SEQUENCE llx_table_rowid_seq OWNED BY llx_table.rowid; +-- -- VPGSQL8.2 ALTER TABLE llx_table ADD PRIMARY KEY (rowid); +-- -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN rowid SET DEFAULT nextval('llx_table_rowid_seq'); +-- -- VPGSQL8.2 SELECT setval('llx_table_rowid_seq', MAX(rowid)) FROM llx_table; +-- To set a field as NULL: -- VMYSQL4.3 ALTER TABLE llx_table MODIFY COLUMN name varchar(60) NULL; +-- To set a field as NULL: -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN name DROP NOT NULL; +-- To set a field as NOT NULL: -- VMYSQL4.3 ALTER TABLE llx_table MODIFY COLUMN name varchar(60) NOT NULL; +-- To set a field as NOT NULL: -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN name SET NOT NULL; +-- To set a field as default NULL: -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN name SET DEFAULT NULL; +-- Note: fields with type BLOB/TEXT can't have default value. +-- To rebuild sequence for postgresql after insert by forcing id autoincrement fields: +-- -- VPGSQL8.2 SELECT dol_util_rebuild_sequences(); + + + +-- Missing in v16 or lower + + + + +-- v17 + +ALTER TABLE llx_facture ADD COLUMN close_missing_amount double(24, 8) after close_code; + +ALTER TABLE llx_facture_fourn ADD COLUMN close_missing_amount double(24, 8) after close_code; diff --git a/htdocs/install/mysql/tables/llx_facture.sql b/htdocs/install/mysql/tables/llx_facture.sql index 8c7e2db385c..3e8ac2b7a50 100644 --- a/htdocs/install/mysql/tables/llx_facture.sql +++ b/htdocs/install/mysql/tables/llx_facture.sql @@ -48,6 +48,7 @@ create table llx_facture remise real DEFAULT 0, -- remise totale calculee close_code varchar(16), -- Code motif cloture sans paiement complet + close_missing_amount double(24,8), -- Amount missing when closing with a not complete payment close_note varchar(128), -- Commentaire cloture sans paiement complet total_tva double(24,8) DEFAULT 0, -- amount total tva apres remise totale diff --git a/htdocs/install/mysql/tables/llx_facture_fourn.sql b/htdocs/install/mysql/tables/llx_facture_fourn.sql index 9ceff4e4fa9..3a304567beb 100644 --- a/htdocs/install/mysql/tables/llx_facture_fourn.sql +++ b/htdocs/install/mysql/tables/llx_facture_fourn.sql @@ -44,6 +44,7 @@ create table llx_facture_fourn remise double(24,8) DEFAULT 0, close_code varchar(16), -- Code motif cloture sans paiement complet + close_missing_amount double(24,8), -- Amount missing when closing with a not complete payment close_note varchar(128), -- Commentaire cloture sans paiement complet tva double(24,8) DEFAULT 0, From 59816ce171da8dac8a6f018d898168b4d27517dc Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 6 Jul 2022 03:08:30 +0200 Subject: [PATCH 139/826] Fix scrutinizer --- htdocs/fourn/class/fournisseur.facture.class.php | 2 +- htdocs/supplier_proposal/class/supplier_proposal.class.php | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/htdocs/fourn/class/fournisseur.facture.class.php b/htdocs/fourn/class/fournisseur.facture.class.php index df10ed07632..5c6db6ce34d 100644 --- a/htdocs/fourn/class/fournisseur.facture.class.php +++ b/htdocs/fourn/class/fournisseur.facture.class.php @@ -3060,7 +3060,7 @@ class FactureFournisseur extends CommonInvoice // Clear fields $object->ref_supplier = (empty($this->ref_supplier) ? $langs->trans("CopyOf").' '.$object->ref_supplier : $this->ref_supplier); $object->author = $user->id; - $object->user_valid = ''; + $object->user_valid = 0; $object->fk_facture_source = 0; $object->date_creation = ''; $object->date_validation = ''; diff --git a/htdocs/supplier_proposal/class/supplier_proposal.class.php b/htdocs/supplier_proposal/class/supplier_proposal.class.php index 8f0c1d36919..794a4542f10 100644 --- a/htdocs/supplier_proposal/class/supplier_proposal.class.php +++ b/htdocs/supplier_proposal/class/supplier_proposal.class.php @@ -1149,8 +1149,10 @@ class SupplierProposal extends CommonObject } // Clear fields - $this->user_author = $user->id; - $this->user_valid = ''; + $this->user_author = $user->id; // deprecated + $this->user_author_id = $user->id; + $this->user_valid = 0; // deprecated + $this->user_valid_id = 0; $this->date = $now; // Set ref From 22d35c6d0b103f8fbe3a74c2b4fbc9a87fec9732 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 6 Jul 2022 03:16:08 +0200 Subject: [PATCH 140/826] Fix scrutinizer --- htdocs/core/db/mysqli.class.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/core/db/mysqli.class.php b/htdocs/core/db/mysqli.class.php index 593a9454b6f..a392e374d0b 100644 --- a/htdocs/core/db/mysqli.class.php +++ b/htdocs/core/db/mysqli.class.php @@ -757,6 +757,9 @@ class DoliDBMysqli extends DoliDB // phpcs:enable // FIXME: $fulltext_keys parameter is unused + $pk = ''; + $sqluq = $sqlk = array(); + // cles recherchees dans le tableau des descriptions (fields) : type,value,attribute,null,default,extra // ex. : $fields['rowid'] = array('type'=>'int','value'=>'11','null'=>'not null','extra'=> 'auto_increment'); $sql = "CREATE TABLE ".$table."("; From 1d3181ea9f8021685f0c7a683e7f49cfd9b683fe Mon Sep 17 00:00:00 2001 From: bagtaib Date: Wed, 6 Jul 2022 05:50:53 +0200 Subject: [PATCH 141/826] affichage --- htdocs/modulebuilder/index.php | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index fd84cb5e4dd..ac0ed014699 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -2074,11 +2074,34 @@ if ($module == 'initmodule') { print ''; print ''; - //print ''.$langs->trans("ModuleBuilderDesc2", 'conf/conf.php', $newdircustom).'
'; - print $langs->trans("EnterNameOfModuleDesc").'
'; + //print ''.$langs->trans("ModuleBuilderDesc2", 'conf/conf.php', $newdircustom).'
'; print '
'; - print '
'; + print ''; + print ' '.$form->textwithpicto('', $langs->trans("EnterNameOfModuleDesc")).'
'; + + + + print '
'; + print '
'; + print '
'; + print '
'; + //print '
'; + print $langs->trans("Family").'
'; + print '
'; print '
'; print ''; From 377e079a6efd7219dbdb23506d7480167a9786e3 Mon Sep 17 00:00:00 2001 From: bagtaib Date: Wed, 6 Jul 2022 07:56:42 +0200 Subject: [PATCH 142/826] backend --- htdocs/langs/en_US/modulebuilder.lang | 1 + htdocs/modulebuilder/index.php | 55 +++++++++++-------- .../core/modules/modMyModule.class.php | 4 +- 3 files changed, 36 insertions(+), 24 deletions(-) diff --git a/htdocs/langs/en_US/modulebuilder.lang b/htdocs/langs/en_US/modulebuilder.lang index b17ab4fdeb2..792070e3d43 100644 --- a/htdocs/langs/en_US/modulebuilder.lang +++ b/htdocs/langs/en_US/modulebuilder.lang @@ -1,4 +1,5 @@ # Dolibarr language file - Source file is en_US - loan +IdModule= Module id ModuleBuilderDesc=This tool must be used only by experienced users or developers. It provides utilities to build or edit your own module. Documentation for alternative manual development is here. EnterNameOfModuleDesc=Enter the name of the module/application to create with no spaces. Use uppercase to separate words (For example: MyModule, EcommerceForShop, SyncWithMySystem...) EnterNameOfObjectDesc=Enter the name of the object to create with no spaces. Use uppercase to separate words (For example: MyObject, Student, Teacher...). The CRUD class file, but also API file, pages to list/add/edit/delete object and SQL files will be generated. diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index ac0ed014699..b6bcf74cc9e 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -71,6 +71,12 @@ $file = GETPOST('file', 'alpha'); $modulename = dol_sanitizeFileName(GETPOST('modulename', 'alpha')); $objectname = dol_sanitizeFileName(GETPOST('objectname', 'alpha')); $dicname = dol_sanitizeFileName(GETPOST('dicname', 'alpha')); +$editorname= GETPOST('editorname', 'alpha'); +$editorurl= GETPOST('editorurl', 'alpha'); +$version= GETPOST('version', 'alpha'); +$family= GETPOST('family', 'alpha'); +$picto= GETPOST('idpicto', 'alpha'); +$idmodule= GETPOST('idmodule', 'alpha'); // Security check if (!isModEnabled('modulebuilder')) { @@ -334,7 +340,13 @@ if ($dirins && $action == 'initmodule' && $modulename) { 'Mon module'=>$modulename, 'mon module'=>$modulename, 'htdocs/modulebuilder/template'=>strtolower($modulename), - '---Put here your own copyright and developer email---'=>dol_print_date($now, '%Y').' '.$user->getFullName($langs).($user->email ? ' <'.$user->email.'>' : '') + '---Put here your own copyright and developer email---'=>dol_print_date($now, '%Y').' '.$user->getFullName($langs).($user->email ? ' <'.$user->email.'>' : ''), + 'Editor name'=>$editorname, + 'https://www.example.com'=>$editorurl, + '1.0'=>$version, + 'idpicto'=>$picto, + "modulefamily" =>$family, + 500000=>$idmodule ); if (!empty($conf->global->MODULEBUILDER_SPECIFIC_EDITOR_NAME)) { @@ -350,7 +362,7 @@ if ($dirins && $action == 'initmodule' && $modulename) { $arrayreplacement['1.0'] = $conf->global->MODULEBUILDER_SPECIFIC_VERSION; } if (!empty($conf->global->MODULEBUILDER_SPECIFIC_FAMILY)) { - $arrayreplacement['other'] = $conf->global->MODULEBUILDER_SPECIFIC_FAMILY; + $arrayreplacement['modulefamily'] = $conf->global->MODULEBUILDER_SPECIFIC_FAMILY; } $result = dolReplaceInFile($phpfileval['fullname'], $arrayreplacement); @@ -2074,34 +2086,33 @@ if ($module == 'initmodule') { print ''; print ''; - //print ''.$langs->trans("ModuleBuilderDesc2", 'conf/conf.php', $newdircustom).'
'; + //print ''.$langs->trans("ModuleBuilderDesc2", 'conf/conf.php', $newdircustom).'
'; print '
'; print ''; print ' '.$form->textwithpicto('', $langs->trans("EnterNameOfModuleDesc")).'
'; - - print '
'; - print '
'; - print '
'; - print '
'; - //print '
'; - print $langs->trans("Family").'
'; + print '
'; + print '
'; + print '
'; + print $langs->trans("Family").'
'; - print '
'; + print '
'; print '
'; print ''; diff --git a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php index 8ea8a575eca..0c99c0fb46d 100644 --- a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php +++ b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php @@ -52,7 +52,7 @@ class modMyModule extends DolibarrModules // Family can be 'base' (core modules),'crm','financial','hr','projects','products','ecm','technic' (transverse modules),'interface' (link with external tools),'other','...' // It is used to group modules by family in module setup page - $this->family = "other"; + $this->family = "modulefamily"; // Module position in the family on 2 digits ('01', '10', '20', ...) $this->module_position = '90'; @@ -83,7 +83,7 @@ class modMyModule extends DolibarrModules // If file is in theme/yourtheme/img directory under name object_pictovalue.png, use this->picto='pictovalue' // If file is in module/img directory under name object_pictovalue.png, use this->picto='pictovalue@module' // To use a supported fa-xxx css style of font awesome, use this->picto='xxx' - $this->picto = 'generic'; + $this->picto = 'idpicto'; // Define some features supported by module (triggers, login, substitutions, menus, css, etc...) $this->module_parts = array( From 696a832ef731996a712c88c5439f032a5376f5e4 Mon Sep 17 00:00:00 2001 From: bagtaib Date: Wed, 6 Jul 2022 10:16:03 +0200 Subject: [PATCH 143/826] add default value for picto --- htdocs/modulebuilder/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index b6bcf74cc9e..3416c1c69b8 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -344,7 +344,7 @@ if ($dirins && $action == 'initmodule' && $modulename) { 'Editor name'=>$editorname, 'https://www.example.com'=>$editorurl, '1.0'=>$version, - 'idpicto'=>$picto, + 'idpicto'=>(empty($picto)) ? 'generic' : $picto, "modulefamily" =>$family, 500000=>$idmodule ); From ae16c278a0da883bc7192dc25e72f8ca5ae0addb Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 6 Jul 2022 15:00:50 +0200 Subject: [PATCH 144/826] Update modMyModule.class.php --- .../modulebuilder/template/core/modules/modMyModule.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php index 0c99c0fb46d..8ea8a575eca 100644 --- a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php +++ b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php @@ -52,7 +52,7 @@ class modMyModule extends DolibarrModules // Family can be 'base' (core modules),'crm','financial','hr','projects','products','ecm','technic' (transverse modules),'interface' (link with external tools),'other','...' // It is used to group modules by family in module setup page - $this->family = "modulefamily"; + $this->family = "other"; // Module position in the family on 2 digits ('01', '10', '20', ...) $this->module_position = '90'; @@ -83,7 +83,7 @@ class modMyModule extends DolibarrModules // If file is in theme/yourtheme/img directory under name object_pictovalue.png, use this->picto='pictovalue' // If file is in module/img directory under name object_pictovalue.png, use this->picto='pictovalue@module' // To use a supported fa-xxx css style of font awesome, use this->picto='xxx' - $this->picto = 'idpicto'; + $this->picto = 'generic'; // Define some features supported by module (triggers, login, substitutions, menus, css, etc...) $this->module_parts = array( From 745f504a2736c1296ce51e76a603d215db483eca Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 6 Jul 2022 15:30:36 +0200 Subject: [PATCH 145/826] Clean init process --- htdocs/langs/en_US/modulebuilder.lang | 1 + htdocs/modulebuilder/index.php | 55 ++++++++++++++++----------- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/htdocs/langs/en_US/modulebuilder.lang b/htdocs/langs/en_US/modulebuilder.lang index 792070e3d43..3e029857a10 100644 --- a/htdocs/langs/en_US/modulebuilder.lang +++ b/htdocs/langs/en_US/modulebuilder.lang @@ -10,6 +10,7 @@ ModuleBuilderDesc4=A module is detected as 'editable' when the file %s'.$langs->trans("ModuleBuilderDesc2", 'conf/conf.php', $newdircustom).'
'; print '
'; - print ''; + print ''.$langs->trans("ModuleName").' '; print ' '.$form->textwithpicto('', $langs->trans("EnterNameOfModuleDesc")).'
'; - - - print '
'; - print '
'; - print '
'; - print '
'; - print $langs->trans("Family").' '; + print ''; + print '   ('.$langs->trans("SeeIDsInUse").''; + print ' - '.$langs->trans("SeeReservedIDsRangeHere").')'; + print ''; + print '
'; + print ''.$langs->trans("Version").'
'; + print ''.$langs->trans("Family").' '; + print '
'; - print '
'; + print ajax_combobox("family"); + print ''.$langs->trans("Picto").' '; + print $form->textwithpicto('', $langs->trans("Example").': generic, globe, ... any font awesome code'); + print '
'; + print ''.$langs->trans("Description").'
'; + + print ''.$langs->trans("EditorName").'
'; + print ''.$langs->trans("EditorUrl").'
'; print '
'; print ''; @@ -2277,8 +2286,10 @@ if ($module == 'initmodule') { print $langs->trans("Numero"); print '
'; print $moduleobj->numero; + print ''; print '   ('.$langs->trans("SeeIDsInUse").''; print ' - '.$langs->trans("SeeReservedIDsRangeHere").')'; + print ''; print '
'; @@ -2300,6 +2311,19 @@ if ($module == 'initmodule') { print $moduleobj->family; print '
'; + print $langs->trans("Picto"); + print ''; + print $moduleobj->picto; + print '   '.img_picto('', $moduleobj->picto, 'class="valignmiddle pictomodule paddingrightonly"'); + print '
'; + print $langs->trans("Description"); + print ''; + print $moduleobj->getDesc(); + print '
'; print $langs->trans("EditorName"); print ''; @@ -2314,19 +2338,6 @@ if ($module == 'initmodule') { } print '
'; - print $langs->trans("Picto"); - print ''; - print $moduleobj->picto; - print '   '.img_picto('', $moduleobj->picto, 'class="valignmiddle pictomodule paddingrightonly"'); - print '
'; - print $langs->trans("Description"); - print ''; - print $moduleobj->getDesc(); - print '
'; } else { print $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module).'
'; From 4c5e05e4110a11eb9dff2952af481c73762a40fc Mon Sep 17 00:00:00 2001 From: Christian Foellmann Date: Mon, 27 Jun 2022 12:46:39 +0200 Subject: [PATCH 146/826] fix page titles Conflicts: htdocs/compta/bank/annuel.php htdocs/contact/list.php htdocs/product/stock/movement_list.php htdocs/user/list.php --- htdocs/comm/propal/card.php | 6 +++++- htdocs/comm/propal/contact.php | 3 ++- htdocs/comm/propal/document.php | 2 +- htdocs/comm/propal/info.php | 2 +- htdocs/comm/propal/list.php | 5 +++-- htdocs/comm/propal/note.php | 3 ++- htdocs/commande/card.php | 6 +++++- htdocs/commande/contact.php | 8 ++++---- htdocs/commande/document.php | 2 +- htdocs/commande/note.php | 2 +- htdocs/compta/bank/annuel.php | 8 ++++---- htdocs/compta/bank/bankentries_list.php | 2 +- htdocs/compta/bank/card.php | 11 ++++++----- htdocs/compta/bank/document.php | 3 +-- htdocs/compta/bank/graph.php | 9 ++++----- htdocs/compta/bank/releve.php | 9 ++++----- htdocs/compta/bank/treso.php | 8 +++----- htdocs/compta/bank/various_payment/card.php | 10 +++++++--- htdocs/compta/bank/various_payment/list.php | 2 +- htdocs/compta/facture/card.php | 6 ++++-- htdocs/compta/facture/contact.php | 2 +- htdocs/compta/facture/document.php | 3 +-- htdocs/compta/facture/info.php | 2 +- htdocs/compta/facture/note.php | 2 +- htdocs/contact/list.php | 3 +-- htdocs/core/lib/usergroups.lib.php | 2 +- htdocs/expedition/card.php | 6 +++++- htdocs/expedition/shipment.php | 2 +- htdocs/fourn/commande/card.php | 5 ++++- htdocs/fourn/commande/contact.php | 8 ++++---- htdocs/fourn/commande/dispatch.php | 3 ++- htdocs/fourn/commande/document.php | 2 +- htdocs/fourn/commande/info.php | 2 +- htdocs/fourn/commande/note.php | 2 +- htdocs/fourn/facture/card.php | 7 +++++-- htdocs/fourn/facture/contact.php | 9 ++++----- htdocs/fourn/facture/document.php | 2 +- htdocs/fourn/facture/info.php | 11 ++++------- htdocs/fourn/facture/note.php | 2 +- htdocs/langs/en_US/suppliers.lang | 1 + htdocs/product/card.php | 17 +++++++++++++---- htdocs/product/list.php | 10 ++++------ htdocs/product/stock/card.php | 7 ++++++- htdocs/product/stock/movement_list.php | 6 +++++- htdocs/projet/card.php | 1 + htdocs/projet/document.php | 2 +- htdocs/projet/info.php | 4 ++-- htdocs/projet/note.php | 2 +- htdocs/projet/tasks.php | 5 ++++- htdocs/projet/tasks/contact.php | 13 +++++++++---- htdocs/projet/tasks/document.php | 9 +++++++-- htdocs/projet/tasks/note.php | 11 ++++++++--- htdocs/projet/tasks/task.php | 14 ++++++++++---- htdocs/projet/tasks/time.php | 15 ++++++++++----- htdocs/societe/card.php | 4 +++- htdocs/societe/list.php | 2 +- htdocs/societe/paymentmodes.php | 2 +- htdocs/supplier_proposal/card.php | 7 +++++-- htdocs/supplier_proposal/contact.php | 8 ++++---- htdocs/supplier_proposal/document.php | 2 +- htdocs/supplier_proposal/info.php | 11 ++++------- htdocs/supplier_proposal/list.php | 6 ++++-- htdocs/supplier_proposal/note.php | 8 ++++---- htdocs/user/agenda_extsites.php | 6 +++++- htdocs/user/bank.php | 5 ++++- htdocs/user/card.php | 10 +++++++++- htdocs/user/clicktodial.php | 8 ++++---- htdocs/user/document.php | 6 +++++- htdocs/user/group/card.php | 7 ++++++- htdocs/user/group/ldap.php | 4 +++- htdocs/user/group/list.php | 4 ++-- htdocs/user/group/perms.php | 4 +++- htdocs/user/home.php | 5 +++-- htdocs/user/info.php | 5 ++++- htdocs/user/ldap.php | 5 ++++- htdocs/user/note.php | 8 +++++--- htdocs/user/param_ihm.php | 5 ++++- htdocs/user/perms.php | 5 ++++- 78 files changed, 274 insertions(+), 162 deletions(-) diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index b8b46a0c8d9..06c36ce517c 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -1526,8 +1526,12 @@ if (!empty($conf->project->enabled)) { $formproject = new FormProjets($db); } -$title = $langs->trans('Proposal')." - ".$langs->trans('Card'); +$title = $object->ref." - ".$langs->trans('Card'); +if ($action == 'create') { + $title = $langs->trans("NewPropal"); +} $help_url = 'EN:Commercial_Proposals|FR:Proposition_commerciale|ES:Presupuestos|DE:Modul_Angebote'; + llxHeader('', $title, $help_url); $now = dol_now(); diff --git a/htdocs/comm/propal/contact.php b/htdocs/comm/propal/contact.php index d9942e9153c..52318684f42 100644 --- a/htdocs/comm/propal/contact.php +++ b/htdocs/comm/propal/contact.php @@ -112,8 +112,9 @@ if ($action == 'addcontact' && $user->rights->propale->creer) { /* * View */ -$title = $langs->trans('Proposal')." - ".$langs->trans('ContactsAddresses'); +$title = $object->ref." - ".$langs->trans('ContactsAddresses'); $help_url = "EN:Commercial_Proposals|FR:Proposition_commerciale|ES:Presupuestos"; + llxHeader('', $title, $help_url); $form = new Form($db); diff --git a/htdocs/comm/propal/document.php b/htdocs/comm/propal/document.php index 31cf2c18f42..35ab2e28b49 100644 --- a/htdocs/comm/propal/document.php +++ b/htdocs/comm/propal/document.php @@ -104,7 +104,7 @@ if ($object->id > 0) { /* * View */ -$title = $langs->trans('Proposal')." - ".$langs->trans('Documents'); +$title = $object->ref." - ".$langs->trans('Documents'); $help_url = 'EN:Commercial_Proposals|FR:Proposition_commerciale|ES:Presupuestos'; llxHeader('', $title, $help_url); diff --git a/htdocs/comm/propal/info.php b/htdocs/comm/propal/info.php index 65ff9c19e2b..92285183cf2 100644 --- a/htdocs/comm/propal/info.php +++ b/htdocs/comm/propal/info.php @@ -59,7 +59,7 @@ restrictedArea($user, 'propal', $object->id); $form = new Form($db); -$title = $langs->trans('Proposal')." - ".$langs->trans('Info'); +$title = $object->ref." - ".$langs->trans('Info'); $help_url = 'EN:Commercial_Proposals|FR:Proposition_commerciale|ES:Presupuestos'; llxHeader('', $title, $help_url); diff --git a/htdocs/comm/propal/list.php b/htdocs/comm/propal/list.php index e490a5ca7ac..ff3957b1382 100644 --- a/htdocs/comm/propal/list.php +++ b/htdocs/comm/propal/list.php @@ -520,8 +520,9 @@ $companystatic = new Societe($db); $projectstatic = new Project($db); $formcompany = new FormCompany($db); +$title = $langs->trans('ListOfProposals'); $help_url = 'EN:Commercial_Proposals|FR:Proposition_commerciale|ES:Presupuestos'; -//llxHeader('',$langs->trans('Proposal'),$help_url); +llxHeader('', $title, $help_url); $sql = 'SELECT'; if ($sall || $search_product_category > 0 || $search_user > 0) { @@ -786,7 +787,7 @@ if ($resql) { exit; } - llxHeader('', $langs->trans('Proposal'), $help_url); +// llxHeader('', $langs->trans('Proposal'), $help_url); $param = '&search_status='.urlencode($search_status); if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { diff --git a/htdocs/comm/propal/note.php b/htdocs/comm/propal/note.php index 7e40552fefb..28819123cb0 100644 --- a/htdocs/comm/propal/note.php +++ b/htdocs/comm/propal/note.php @@ -81,8 +81,9 @@ if (empty($reshook)) { $form = new Form($db); -$title = $langs->trans('Proposal')." - ".$langs->trans('Notes'); +$title = $object->ref." - ".$langs->trans('Notes'); $help_url = 'EN:Commercial_Proposals|FR:Proposition_commerciale|ES:Presupuestos'; + llxHeader('', $title, $help_url); if ($object->id > 0) { diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 22505f6b921..d7d86589dff 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -1484,8 +1484,12 @@ if (empty($reshook)) { * View */ -$title = $langs->trans('Order')." - ".$langs->trans('Card'); +$title = $object->ref." - ".$langs->trans('Card'); +if ($action == 'create') { + $title = $langs->trans("NewOrder"); +} $help_url = 'EN:Customers_Orders|FR:Commandes_Clients|ES:Pedidos de clientes|DE:Modul_Kundenaufträge'; + llxHeader('', $title, $help_url); $form = new Form($db); diff --git a/htdocs/commande/contact.php b/htdocs/commande/contact.php index 5f4de8b59a0..c9ef518d1d0 100644 --- a/htdocs/commande/contact.php +++ b/htdocs/commande/contact.php @@ -96,10 +96,6 @@ if ($action == 'addcontact' && $user->rights->commande->creer) { /* * View */ -$title = $langs->trans('Order')." - ".$langs->trans('ContactsAddresses'); -$help_url = 'EN:Customers_Orders|FR:Commandes_Clients|ES:Pedidos de clientes|DE:Modul_Kundenaufträge'; -llxHeader('', $title, $help_url); - $form = new Form($db); $formcompany = new FormCompany($db); $formother = new FormOther($db); @@ -117,6 +113,10 @@ if ($id > 0 || !empty($ref)) { if ($object->fetch($id, $ref) > 0) { $object->fetch_thirdparty(); + $title = $object->ref." - ".$langs->trans('ContactsAddresses'); + $help_url = 'EN:Customers_Orders|FR:Commandes_Clients|ES:Pedidos de clientes|DE:Modul_Kundenaufträge'; + llxHeader('', $title, $help_url); + $head = commande_prepare_head($object); print dol_get_fiche_head($head, 'contact', $langs->trans("CustomerOrder"), -1, 'order'); diff --git a/htdocs/commande/document.php b/htdocs/commande/document.php index d85400243e7..af04389b8d9 100644 --- a/htdocs/commande/document.php +++ b/htdocs/commande/document.php @@ -96,7 +96,7 @@ include DOL_DOCUMENT_ROOT.'/core/actions_linkedfiles.inc.php'; /* * View */ -$title = $langs->trans('Order')." - ".$langs->trans('Documents'); +$title = $object->ref." - ".$langs->trans('Documents'); $help_url = 'EN:Customers_Orders|FR:Commandes_Clients|ES:Pedidos de clientes|DE:Modul_Kundenaufträge'; llxHeader('', $title, $help_url); diff --git a/htdocs/commande/note.php b/htdocs/commande/note.php index 75d8e587ccb..934299377e5 100644 --- a/htdocs/commande/note.php +++ b/htdocs/commande/note.php @@ -77,7 +77,7 @@ if (empty($reshook)) { /* * View */ -$title = $langs->trans('Order')." - ".$langs->trans('Notes'); +$title = $object->ref." - ".$langs->trans('Notes'); $help_url = 'EN:Customers_Orders|FR:Commandes_Clients|ES:Pedidos de clientes|DE:Modul_Kundenaufträge'; llxHeader('', $title, $help_url); diff --git a/htdocs/compta/bank/annuel.php b/htdocs/compta/bank/annuel.php index 5d6c2045d47..41d58cb35c2 100644 --- a/htdocs/compta/bank/annuel.php +++ b/htdocs/compta/bank/annuel.php @@ -61,10 +61,6 @@ if (!$year_start) { * View */ -$title = $langs->trans("FinancialAccount").' - '.$langs->trans("IOMonthlyReporting"); -$helpurl = ""; -llxHeader('', $title, $helpurl); - $form = new Form($db); // Get account informations @@ -82,6 +78,10 @@ $annee = ''; $totentrees = array(); $totsorties = array(); +$title = $object->ref.' - '.$langs->trans("IOMonthlyReporting"); +$helpurl = ""; +llxHeader('', $title, $helpurl); + // Ce rapport de tresorerie est base sur llx_bank (car doit inclure les transactions sans facture) // plutot que sur llx_paiement + llx_paiementfourn diff --git a/htdocs/compta/bank/bankentries_list.php b/htdocs/compta/bank/bankentries_list.php index fba2d05897c..511d75a12c8 100644 --- a/htdocs/compta/bank/bankentries_list.php +++ b/htdocs/compta/bank/bankentries_list.php @@ -512,7 +512,7 @@ $buttonreconcile = ''; $morehtmlref = ''; if ($id > 0 || !empty($ref)) { - $title = $langs->trans("FinancialAccount").' - '.$langs->trans("Transactions"); + $title = $object->ref.' - '.$langs->trans("Transactions"); $helpurl = ""; llxHeader('', $title, $helpurl); diff --git a/htdocs/compta/bank/card.php b/htdocs/compta/bank/card.php index 29341b0fb99..2751947c023 100644 --- a/htdocs/compta/bank/card.php +++ b/htdocs/compta/bank/card.php @@ -332,18 +332,16 @@ if (!empty($conf->accounting->enabled)) { $countrynotdefined = $langs->trans("ErrorSetACountryFirst").' ('.$langs->trans("SeeAbove").')'; -$title = $langs->trans("FinancialAccount")." - ".$langs->trans("Card"); - $help_url = 'EN:Module_Banks_and_Cash|FR:Module_Banques_et_Caisses|ES:Módulo_Bancos_y_Cajas|DE:Modul_Banken_und_Barbestände'; -llxHeader("", $title, $help_url); - - // Creation if ($action == 'create') { $object = new Account($db); + $title = $langs->trans("NewFinancialAccount"); + llxHeader("", $title, $help_url); + print load_fiche_titre($langs->trans("NewFinancialAccount"), '', 'bank_account'); if ($conf->use_javascript_ajax) { @@ -615,6 +613,9 @@ if ($action == 'create') { $_GET["id"] = $object->id; } + $title = $object->ref." - ".$langs->trans("Card"); + llxHeader("", $title, $help_url); + // Show tabs $head = bank_prepare_head($object); print dol_get_fiche_head($head, 'bankname', $langs->trans("FinancialAccount"), -1, 'account'); diff --git a/htdocs/compta/bank/document.php b/htdocs/compta/bank/document.php index 78d45beadf3..91f514948a6 100644 --- a/htdocs/compta/bank/document.php +++ b/htdocs/compta/bank/document.php @@ -93,8 +93,7 @@ include DOL_DOCUMENT_ROOT.'/core/actions_linkedfiles.inc.php'; * View */ -$title = $langs->trans("FinancialAccount").' - '.$langs->trans("Documents"); - +$title = $object->ref.' - '.$langs->trans("Documents"); $help_url = "EN:Module_Banks_and_Cash|FR:Module_Banques_et_Caisses"; llxHeader("", $title, $help_url); diff --git a/htdocs/compta/bank/graph.php b/htdocs/compta/bank/graph.php index 459134dc68a..c9bc7c649b3 100644 --- a/htdocs/compta/bank/graph.php +++ b/htdocs/compta/bank/graph.php @@ -55,11 +55,6 @@ $error = 0; /* * View */ - -$title = $langs->trans("FinancialAccount").' - '.$langs->trans("Graph"); -$helpurl = ""; -llxHeader('', $title, $helpurl); - $form = new Form($db); $datetime = dol_now(); @@ -83,6 +78,10 @@ if (GETPOST("ref")) { $account = $object->id; } +$title = $object->ref.' - '.$langs->trans("Graph"); +$helpurl = ""; +llxHeader('', $title, $helpurl); + $result = dol_mkdir($conf->bank->dir_temp); if ($result < 0) { $langs->load("errors"); diff --git a/htdocs/compta/bank/releve.php b/htdocs/compta/bank/releve.php index d424a3a8fef..2dbaaa07373 100644 --- a/htdocs/compta/bank/releve.php +++ b/htdocs/compta/bank/releve.php @@ -197,11 +197,6 @@ if ($action == 'confirm_editbankreceipt' && !empty($oldbankreceipt) && !empty($n /* * View */ - -$title = $langs->trans("FinancialAccount").' - '.$langs->trans("AccountStatements"); -$helpurl = ""; -llxHeader('', $title, $helpurl); - $form = new Form($db); $societestatic = new Societe($db); $chargestatic = new ChargeSociales($db); @@ -253,6 +248,10 @@ if (empty($numref)) { $numrows = $db->num_rows($result); $i = 0; + $title = $object->ref.' - '.$langs->trans("AccountStatements"); + $helpurl = ""; + llxHeader('', $title, $helpurl); + // Onglets $head = bank_prepare_head($object); print dol_get_fiche_head($head, 'statement', $langs->trans("FinancialAccount"), 0, 'account'); diff --git a/htdocs/compta/bank/treso.php b/htdocs/compta/bank/treso.php index 71e5cf37c87..0d76b40a3e2 100644 --- a/htdocs/compta/bank/treso.php +++ b/htdocs/compta/bank/treso.php @@ -57,11 +57,6 @@ $hookmanager->initHooks(array('banktreso', 'globalcard')); /* * View */ - -$title = $langs->trans("FinancialAccount").' - '.$langs->trans("PlannedTransactions"); -$helpurl = ""; -llxHeader('', $title, $helpurl); - $societestatic = new Societe($db); $facturestatic = new Facture($db); $facturefournstatic = new FactureFournisseur($db); @@ -85,6 +80,9 @@ if (GETPOST("account") || GETPOST("ref")) { $_GET["account"] = $object->id; } + $title = $object->ref.' - '.$langs->trans("PlannedTransactions"); + $helpurl = ""; + llxHeader('', $title, $helpurl); // Onglets $head = bank_prepare_head($object); diff --git a/htdocs/compta/bank/various_payment/card.php b/htdocs/compta/bank/various_payment/card.php index 95d5ffa0e9e..601ef04de45 100644 --- a/htdocs/compta/bank/various_payment/card.php +++ b/htdocs/compta/bank/various_payment/card.php @@ -304,9 +304,6 @@ if ($action == 'confirm_clone' && $confirm == 'yes' && ($user->rights->banque->m /* * View */ - -llxHeader("", $langs->trans("VariousPayment")); - $form = new Form($db); if (!empty($conf->accounting->enabled)) { $formaccounting = new FormAccounting($db); @@ -324,6 +321,13 @@ if ($id) { } } +$title = $object->ref." - ".$langs->trans('Card'); +if ($action == 'create') { + $title = $langs->trans("NewVariousPayment"); +} +$help_url = 'EN:Module_Suppliers_Invoices|FR:Module_Fournisseurs_Factures|ES:Módulo_Facturas_de_proveedores|DE:Modul_Lieferantenrechnungen'; +llxHeader('', $title, $help_url); + $options = array(); // Load bank groups diff --git a/htdocs/compta/bank/various_payment/list.php b/htdocs/compta/bank/various_payment/list.php index f75ce6d4471..f56e21a2fe2 100644 --- a/htdocs/compta/bank/various_payment/list.php +++ b/htdocs/compta/bank/various_payment/list.php @@ -284,7 +284,7 @@ if ($resql) { } // must be place behind the last "header(...)" call - llxHeader(); + llxHeader('', $langs->trans("VariousPayments")); $i = 0; $total = 0; diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index d0b0ba331f3..59345604d1d 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -2880,8 +2880,10 @@ if (!empty($conf->project->enabled)) { $now = dol_now(); -$title = $langs->trans('InvoiceCustomer')." - ".$langs->trans('Card'); - +$title = $object->ref." - ".$langs->trans('Card'); +if ($action == 'create') { + $title = $langs->trans("NewBill"); +} $help_url = "EN:Customers_Invoices|FR:Factures_Clients|ES:Facturas_a_clientes"; llxHeader('', $title, $help_url); diff --git a/htdocs/compta/facture/contact.php b/htdocs/compta/facture/contact.php index 1b75d43753e..78d1aaaa1cc 100644 --- a/htdocs/compta/facture/contact.php +++ b/htdocs/compta/facture/contact.php @@ -100,7 +100,7 @@ if ($action == 'addcontact' && $user->rights->facture->creer) { * View */ -$title = $langs->trans('InvoiceCustomer')." - ".$langs->trans('ContactsAddresses'); +$title = $object->ref." - ".$langs->trans('ContactsAddresses'); $helpurl = "EN:Customers_Invoices|FR:Factures_Clients|ES:Facturas_a_clientes"; llxHeader('', $title, $helpurl); diff --git a/htdocs/compta/facture/document.php b/htdocs/compta/facture/document.php index 1685da08a2e..5c57f89f51b 100644 --- a/htdocs/compta/facture/document.php +++ b/htdocs/compta/facture/document.php @@ -100,8 +100,7 @@ if (empty($object->id)) { exit; } -$title = $langs->trans('InvoiceCustomer')." - ".$langs->trans('Documents'); - +$title = $object->ref." - ".$langs->trans('Documents'); $help_url = "EN:Customers_Invoices|FR:Factures_Clients|ES:Facturas_a_clientes"; llxHeader('', $title, $help_url); diff --git a/htdocs/compta/facture/info.php b/htdocs/compta/facture/info.php index 4521c7e5096..ddd74de0211 100644 --- a/htdocs/compta/facture/info.php +++ b/htdocs/compta/facture/info.php @@ -65,7 +65,7 @@ $result = restrictedArea($user, 'facture', $object->id, '', '', 'fk_soc', 'rowid $form = new Form($db); -$title = $langs->trans('InvoiceCustomer')." - ".$langs->trans('Info'); +$title = $object->ref." - ".$langs->trans('Info'); $help_url = "EN:Customers_Invoices|FR:Factures_Clients|ES:Facturas_a_clientes"; llxHeader('', $title, $help_url); diff --git a/htdocs/compta/facture/note.php b/htdocs/compta/facture/note.php index 5b30d39da12..711921ee08e 100644 --- a/htdocs/compta/facture/note.php +++ b/htdocs/compta/facture/note.php @@ -85,7 +85,7 @@ if (empty($object->id)) { exit; } -$title = $langs->trans('InvoiceCustomer')." - ".$langs->trans('Notes'); +$title = $object->ref." - ".$langs->trans('Notes'); $helpurl = "EN:Customers_Invoices|FR:Factures_Clients|ES:Facturas_a_clientes"; llxHeader('', $title, $helpurl); diff --git a/htdocs/contact/list.php b/htdocs/contact/list.php index e68274ecff2..2204120468a 100644 --- a/htdocs/contact/list.php +++ b/htdocs/contact/list.php @@ -132,6 +132,7 @@ if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('b } $offset = $limit * $page; + $title = (!empty($conf->global->SOCIETE_ADDRESSES_MANAGEMENT) ? $langs->trans("Contacts") : $langs->trans("ContactsAddresses")); if ($type == "p") { if (empty($contextpage) || $contextpage == 'contactlist') { @@ -345,8 +346,6 @@ if (!empty($conf->global->THIRDPARTY_ENABLE_PROSPECTION_ON_ALTERNATIVE_ADRESSES) $contactstatic->loadCacheOfProspStatus(); } -$title = (!empty($conf->global->SOCIETE_ADDRESSES_MANAGEMENT) ? $langs->trans("Contacts") : $langs->trans("ContactsAddresses")); - // Select every potentiels, and note each potentiels which fit in search parameters $tab_level = array(); $sql = "SELECT code, label, sortorder"; diff --git a/htdocs/core/lib/usergroups.lib.php b/htdocs/core/lib/usergroups.lib.php index 4aa2942884d..65b512ec18e 100644 --- a/htdocs/core/lib/usergroups.lib.php +++ b/htdocs/core/lib/usergroups.lib.php @@ -212,7 +212,7 @@ function group_prepare_head($object) $head = array(); $head[$h][0] = DOL_URL_ROOT.'/user/group/card.php?id='.$object->id; - $head[$h][1] = $langs->trans("GroupCard"); + $head[$h][1] = $langs->trans("Card"); $head[$h][2] = 'group'; $h++; diff --git a/htdocs/expedition/card.php b/htdocs/expedition/card.php index 0508c51dfae..c65c9eb36d7 100644 --- a/htdocs/expedition/card.php +++ b/htdocs/expedition/card.php @@ -804,9 +804,13 @@ if (empty($reshook)) { * View */ +$title = $langs->trans("Shipment"); +if ($action == 'create2') { + $title = $langs->trans("CreateShipment"); +} $help_url = 'EN:Module_Shipments|FR:Module_Expéditions|ES:Módulo_Expediciones|DE:Modul_Lieferungen'; -llxHeader('', $langs->trans('Shipment'), 'Expedition', $help_url); +llxHeader('', $title, 'Expedition', $help_url); if (empty($action)) { $action = 'view'; diff --git a/htdocs/expedition/shipment.php b/htdocs/expedition/shipment.php index 328a84430a9..852ad9e82ab 100644 --- a/htdocs/expedition/shipment.php +++ b/htdocs/expedition/shipment.php @@ -231,7 +231,7 @@ if (!empty($conf->project->enabled)) { $formproject = new FormProjets($db); } -$title = $langs->trans('Order')." - ".$langs->trans('Shipments'); +$title = $object->ref." - ".$langs->trans('Shipments'); $help_url = 'EN:Customers_Orders|FR:Commandes_Clients|ES:Pedidos de clientes|DE:Modul_Kundenaufträge'; llxHeader('', $title, $help_url); diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index 19a630871fc..67b8eb75fb4 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -1538,7 +1538,10 @@ if (!empty($conf->project->enabled)) { $formproject = new FormProjets($db); } -$title = $langs->trans('SupplierOrder')." - ".$langs->trans('Card'); +$title = $object->ref." - ".$langs->trans('Card'); +if ($action == 'create') { + $title = $langs->trans("NewOrderSupplier"); +} $help_url = 'EN:Module_Suppliers_Orders|FR:CommandeFournisseur|ES:Módulo_Pedidos_a_proveedores'; llxHeader('', $title, $help_url); diff --git a/htdocs/fourn/commande/contact.php b/htdocs/fourn/commande/contact.php index f05251993a7..3cae4f04c73 100644 --- a/htdocs/fourn/commande/contact.php +++ b/htdocs/fourn/commande/contact.php @@ -99,10 +99,6 @@ if ($action == 'addcontact' && ($user->rights->fournisseur->commande->creer || $ /* * View */ -$title = $langs->trans('SupplierOrder')." - ".$langs->trans('ContactsAddresses'); -$help_url = 'EN:Module_Suppliers_Orders|FR:CommandeFournisseur|ES:Módulo_Pedidos_a_proveedores'; -llxHeader('', $title, $help_url); - $form = new Form($db); $formcompany = new FormCompany($db); $contactstatic = new Contact($db); @@ -121,6 +117,10 @@ if ($id > 0 || !empty($ref)) { if ($object->fetch($id, $ref) > 0) { $object->fetch_thirdparty(); + $title = $object->ref." - ".$langs->trans('ContactsAddresses'); + $help_url = 'EN:Module_Suppliers_Orders|FR:CommandeFournisseur|ES:Módulo_Pedidos_a_proveedores'; + llxHeader('', $title, $help_url); + $head = ordersupplier_prepare_head($object); print dol_get_fiche_head($head, 'contact', $langs->trans("SupplierOrder"), -1, 'order'); diff --git a/htdocs/fourn/commande/dispatch.php b/htdocs/fourn/commande/dispatch.php index 7b352a01abc..c20768e8f38 100644 --- a/htdocs/fourn/commande/dispatch.php +++ b/htdocs/fourn/commande/dispatch.php @@ -505,10 +505,11 @@ $formproduct = new FormProduct($db); $warehouse_static = new Entrepot($db); $supplierorderdispatch = new CommandeFournisseurDispatch($db); +$title = $object->ref." - ".$langs->trans('OrderDispatch'); $help_url = 'EN:Module_Suppliers_Orders|FR:CommandeFournisseur|ES:Módulo_Pedidos_a_proveedores'; $morejs = array('/fourn/js/lib_dispatch.js.php'); -llxHeader('', $langs->trans("OrderDispatch"), $help_url, '', 0, 0, $morejs); +llxHeader('', $title, $help_url, '', 0, 0, $morejs); if ($id > 0 || !empty($ref)) { $soc = new Societe($db); diff --git a/htdocs/fourn/commande/document.php b/htdocs/fourn/commande/document.php index ca43b69fd5e..5a017296887 100644 --- a/htdocs/fourn/commande/document.php +++ b/htdocs/fourn/commande/document.php @@ -98,7 +98,7 @@ include DOL_DOCUMENT_ROOT.'/core/actions_linkedfiles.inc.php'; $form = new Form($db); -$title = $langs->trans('SupplierOrder')." - ".$langs->trans('Documents'); +$title = $object->ref." - ".$langs->trans('Documents'); $help_url = 'EN:Module_Suppliers_Orders|FR:CommandeFournisseur|ES:Módulo_Pedidos_a_proveedores'; llxHeader('', $title, $help_url); diff --git a/htdocs/fourn/commande/info.php b/htdocs/fourn/commande/info.php index 771a6faf23f..18c4f5f2670 100644 --- a/htdocs/fourn/commande/info.php +++ b/htdocs/fourn/commande/info.php @@ -113,7 +113,7 @@ if ($id > 0 || !empty($ref)) { $object->info($object->id); } -$title = $langs->trans("SupplierOrder").' - '.$langs->trans('Info').' - '.$object->ref.' '.$object->name; +$title = $object->ref.' - '.$langs->trans('Info').' - '.$object->ref.' '.$object->name; if (!empty($conf->global->MAIN_HTML_TITLE) && preg_match('/projectnameonly/', $conf->global->MAIN_HTML_TITLE) && $object->name) { $title = $object->ref.' '.$object->name.' - '.$langs->trans("Info"); } diff --git a/htdocs/fourn/commande/note.php b/htdocs/fourn/commande/note.php index d2c7398a98c..cfdea75d9d9 100644 --- a/htdocs/fourn/commande/note.php +++ b/htdocs/fourn/commande/note.php @@ -69,7 +69,7 @@ if (empty($reshook)) { /* * View */ -$title = $langs->trans('SupplierOrder')." - ".$langs->trans('Notes'); +$title = $object->ref." - ".$langs->trans('Notes'); $help_url = 'EN:Module_Suppliers_Orders|FR:CommandeFournisseur|ES:Módulo_Pedidos_a_proveedores'; llxHeader('', $title, $help_url); diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index c2fc4e8511a..bd06da5f987 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -1894,7 +1894,10 @@ if (!empty($conf->project->enabled)) { $now = dol_now(); -$title = $langs->trans('SupplierInvoice')." - ".$langs->trans('Card'); +$title = $object->ref." - ".$langs->trans('Card'); +if ($action == 'create') { + $title = $langs->trans("NewSupplierInvoice"); +} $help_url = 'EN:Module_Suppliers_Invoices|FR:Module_Fournisseurs_Factures|ES:Módulo_Facturas_de_proveedores|DE:Modul_Lieferantenrechnungen'; llxHeader('', $title, $help_url); @@ -1902,7 +1905,7 @@ llxHeader('', $title, $help_url); if ($action == 'create') { $facturestatic = new FactureFournisseur($db); - print load_fiche_titre($langs->trans('NewBill'), '', 'supplier_invoice'); + print load_fiche_titre($langs->trans('NewSupplierInvoice'), '', 'supplier_invoice'); dol_htmloutput_events(); diff --git a/htdocs/fourn/facture/contact.php b/htdocs/fourn/facture/contact.php index 85885ae866e..1096cb1eae8 100644 --- a/htdocs/fourn/facture/contact.php +++ b/htdocs/fourn/facture/contact.php @@ -99,11 +99,6 @@ if ($action == 'addcontact' && ($user->rights->fournisseur->facture->creer || $u /* * View */ - -$title = $langs->trans('SupplierInvoice')." - ".$langs->trans('ContactsAddresses'); -$helpurl = "EN:Module_Suppliers_Invoices|FR:Module_Fournisseurs_Factures|ES:Módulo_Facturas_de_proveedores"; -llxHeader('', $title, $helpurl); - $form = new Form($db); $formcompany = new FormCompany($db); $contactstatic = new Contact($db); @@ -122,6 +117,10 @@ if ($id > 0 || !empty($ref)) { $alreadypaid = $object->getSommePaiement(); + $title = $object->ref." - ".$langs->trans('ContactsAddresses'); + $helpurl = "EN:Module_Suppliers_Invoices|FR:Module_Fournisseurs_Factures|ES:Módulo_Facturas_de_proveedores"; + llxHeader('', $title, $helpurl); + $head = facturefourn_prepare_head($object); print dol_get_fiche_head($head, 'contact', $langs->trans('SupplierInvoice'), -1, 'supplier_invoice'); diff --git a/htdocs/fourn/facture/document.php b/htdocs/fourn/facture/document.php index d2f7181856a..6cedd8884df 100644 --- a/htdocs/fourn/facture/document.php +++ b/htdocs/fourn/facture/document.php @@ -94,7 +94,7 @@ include DOL_DOCUMENT_ROOT.'/core/actions_linkedfiles.inc.php'; $form = new Form($db); -$title = $langs->trans('SupplierInvoice')." - ".$langs->trans('Documents'); +$title = $object->ref." - ".$langs->trans('Documents'); $helpurl = "EN:Module_Suppliers_Invoices|FR:Module_Fournisseurs_Factures|ES:Módulo_Facturas_de_proveedores"; llxHeader('', $title, $helpurl); diff --git a/htdocs/fourn/facture/info.php b/htdocs/fourn/facture/info.php index 0f932c27bae..de5985ae28f 100644 --- a/htdocs/fourn/facture/info.php +++ b/htdocs/fourn/facture/info.php @@ -54,18 +54,15 @@ $object = new FactureFournisseur($db); */ $form = new Form($db); - -$title = $langs->trans('SupplierInvoice')." - ".$langs->trans('Info'); -$helpurl = "EN:Module_Suppliers_Invoices|FR:Module_Fournisseurs_Factures|ES:Módulo_Facturas_de_proveedores"; -llxHeader('', $title, $helpurl); - $object->fetch($id, $ref); $object->fetch_thirdparty(); - $object->info($object->id); - $alreadypaid = $object->getSommePaiement(); +$title = $object->ref." - ".$langs->trans('Info'); +$helpurl = "EN:Module_Suppliers_Invoices|FR:Module_Fournisseurs_Factures|ES:Módulo_Facturas_de_proveedores"; +llxHeader('', $title, $helpurl); + $head = facturefourn_prepare_head($object); $titre = $langs->trans('SupplierInvoice'); print dol_get_fiche_head($head, 'info', $langs->trans('SupplierInvoice'), -1, 'supplier_invoice'); diff --git a/htdocs/fourn/facture/note.php b/htdocs/fourn/facture/note.php index 682d92b4515..46a9f8fdc44 100644 --- a/htdocs/fourn/facture/note.php +++ b/htdocs/fourn/facture/note.php @@ -83,7 +83,7 @@ if ($action == 'setlabel' && ($user->rights->fournisseur->facture->creer || $use $form = new Form($db); -$title = $langs->trans('SupplierInvoice')." - ".$langs->trans('Notes'); +$title = $object->ref." - ".$langs->trans('Notes'); $helpurl = "EN:Module_Suppliers_Invoices|FR:Module_Fournisseurs_Factures|ES:Módulo_Facturas_de_proveedores"; llxHeader('', $title, $helpurl); diff --git a/htdocs/langs/en_US/suppliers.lang b/htdocs/langs/en_US/suppliers.lang index 15da3f0638a..08895194016 100644 --- a/htdocs/langs/en_US/suppliers.lang +++ b/htdocs/langs/en_US/suppliers.lang @@ -4,6 +4,7 @@ SuppliersInvoice=Vendor invoice SupplierInvoices=Vendor invoices ShowSupplierInvoice=Show Vendor Invoice NewSupplier=New vendor +NewSupplierInvoice = New vendor invoice History=History ListOfSuppliers=List of vendors ShowSupplier=Show vendor diff --git a/htdocs/product/card.php b/htdocs/product/card.php index 664b25ff169..75e539bf9c8 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -1190,15 +1190,24 @@ if (!empty($conf->accounting->enabled)) { $title = $langs->trans('ProductServiceCard'); + $help_url = ''; $shortlabel = dol_trunc($object->label, 16); if (GETPOST("type") == '0' || ($object->type == Product::TYPE_PRODUCT)) { - $title = $langs->trans('Product')." ".$shortlabel." - ".$langs->trans('Card'); - $help_url = 'EN:Module_Products|FR:Module_Produits|ES:Módulo_Productos|DE:Modul_Produkte'; + if ($action == 'create') { + $title = $langs->trans("NewProduct"); + } else { + $title = $langs->trans('Product')." ".$shortlabel." - ".$langs->trans('Card'); + $help_url = 'EN:Module_Products|FR:Module_Produits|ES:Módulo_Productos|DE:Modul_Produkte'; + } } if (GETPOST("type") == '1' || ($object->type == Product::TYPE_SERVICE)) { - $title = $langs->trans('Service')." ".$shortlabel." - ".$langs->trans('Card'); - $help_url = 'EN:Module_Services_En|FR:Module_Services|ES:Módulo_Servicios|DE:Modul_Leistungen'; + if ($action == 'create') { + $title = $langs->trans("NewService"); + } else { + $title = $langs->trans('Service')." ".$shortlabel." - ".$langs->trans('Card'); + $help_url = 'EN:Module_Services_En|FR:Module_Services|ES:Módulo_Servicios|DE:Modul_Leistungen'; + } } llxHeader('', $title, $help_url); diff --git a/htdocs/product/list.php b/htdocs/product/list.php index 70c5b4f3799..39f2ec11c45 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -387,16 +387,14 @@ if (empty($reshook)) { * View */ -$title = $langs->trans("ProductsAndServices"); +$title = $langs->trans("ListOfProductsAndServices"); if ($search_type != '' && $search_type != '-1') { if ($search_type == 1) { - $texte = $langs->trans("Services"); + $title = $langs->trans("ListOfServices"); } else { - $texte = $langs->trans("Products"); + $title = $langs->trans("ListOfProducts"); } -} else { - $texte = $langs->trans("ProductsAndServices"); } $sql = 'SELECT DISTINCT p.rowid, p.ref, p.label, p.fk_product_type, p.barcode, p.price, p.tva_tx, p.price_ttc, p.price_base_type, p.entity,'; @@ -790,7 +788,7 @@ if ($resql) { $picto = 'service'; } - print_barre_liste($texte, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, $picto, 0, $newcardbutton, '', $limit, 0, 0, 1); + print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, $picto, 0, $newcardbutton, '', $limit, 0, 0, 1); $topicmail = "Information"; $modelmail = "product"; diff --git a/htdocs/product/stock/card.php b/htdocs/product/stock/card.php index 3ef85adeb84..311b04a4c89 100644 --- a/htdocs/product/stock/card.php +++ b/htdocs/product/stock/card.php @@ -281,8 +281,13 @@ if (!empty($conf->project->enabled)) { $formproject = new FormProjets($db); } +$title = $langs->trans("WarehouseCard"); +if ($action == 'create') { + $title = $langs->trans("NewWarehouse"); +} + $help_url = 'EN:Module_Stocks_En|FR:Module_Stock|ES:Módulo_Stocks'; -llxHeader("", $langs->trans("WarehouseCard"), $help_url); +llxHeader("", $title, $help_url); if ($action == 'create') { diff --git a/htdocs/product/stock/movement_list.php b/htdocs/product/stock/movement_list.php index 34a2a074ec5..561ee5d5d4d 100644 --- a/htdocs/product/stock/movement_list.php +++ b/htdocs/product/stock/movement_list.php @@ -777,7 +777,11 @@ if ($msid) { } else { $title = $langs->trans("ListOfStockMovements"); if ($id) { - $title .= ' ('.$langs->trans("ForThisWarehouse").')'; + if (!empty($object->ref)) { + $title .= ' ('.$object->ref.')'; + } else { + $title .= ' ('.$langs->trans("ForThisWarehouse").')'; + } } } diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index 2ad89326e6a..08a4367857c 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -483,6 +483,7 @@ $title = $langs->trans("Project").' - '.$object->ref.(!empty($object->thirdparty if (!empty($conf->global->MAIN_HTML_TITLE) && preg_match('/projectnameonly/', $conf->global->MAIN_HTML_TITLE)) { $title = $object->ref.(!empty($object->thirdparty->name) ? ' - '.$object->thirdparty->name : '').(!empty($object->title) ? ' - '.$object->title : ''); } + $help_url = "EN:Module_Projects|FR:Module_Projets|ES:Módulo_Proyectos|DE:Modul_Projekte"; llxHeader("", $title, $help_url); diff --git a/htdocs/projet/document.php b/htdocs/projet/document.php index 588043a56dc..ad5b8715e95 100644 --- a/htdocs/projet/document.php +++ b/htdocs/projet/document.php @@ -97,7 +97,7 @@ include DOL_DOCUMENT_ROOT.'/core/actions_linkedfiles.inc.php'; * View */ -$title = $langs->trans('Project').' - '.$langs->trans('Document').' - '.$object->ref.' '.$object->name; +$title = $langs->trans('Documents').' - '.$object->ref.' '.$object->name; if (!empty($conf->global->MAIN_HTML_TITLE) && preg_match('/projectnameonly/', $conf->global->MAIN_HTML_TITLE) && $object->name) { $title = $object->ref.' '.$object->name.' - '.$langs->trans('Document'); } diff --git a/htdocs/projet/info.php b/htdocs/projet/info.php index 19897bf2859..e3532fb6471 100644 --- a/htdocs/projet/info.php +++ b/htdocs/projet/info.php @@ -109,8 +109,8 @@ if ($id > 0 || !empty($ref)) { } $object->info($object->id); } - -$title = $langs->trans("Project").' - '.$object->ref.' '.$object->name; +$agenda = (!empty($conf->agenda->enabled) && (!empty($user->rights->agenda->myactions->read) || !empty($user->rights->agenda->allactions->read))) ? '/'.$langs->trans("Agenda") : ''; +$title = $langs->trans('Events').$agenda.' - '.$object->ref.' '.$object->name; if (!empty($conf->global->MAIN_HTML_TITLE) && preg_match('/projectnameonly/', $conf->global->MAIN_HTML_TITLE) && $object->name) { $title = $object->ref.' '.$object->name.' - '.$langs->trans("Info"); } diff --git a/htdocs/projet/note.php b/htdocs/projet/note.php index 2ee52d3a247..3eed5e14c60 100644 --- a/htdocs/projet/note.php +++ b/htdocs/projet/note.php @@ -69,7 +69,7 @@ if (empty($reshook)) { * View */ -$title = $langs->trans("Project").' - '.$langs->trans("Note").' - '.$object->ref.' '.$object->name; +$title = $langs->trans("Notes").' - '.$object->ref.' '.$object->name; if (!empty($conf->global->MAIN_HTML_TITLE) && preg_match('/projectnameonly/', $conf->global->MAIN_HTML_TITLE) && $object->name) { $title = $object->ref.' '.$object->name.' - '.$langs->trans("Note"); } diff --git a/htdocs/projet/tasks.php b/htdocs/projet/tasks.php index 612aa0e6fe7..f527a13644e 100644 --- a/htdocs/projet/tasks.php +++ b/htdocs/projet/tasks.php @@ -402,10 +402,13 @@ $projectstatic = new Project($db); $taskstatic = new Task($db); $userstatic = new User($db); -$title = $langs->trans("Project").' - '.$langs->trans("Tasks").' - '.$object->ref.' '.$object->name; +$title = $langs->trans("Tasks").' - '.$object->ref.' '.$object->name; if (!empty($conf->global->MAIN_HTML_TITLE) && preg_match('/projectnameonly/', $conf->global->MAIN_HTML_TITLE) && $object->name) { $title = $object->ref.' '.$object->name.' - '.$langs->trans("Tasks"); } +if ($action == 'create') { + $title = $langs->trans("NewTask"); +} $help_url = "EN:Module_Projects|FR:Module_Projets|ES:Módulo_Proyectos"; llxHeader("", $title, $help_url); diff --git a/htdocs/projet/tasks/contact.php b/htdocs/projet/tasks/contact.php index 9718a0ffccb..718af1bf17b 100644 --- a/htdocs/projet/tasks/contact.php +++ b/htdocs/projet/tasks/contact.php @@ -140,13 +140,19 @@ if (!empty($project_ref) && !empty($withproject)) { /* * View */ - -llxHeader('', $langs->trans("Task")); - $form = new Form($db); $formcompany = new FormCompany($db); $contactstatic = new Contact($db); $userstatic = new User($db); +$result = $projectstatic->fetch($object->fk_project); + +$title = $object->ref . ' - ' . $langs->trans("Contacts"); +if (!empty($withproject)) { + $title .= ' | ' . $langs->trans("Project") . (!empty($projectstatic->ref) ? ': '.$projectstatic->ref : '') ; +} +$help_url = ''; + +llxHeader('', $title, $help_url); /* *************************************************************************** */ @@ -162,7 +168,6 @@ if ($id > 0 || !empty($ref)) { } $id = $object->id; // So when doing a search from ref, id is also set correctly. - $result = $projectstatic->fetch($object->fk_project); if (!empty($conf->global->PROJECT_ALLOW_COMMENT_ON_PROJECT) && method_exists($projectstatic, 'fetchComments') && empty($projectstatic->comments)) { $projectstatic->fetchComments(); } diff --git a/htdocs/projet/tasks/document.php b/htdocs/projet/tasks/document.php index ad0a2c0b628..25bf2f94d5d 100644 --- a/htdocs/projet/tasks/document.php +++ b/htdocs/projet/tasks/document.php @@ -119,10 +119,15 @@ include DOL_DOCUMENT_ROOT.'/core/actions_linkedfiles.inc.php'; /* * View */ - $form = new Form($db); -llxHeader('', $langs->trans('Task')); +$title = $object->ref . ' - ' . $langs->trans("Documents"); +if (!empty($withproject)) { + $title .= ' | ' . $langs->trans("Project") . (!empty($projectstatic->ref) ? ': '.$projectstatic->ref : '') ; +} +$help_url = ''; + +llxHeader('', $title, $help_url); if ($object->id > 0) { $projectstatic->fetch_thirdparty(); diff --git a/htdocs/projet/tasks/note.php b/htdocs/projet/tasks/note.php index 206a92afb36..b877c7c8a8d 100644 --- a/htdocs/projet/tasks/note.php +++ b/htdocs/projet/tasks/note.php @@ -110,14 +110,19 @@ if (empty($reshook)) { /* * View */ - -llxHeader('', $langs->trans("Task")); - $form = new Form($db); $userstatic = new User($db); $now = dol_now(); +$title = $object->ref . ' - ' . $langs->trans("Notes"); +if (!empty($withproject)) { + $title .= ' | ' . $langs->trans("Project") . (!empty($projectstatic->ref) ? ': '.$projectstatic->ref : '') ; +} +$help_url = ''; + +llxHeader('', $title, $help_url); + if ($object->id > 0) { $userWrite = $projectstatic->restrictedProjectArea($user, 'write'); diff --git a/htdocs/projet/tasks/task.php b/htdocs/projet/tasks/task.php index 3df3cf8928e..31fa1547ffc 100644 --- a/htdocs/projet/tasks/task.php +++ b/htdocs/projet/tasks/task.php @@ -192,12 +192,18 @@ if ($action == 'remove_file' && $user->rights->projet->creer) { /* * View */ - -llxHeader('', $langs->trans("Task")); - $form = new Form($db); $formother = new FormOther($db); $formfile = new FormFile($db); +$result = $projectstatic->fetch($object->fk_project); + +$title = $object->ref; +if (!empty($withproject)) { + $title .= ' | ' . $langs->trans("Project") . (!empty($projectstatic->ref) ? ': '.$projectstatic->ref : '') ; +} +$help_url = ''; + +llxHeader('', $title, $help_url); if ($id > 0 || !empty($ref)) { $res = $object->fetch_optionals(); @@ -205,7 +211,7 @@ if ($id > 0 || !empty($ref)) { $object->fetchComments(); } - $result = $projectstatic->fetch($object->fk_project); + if (!empty($conf->global->PROJECT_ALLOW_COMMENT_ON_PROJECT) && method_exists($projectstatic, 'fetchComments') && empty($projectstatic->comments)) { $projectstatic->fetchComments(); } diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index 801e0cb0a00..f409b3cb547 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -702,15 +702,20 @@ if ($action == 'confirm_generateinter') { /* * View */ - -$arrayofselected = is_array($toselect) ? $toselect : array(); - -llxHeader("", $langs->trans("Task")); - $form = new Form($db); $formother = new FormOther($db); $formproject = new FormProjets($db); $userstatic = new User($db); +//$result = $projectstatic->fetch($object->fk_project); +$arrayofselected = is_array($toselect) ? $toselect : array(); + +$title = $object->ref . ' - ' . $langs->trans("TimeSpent"); +if (!empty($withproject)) { + $title .= ' | ' . $langs->trans("Project") . (!empty($projectstatic->ref) ? ': '.$projectstatic->ref : '') ; +} +$help_url = ''; + +llxHeader('', $title, $help_url); if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser > 0) { /* diff --git a/htdocs/societe/card.php b/htdocs/societe/card.php index 8e347a6d487..aa784d8639d 100644 --- a/htdocs/societe/card.php +++ b/htdocs/societe/card.php @@ -959,10 +959,12 @@ if ($socid > 0 && empty($object->id)) { } $title = $langs->trans("ThirdParty"); +if ($action == 'create') { + $title = $langs->trans("NewThirdParty"); +} if (!empty($conf->global->MAIN_HTML_TITLE) && preg_match('/thirdpartynameonly/', $conf->global->MAIN_HTML_TITLE) && $object->name) { $title = $object->name." - ".$langs->trans('Card'); } - $help_url = 'EN:Module_Third_Parties|FR:Module_Tiers|ES:Empresas|DE:Modul_Geschäftspartner'; llxHeader('', $title, $help_url); diff --git a/htdocs/societe/list.php b/htdocs/societe/list.php index 255152744f7..a358cbe5d6f 100644 --- a/htdocs/societe/list.php +++ b/htdocs/societe/list.php @@ -731,7 +731,7 @@ if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && ( } $help_url = 'EN:Module_Third_Parties|FR:Module_Tiers|ES:Empresas'; -llxHeader('', $langs->trans("ThirdParty"), $help_url); +llxHeader('', $title, $help_url); $param = ''; if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { diff --git a/htdocs/societe/paymentmodes.php b/htdocs/societe/paymentmodes.php index 005c55c260a..c0bff452b9c 100644 --- a/htdocs/societe/paymentmodes.php +++ b/htdocs/societe/paymentmodes.php @@ -683,7 +683,7 @@ if (!empty($conf->global->MAIN_HTML_TITLE) && preg_match('/thirdpartynameonly/', $title = $object->name." - ".$langs->trans('PaymentInformation'); } -llxHeader(); +llxHeader('', $title, $help_url); $head = societe_prepare_head($object); diff --git a/htdocs/supplier_proposal/card.php b/htdocs/supplier_proposal/card.php index 9e92a5fb4b6..6253d9b86b2 100644 --- a/htdocs/supplier_proposal/card.php +++ b/htdocs/supplier_proposal/card.php @@ -1122,7 +1122,10 @@ if (empty($reshook)) { /* * View */ -$title = $langs->trans('CommRequest')." - ".$langs->trans('Card'); +$title = $object->ref." - ".$langs->trans('Card'); +if ($action == 'create') { + $title = $langs->trans("SupplierProposalNew"); +} $help_url = 'EN:Ask_Price_Supplier|FR:Demande_de_prix_fournisseur'; llxHeader('', $title, $help_url); @@ -1141,7 +1144,7 @@ $now = dol_now(); if ($action == 'create') { $currency_code = $conf->currency; - print load_fiche_titre($langs->trans("NewAskPrice"), '', 'supplier_proposal'); + print load_fiche_titre($langs->trans("SupplierProposalNew"), '', 'supplier_proposal'); $soc = new Societe($db); if ($socid > 0) { diff --git a/htdocs/supplier_proposal/contact.php b/htdocs/supplier_proposal/contact.php index bc5e555fa99..51137133aca 100644 --- a/htdocs/supplier_proposal/contact.php +++ b/htdocs/supplier_proposal/contact.php @@ -98,10 +98,6 @@ if ($action == 'addcontact' && $permissiontoedit) { /* * View */ -$title = $langs->trans('CommRequest')." - ".$langs->trans('ContactsAddresses'); -$help_url = 'EN:Ask_Price_Supplier|FR:Demande_de_prix_fournisseur'; -llxHeader('', $title, $help_url); - $form = new Form($db); $formcompany = new FormCompany($db); $contactstatic = new Contact($db); @@ -120,6 +116,10 @@ if ($id > 0 || !empty($ref)) { if ($object->fetch($id, $ref) > 0) { $object->fetch_thirdparty(); + $title = $object->ref." - ".$langs->trans('ContactsAddresses'); + $help_url = 'EN:Ask_Price_Supplier|FR:Demande_de_prix_fournisseur'; + llxHeader('', $title, $help_url); + $head = supplier_proposal_prepare_head($object); print dol_get_fiche_head($head, 'contact', $langs->trans("CommRequest"), -1, 'supplier_proposal'); diff --git a/htdocs/supplier_proposal/document.php b/htdocs/supplier_proposal/document.php index af2353c4d8f..74dd7c6160e 100644 --- a/htdocs/supplier_proposal/document.php +++ b/htdocs/supplier_proposal/document.php @@ -90,7 +90,7 @@ if ($object->id > 0) { * View */ -$title = $langs->trans('CommRequest')." - ".$langs->trans('Documents'); +$title = $object->ref." - ".$langs->trans('Documents'); $help_url = 'EN:Ask_Price_Supplier|FR:Demande_de_prix_fournisseur'; llxHeader('', $title, $help_url); diff --git a/htdocs/supplier_proposal/info.php b/htdocs/supplier_proposal/info.php index 7bb6d4f7682..b95c06581ce 100644 --- a/htdocs/supplier_proposal/info.php +++ b/htdocs/supplier_proposal/info.php @@ -48,19 +48,16 @@ $result = restrictedArea($user, 'supplier_proposal', $id); /* * View */ - $form = new Form($db); - -$title = $langs->trans('CommRequest')." - ".$langs->trans('Info'); -$help_url = 'EN:Ask_Price_Supplier|FR:Demande_de_prix_fournisseur'; -llxHeader('', $title, $help_url); - $object = new SupplierProposal($db); $object->fetch($id); $object->fetch_thirdparty(); - $object->info($object->id); +$title = $object->ref." - ".$langs->trans('Info'); +$help_url = 'EN:Ask_Price_Supplier|FR:Demande_de_prix_fournisseur'; +llxHeader('', $title, $help_url); + $head = supplier_proposal_prepare_head($object); print dol_get_fiche_head($head, 'info', $langs->trans('CommRequest'), -1, 'supplier_proposal'); diff --git a/htdocs/supplier_proposal/list.php b/htdocs/supplier_proposal/list.php index 96f8a2b2cca..1c347a2b23c 100644 --- a/htdocs/supplier_proposal/list.php +++ b/htdocs/supplier_proposal/list.php @@ -285,8 +285,10 @@ $formpropal = new FormPropal($db); $companystatic = new Societe($db); $formcompany = new FormCompany($db); +$title = $langs->trans('ListOfSupplierProposals'); $help_url = 'EN:Ask_Price_Supplier|FR:Demande_de_prix_fournisseur'; -//llxHeader('',$langs->trans('CommRequest'),$help_url); + +llxHeader('', $title, $help_url); $sql = 'SELECT'; if ($sall || $search_product_category > 0 || $search_user > 0) { @@ -467,7 +469,7 @@ if ($resql) { exit; } - llxHeader('', $langs->trans('CommRequest'), $help_url); +// llxHeader('', $langs->trans('CommRequest'), $help_url); $param = ''; if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { diff --git a/htdocs/supplier_proposal/note.php b/htdocs/supplier_proposal/note.php index 4ef46594e0e..48ce778c0cf 100644 --- a/htdocs/supplier_proposal/note.php +++ b/htdocs/supplier_proposal/note.php @@ -72,10 +72,6 @@ if (empty($reshook)) { /* * View */ -$title = $langs->trans('CommRequest')." - ".$langs->trans('Notes'); -$help_url = 'EN:Ask_Price_Supplier|FR:Demande_de_prix_fournisseur'; -llxHeader('', $title, $help_url); - $form = new Form($db); if ($id > 0 || !empty($ref)) { @@ -88,6 +84,10 @@ if ($id > 0 || !empty($ref)) { if ($object->fetch($id, $ref)) { $object->fetch_thirdparty(); + $title = $object->ref." - ".$langs->trans('Notes'); + $help_url = 'EN:Ask_Price_Supplier|FR:Demande_de_prix_fournisseur'; + llxHeader('', $title, $help_url); + $societe = new Societe($db); if ($societe->fetch($object->socid)) { $head = supplier_proposal_prepare_head($object); diff --git a/htdocs/user/agenda_extsites.php b/htdocs/user/agenda_extsites.php index b7d66d2677c..f1b908ef5f7 100644 --- a/htdocs/user/agenda_extsites.php +++ b/htdocs/user/agenda_extsites.php @@ -148,7 +148,11 @@ $formother = new FormOther($db); $arrayofjs = array(); $arrayofcss = array(); -llxHeader('', $langs->trans("UserSetup"), '', '', 0, 0, $arrayofjs, $arrayofcss); +$person_name = !empty($object->firstname) ? $object->lastname.", ".$object->firstname : $object->lastname; +$title = $person_name." - ".$langs->trans('ExtSites'); +$help_url = ''; + +llxHeader('', $title, $help_url, '', 0, 0, $arrayofjs, $arrayofcss); print '
'; diff --git a/htdocs/user/bank.php b/htdocs/user/bank.php index 7cd8bbe6863..fd82ab6c14e 100644 --- a/htdocs/user/bank.php +++ b/htdocs/user/bank.php @@ -277,7 +277,10 @@ $form = new Form($db); $childids = $user->getAllChildIds(1); -llxHeader(null, $langs->trans("BankAccounts")); +$person_name = !empty($object->firstname) ? $object->lastname.", ".$object->firstname : $object->lastname; +$title = $person_name." - ".$langs->trans('BankAccounts'); +$help_url = ''; +llxHeader('', $title, $help_url); $head = user_prepare_head($object); diff --git a/htdocs/user/card.php b/htdocs/user/card.php index 36807533a66..563bb0284c2 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -730,9 +730,13 @@ if (!empty($conf->stock->enabled)) { $formproduct = new FormProduct($db); } -llxHeader('', $langs->trans("UserCard")); +$help_url = ''; if ($action == 'create' || $action == 'adduserldap') { + + $title = $langs->trans("NewUser"); + llxHeader('', $title, $help_url); + print load_fiche_titre($langs->trans("NewUser"), '', 'user'); print ''.$langs->trans("CreateInternalUserDesc")."
\n"; @@ -1350,6 +1354,10 @@ if ($action == 'create' || $action == 'adduserldap') { } } + $person_name = !empty($object->firstname) ? $object->lastname.", ".$object->firstname : $object->lastname; + $title = $person_name." - ".$langs->trans('Card'); + llxHeader('', $title, $help_url); + // Show tabs if ($mode == 'employee') { // For HRM module development $title = $langs->trans("Employee"); diff --git a/htdocs/user/clicktodial.php b/htdocs/user/clicktodial.php index 0dd38cc057b..ca228f122ec 100644 --- a/htdocs/user/clicktodial.php +++ b/htdocs/user/clicktodial.php @@ -74,18 +74,18 @@ if (empty($reshook)) { /* * View */ - $form = new Form($db); -llxHeader("", "ClickToDial"); - - if ($id > 0) { $object = new User($db); $object->fetch($id, '', '', 1); $object->getrights(); $object->fetch_clicktodial(); + $person_name = !empty($object->firstname) ? $object->lastname.", ".$object->firstname : $object->lastname; + $title = $person_name." - ".$langs->trans('ClickToDial'); + $help_url = ''; + llxHeader('', $title, $help_url); $head = user_prepare_head($object); diff --git a/htdocs/user/document.php b/htdocs/user/document.php index 142c44d85fe..d33175af8c5 100644 --- a/htdocs/user/document.php +++ b/htdocs/user/document.php @@ -129,7 +129,11 @@ if (empty($reshook)) { $form = new Form($db); -llxHeader('', $langs->trans("UserCard").' - '.$langs->trans("Files")); + +$person_name = !empty($object->firstname) ? $object->lastname.", ".$object->firstname : $object->lastname; +$title = $person_name." - ".$langs->trans('Documents'); +$help_url = ''; +llxHeader('', $title, $help_url); if ($object->id) { /* diff --git a/htdocs/user/group/card.php b/htdocs/user/group/card.php index 1acfa858663..92d309e554b 100644 --- a/htdocs/user/group/card.php +++ b/htdocs/user/group/card.php @@ -246,8 +246,13 @@ if (empty($reshook)) { /* * View */ +$title = $object->name.' - '.$langs->trans("Card"); +if ($action == 'create') { + $title = $langs->trans("NewGroup"); +} + +llxHeader('', $title, $help_url); -llxHeader('', $langs->trans("GroupCard")); $form = new Form($db); $fuserstatic = new User($db); diff --git a/htdocs/user/group/ldap.php b/htdocs/user/group/ldap.php index af28b979225..0c73b07807e 100644 --- a/htdocs/user/group/ldap.php +++ b/htdocs/user/group/ldap.php @@ -92,7 +92,9 @@ if ($action == 'dolibarr2ldap') { $form = new Form($db); -llxHeader(); +$title = $object->name." - ".$langs->trans('LDAP'); +$help_url = ''; +llxHeader('', $title, $help_url); $head = group_prepare_head($object); diff --git a/htdocs/user/group/list.php b/htdocs/user/group/list.php index bf8bd407093..bb130b33e75 100644 --- a/htdocs/user/group/list.php +++ b/htdocs/user/group/list.php @@ -120,8 +120,8 @@ if (empty($reshook)) { /* * View */ - -llxHeader(); +$title = $langs->trans("ListOfGroups"); +llxHeader('', $title, $help_url); $sql = "SELECT g.rowid, g.nom as name, g.note, g.entity, g.datec, g.tms as datem, COUNT(DISTINCT ugu.fk_user) as nb, COUNT(DISTINCT ugr.fk_id) as nbpermissions"; $sql .= " FROM ".MAIN_DB_PREFIX."usergroup as g"; diff --git a/htdocs/user/group/perms.php b/htdocs/user/group/perms.php index 34e181469cc..edf20d0884c 100644 --- a/htdocs/user/group/perms.php +++ b/htdocs/user/group/perms.php @@ -128,7 +128,9 @@ if (empty($reshook)) { $form = new Form($db); -llxHeader('', $langs->trans("Permissions")); +$title = $object->name." - ".$langs->trans('Permissions'); +$help_url = ''; +llxHeader('', $title, $help_url); if ($object->id > 0) { $head = group_prepare_head($object); diff --git a/htdocs/user/home.php b/htdocs/user/home.php index c8dbdf2c1b8..b79476e7d5c 100644 --- a/htdocs/user/home.php +++ b/htdocs/user/home.php @@ -75,8 +75,9 @@ if (GETPOST('addbox')) { /* * View */ - -llxHeader(); +$title = $langs->trans("MenuUsersAndGroups"); +$help_url = ''; +llxHeader('', $title, $help_url); print load_fiche_titre($langs->trans("MenuUsersAndGroups"), $resultboxes['selectboxlist'], 'user'); diff --git a/htdocs/user/info.php b/htdocs/user/info.php index f6a0c731e14..6104df6f996 100644 --- a/htdocs/user/info.php +++ b/htdocs/user/info.php @@ -62,7 +62,10 @@ if (($object->id != $user->id) && (!$user->rights->user->user->lire)) { $form = new Form($db); -llxHeader(); +$person_name = !empty($object->firstname) ? $object->lastname.", ".$object->firstname : $object->lastname; +$title = $person_name." - ".$langs->trans('Info'); +$help_url = ''; +llxHeader('', $title, $help_url); $head = user_prepare_head($object); diff --git a/htdocs/user/ldap.php b/htdocs/user/ldap.php index 5e6cf57bfd4..8a8ca28092e 100644 --- a/htdocs/user/ldap.php +++ b/htdocs/user/ldap.php @@ -89,7 +89,10 @@ if (empty($reshook)) { $form = new Form($db); -llxHeader(); +$person_name = !empty($object->firstname) ? $object->lastname.", ".$object->firstname : $object->lastname; +$title = $person_name." - ".$langs->trans('LDAP'); +$help_url = ''; +llxHeader('', $title, $help_url); $head = user_prepare_head($object); diff --git a/htdocs/user/note.php b/htdocs/user/note.php index 801cafbbd52..a52b39aab09 100644 --- a/htdocs/user/note.php +++ b/htdocs/user/note.php @@ -84,11 +84,13 @@ if (empty($reshook)) { /* * View */ - -llxHeader(); - $form = new Form($db); +$person_name = !empty($object->firstname) ? $object->lastname.", ".$object->firstname : $object->lastname; +$title = $person_name." - ".$langs->trans('Notes'); +$help_url = ''; +llxHeader('', $title, $help_url); + if ($id) { $head = user_prepare_head($object); diff --git a/htdocs/user/param_ihm.php b/htdocs/user/param_ihm.php index 7916f4650d2..2823925fc24 100644 --- a/htdocs/user/param_ihm.php +++ b/htdocs/user/param_ihm.php @@ -178,8 +178,11 @@ if (empty($reshook)) { /* * View */ +$person_name = !empty($object->firstname) ? $object->lastname.", ".$object->firstname : $object->lastname; +$title = $person_name." - ".$langs->trans('Card'); +$help_url = ''; -llxHeader(); +llxHeader('', $title, $help_url); // List of possible landing pages $tmparray = array('index.php'=>'Dashboard'); diff --git a/htdocs/user/perms.php b/htdocs/user/perms.php index e8a4ed41a1c..d98b980f8ed 100644 --- a/htdocs/user/perms.php +++ b/htdocs/user/perms.php @@ -143,7 +143,10 @@ if (empty($reshook)) { $form = new Form($db); -llxHeader('', $langs->trans("Permissions")); +$person_name = !empty($object->firstname) ? $object->lastname.", ".$object->firstname : $object->lastname; +$title = $person_name." - ".$langs->trans('Permissions'); +$help_url = ''; +llxHeader('', $title, $help_url); $head = user_prepare_head($object); From daf8c0ff1ec07c8f5309563958c3db81cd3aa17e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 6 Jul 2022 19:19:47 +0200 Subject: [PATCH 147/826] Cherry pick --- htdocs/comm/propal/list.php | 2 +- htdocs/supplier_proposal/list.php | 2 +- htdocs/user/card.php | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/htdocs/comm/propal/list.php b/htdocs/comm/propal/list.php index ff3957b1382..3fabc1436f7 100644 --- a/htdocs/comm/propal/list.php +++ b/htdocs/comm/propal/list.php @@ -787,7 +787,7 @@ if ($resql) { exit; } -// llxHeader('', $langs->trans('Proposal'), $help_url); + // llxHeader('', $langs->trans('Proposal'), $help_url); $param = '&search_status='.urlencode($search_status); if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { diff --git a/htdocs/supplier_proposal/list.php b/htdocs/supplier_proposal/list.php index 1c347a2b23c..0bcd3ec46fc 100644 --- a/htdocs/supplier_proposal/list.php +++ b/htdocs/supplier_proposal/list.php @@ -469,7 +469,7 @@ if ($resql) { exit; } -// llxHeader('', $langs->trans('CommRequest'), $help_url); + // llxHeader('', $langs->trans('CommRequest'), $help_url); $param = ''; if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { diff --git a/htdocs/user/card.php b/htdocs/user/card.php index 563bb0284c2..f642fe8fd14 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -733,7 +733,6 @@ if (!empty($conf->stock->enabled)) { $help_url = ''; if ($action == 'create' || $action == 'adduserldap') { - $title = $langs->trans("NewUser"); llxHeader('', $title, $help_url); From 1a31704e18bfcaa057b287cf67e735696ab08c4c Mon Sep 17 00:00:00 2001 From: Christian Foellmann Date: Mon, 27 Jun 2022 12:59:06 +0200 Subject: [PATCH 148/826] remove old commented code --- htdocs/comm/propal/list.php | 2 -- htdocs/supplier_proposal/list.php | 2 -- 2 files changed, 4 deletions(-) diff --git a/htdocs/comm/propal/list.php b/htdocs/comm/propal/list.php index 3fabc1436f7..bc7f600b186 100644 --- a/htdocs/comm/propal/list.php +++ b/htdocs/comm/propal/list.php @@ -787,8 +787,6 @@ if ($resql) { exit; } - // llxHeader('', $langs->trans('Proposal'), $help_url); - $param = '&search_status='.urlencode($search_status); if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.urlencode($contextpage); diff --git a/htdocs/supplier_proposal/list.php b/htdocs/supplier_proposal/list.php index 0bcd3ec46fc..fcf909c15da 100644 --- a/htdocs/supplier_proposal/list.php +++ b/htdocs/supplier_proposal/list.php @@ -469,8 +469,6 @@ if ($resql) { exit; } - // llxHeader('', $langs->trans('CommRequest'), $help_url); - $param = ''; if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.urlencode($contextpage); From 572f1f0feefc1c6e2d7a9474a414282d10a4d4db Mon Sep 17 00:00:00 2001 From: Faustin Date: Thu, 7 Jul 2022 00:07:15 +0200 Subject: [PATCH 149/826] NEW : Recurrent events on agenda v2 --- htdocs/comm/action/card.php | 351 ++++++++++++++++++++++++++---------- 1 file changed, 253 insertions(+), 98 deletions(-) diff --git a/htdocs/comm/action/card.php b/htdocs/comm/action/card.php index ac943350819..6701b8e367f 100644 --- a/htdocs/comm/action/card.php +++ b/htdocs/comm/action/card.php @@ -414,117 +414,229 @@ if (empty($reshook) && $action == 'add') { if (!$error) { $db->begin(); - $dayoffset = 0; - $monthoffset = 0; + + + // Creation of action/event + $idaction = $object->create($user); + + if ($idaction > 0) { + if (!$object->error) { + // Category association + $categories = GETPOST('categories', 'array'); + $object->setCategories($categories); + + unset($_SESSION['assignedtouser']); + + $moreparam = ''; + if ($user->id != $object->userownerid) { + $moreparam = "filtert=-1"; // We force to remove filter so created record is visible when going back to per user view. + } + + // Create reminders + if ($addreminder == 'on') { + $actionCommReminder = new ActionCommReminder($db); + + $dateremind = dol_time_plus_duree($datep, -$offsetvalue, $offsetunit); + + $actionCommReminder->dateremind = $dateremind; + $actionCommReminder->typeremind = $remindertype; + $actionCommReminder->offsetunit = $offsetunit; + $actionCommReminder->offsetvalue = $offsetvalue; + $actionCommReminder->status = $actionCommReminder::STATUS_TODO; + $actionCommReminder->fk_actioncomm = $object->id; + if ($remindertype == 'email') { + $actionCommReminder->fk_email_template = $modelmail; + } + + // the notification must be created for every user assigned to the event + foreach ($object->userassigned as $userassigned) { + $actionCommReminder->fk_user = $userassigned['id']; + $res = $actionCommReminder->create($user); + + if ($res <= 0) { + // If error + $db->rollback(); + $langs->load("errors"); + $error = $langs->trans('ErrorReminderActionCommCreation'); + setEventMessages($error, null, 'errors'); + $action = 'create'; $donotclearsession = 1; + break; + } + } + } + + // Modify $moreparam so we are sure to see the event we have just created, whatever are the default value of filter on next page. + /*$moreparam .= ($moreparam ? '&' : '').'search_actioncode=0'; + $moreparam .= ($moreparam ? '&' : '').'search_status=-1'; + $moreparam .= ($moreparam ? '&' : '').'search_filtert='.$object->userownerid; + */ + $moreparam .= ($moreparam ? '&' : '').'disabledefaultvalues=1'; + + if ($error) { + $db->rollback(); + } else { + $db->commit(); + } + + // if (!empty($backtopage)) { + // dol_syslog("Back to ".$backtopage.($moreparam ? (preg_match('/\?/', $backtopage) ? '&'.$moreparam : '?'.$moreparam) : '')); + // header("Location: ".$backtopage.($moreparam ? (preg_match('/\?/', $backtopage) ? '&'.$moreparam : '?'.$moreparam) : '')); + // } elseif ($idaction) { + // header("Location: ".DOL_URL_ROOT.'/comm/action/card.php?id='.$idaction.($moreparam ? '&'.$moreparam : '')); + // } else { + // header("Location: ".DOL_URL_ROOT.'/comm/action/index.php'.($moreparam ? '?'.$moreparam : '')); + // } + // exit; + } else { + // If error + $db->rollback(); + $langs->load("errors"); + $error = $langs->trans($object->error); + setEventMessages($error, null, 'errors'); + $action = 'create'; $donotclearsession = 1; + } + } else { + $db->rollback(); + setEventMessages($object->error, $object->errors, 'errors'); + $action = 'create'; $donotclearsession = 1; + } + + $selectedrecurrulefreq = 'no'; + $selectedrecurrulebymonthday = ''; + $selectedrecurrulebyday = ''; + $object->recurrule = GETPOSTISSET('recurrulefreq') ? "FREQ=".GETPOST('recurrulefreq', 'alpha') : ""; + $object->recurrule .= GETPOSTISSET('BYMONTHDAY') ? "_BYMONTHDAY".GETPOST('BYMONTHDAY', 'alpha') : ""; + $object->recurrule .= GETPOSTISSET('BYDAY') ? "_BYDAY".GETPOST('BYDAY', 'alpha') : ""; + + if ($object->recurrule && preg_match('/FREQ=([A-Z]+)/i', $object->recurrule, $reg1)) { + $selectedrecurrulefreq = $reg1[1]; + } + if ($object->recurrule && preg_match('/FREQ=MONTHLY.*BYMONTHDAY(\d+)/i', $object->recurrule, $reg2)) { + $selectedrecurrulebymonthday = $reg2[1]; + } + if ($object->recurrule && preg_match('/FREQ=WEEKLY.*BYDAY(\d+)/i', $object->recurrule, $reg3)) { + $selectedrecurrulebyday = $reg3[1]; + } // If event is recurrent $userepeatevent = ($conf->global->MAIN_FEATURES_LEVEL == 2 ? 1 : 0); - if ($userepeatevent && GETPOSTISSET('recurrulefreq') && GETPOST('recurrulefreq') != 'no' && GETPOSTISSET("limityear") && GETPOSTISSET("limitmonth") && GETPOSTISSET("limitday")) { - $repeateventlimitdate = dol_mktime('23', '59', '59', GETPOST("limitmonth", 'int'), GETPOST("limitday", 'int'), GETPOST("limityear", 'int') < 2100 ? GETPOST("limityear", 'int') : 2100, $tzforfullday ? $tzforfullday : 'tzuser'); - if (GETPOST('recurrulefreq') == 'DAILY') { - $dayoffset = 1; - } elseif (GETPOST('recurrulefreq') == 'WEEKLY') { + if ($userepeatevent && !empty($selectedrecurrulefreq) && $selectedrecurrulefreq != 'no') { + // We set first date of recurrence and offsets + if ($selectedrecurrulefreq == 'WEEKLY' && !empty($selectedrecurrulebyday)) { + $firstdatearray = dol_get_first_day_week(GETPOST("apday", 'int'), GETPOST("apmonth", 'int'), GETPOST("apyear", 'int')); + $datep = dol_mktime($fulldayevent ? '00' : GETPOST("aphour", 'int'), $fulldayevent ? '00' : GETPOST("apmin", 'int'), $fulldayevent ? '00' : GETPOST("apsec", 'int'), $firstdatearray['month'], $firstdatearray['first_day'], $firstdatearray['year'], $tzforfullday ? $tzforfullday : 'tzuser'); + $datep = dol_time_plus_duree($datep, $selectedrecurrulebyday + 6, 'd');//We begin the week after $dayoffset = 7; - } elseif (GETPOST('recurrulefreq') == 'MONTHLY') { + $monthoffset = 0; + } elseif ($selectedrecurrulefreq == 'MONTHLY' && !empty($selectedrecurrulebymonthday)) { + $firstday = $selectedrecurrulebymonthday; + $firstmonth = GETPOST("apday") > $selectedrecurrulebymonthday ? GETPOST("apmonth", 'int') + 1 : GETPOST("apmonth", 'int');//We begin the week after + $datep = dol_mktime($fulldayevent ? '00' : GETPOST("aphour", 'int'), $fulldayevent ? '00' : GETPOST("apmin", 'int'), $fulldayevent ? '00' : GETPOST("apsec", 'int'), $firstmonth, $firstday, GETPOST("apyear", 'int'), $tzforfullday ? $tzforfullday : 'tzuser'); + $dayoffset = 0; $monthoffset = 1; + } else { + $error++; } - } else { // If event is not recurrent, limit date is the date of the event - $repeateventlimitdate = $datep; - } + // End date + $repeateventlimitdate = dol_mktime('23', '59', '59', GETPOSTISSET("limitmonth", 'int') ? GETPOST("limitmonth", 'int') : 01, GETPOSTISSET("limitday", 'int') ? GETPOST("limitday", 'int') : 01, GETPOSTISSET("limityear", 'int') && GETPOST("limityear", 'int') < 2100 ? GETPOST("limityear", 'int') : 2100, $tzforfullday ? $tzforfullday : 'tzuser'); + // Set date of end of event + $deltatime = num_between_day($object->datep, $datep); + $datef = dol_time_plus_duree($datef, $deltatime, 'd'); - while ($datep <= $repeateventlimitdate) { - $finalobject = clone $object; + while ($datep <= $repeateventlimitdate && !$error) { + $finalobject = clone $object; - $finalobject->datep = $datep; - $finalobject->datef = $datef; - // Creation of action/event - $idaction = $finalobject->create($user); + $finalobject->datep = $datep; + $finalobject->datef = $datef; + // Creation of action/event + $idaction = $finalobject->create($user); - if ($idaction > 0) { - if (!$finalobject->error) { - // Category association - $categories = GETPOST('categories', 'array'); - $finalobject->setCategories($categories); + if ($idaction > 0) { + if (!$finalobject->error) { + // Category association + $categories = GETPOST('categories', 'array'); + $finalobject->setCategories($categories); - unset($_SESSION['assignedtouser']); + unset($_SESSION['assignedtouser']); - $moreparam = ''; - if ($user->id != $finalobject->userownerid) { - $moreparam = "filtert=-1"; // We force to remove filter so created record is visible when going back to per user view. - } - - // Create reminders - if ($addreminder == 'on') { - $actionCommReminder = new ActionCommReminder($db); - - $dateremind = dol_time_plus_duree($datep, -$offsetvalue, $offsetunit); - - $actionCommReminder->dateremind = $dateremind; - $actionCommReminder->typeremind = $remindertype; - $actionCommReminder->offsetunit = $offsetunit; - $actionCommReminder->offsetvalue = $offsetvalue; - $actionCommReminder->status = $actionCommReminder::STATUS_TODO; - $actionCommReminder->fk_actioncomm = $finalobject->id; - if ($remindertype == 'email') { - $actionCommReminder->fk_email_template = $modelmail; + $moreparam = ''; + if ($user->id != $finalobject->userownerid) { + $moreparam = "filtert=-1"; // We force to remove filter so created record is visible when going back to per user view. } - // the notification must be created for every user assigned to the event - foreach ($finalobject->userassigned as $userassigned) { - $actionCommReminder->fk_user = $userassigned['id']; - $res = $actionCommReminder->create($user); + // Create reminders + if ($addreminder == 'on') { + $actionCommReminder = new ActionCommReminder($db); - if ($res <= 0) { - // If error - $db->rollback(); - $langs->load("errors"); - $error = $langs->trans('ErrorReminderActionCommCreation'); - setEventMessages($error, null, 'errors'); - $action = 'create'; $donotclearsession = 1; - break; + $dateremind = dol_time_plus_duree($datep, -$offsetvalue, $offsetunit); + + $actionCommReminder->dateremind = $dateremind; + $actionCommReminder->typeremind = $remindertype; + $actionCommReminder->offsetunit = $offsetunit; + $actionCommReminder->offsetvalue = $offsetvalue; + $actionCommReminder->status = $actionCommReminder::STATUS_TODO; + $actionCommReminder->fk_actioncomm = $finalobject->id; + if ($remindertype == 'email') { + $actionCommReminder->fk_email_template = $modelmail; + } + + // the notification must be created for every user assigned to the event + foreach ($finalobject->userassigned as $userassigned) { + $actionCommReminder->fk_user = $userassigned['id']; + $res = $actionCommReminder->create($user); + + if ($res <= 0) { + // If error + $db->rollback(); + $langs->load("errors"); + $error = $langs->trans('ErrorReminderActionCommCreation'); + setEventMessages($error, null, 'errors'); + $action = 'create'; $donotclearsession = 1; + break; + } } } - } - // Modify $moreparam so we are sure to see the event we have just created, whatever are the default value of filter on next page. - /*$moreparam .= ($moreparam ? '&' : '').'search_actioncode=0'; - $moreparam .= ($moreparam ? '&' : '').'search_status=-1'; - $moreparam .= ($moreparam ? '&' : '').'search_filtert='.$object->userownerid; - */ - $moreparam .= ($moreparam ? '&' : '').'disabledefaultvalues=1'; + // Modify $moreparam so we are sure to see the event we have just created, whatever are the default value of filter on next page. + /*$moreparam .= ($moreparam ? '&' : '').'search_actioncode=0'; + $moreparam .= ($moreparam ? '&' : '').'search_status=-1'; + $moreparam .= ($moreparam ? '&' : '').'search_filtert='.$object->userownerid; + */ + $moreparam .= ($moreparam ? '&' : '').'disabledefaultvalues=1'; - if ($error) { - $db->rollback(); + if ($error) { + $db->rollback(); + } else { + $db->commit(); + } } else { - $db->commit(); + // If error + $db->rollback(); + $langs->load("errors"); + $error = $langs->trans($finalobject->error); + setEventMessages($error, null, 'errors'); + $action = 'create'; $donotclearsession = 1; } } else { - // If error $db->rollback(); - $langs->load("errors"); - $error = $langs->trans($finalobject->error); - setEventMessages($error, null, 'errors'); + setEventMessages($finalobject->error, $finalobject->errors, 'errors'); $action = 'create'; $donotclearsession = 1; } - } else { - $db->rollback(); - setEventMessages($finalobject->error, $finalobject->errors, 'errors'); - $action = 'create'; $donotclearsession = 1; - } - // If event is not recurrent, we stop here - if (!($userepeatevent && GETPOSTISSET('recurrulefreq') && GETPOST('recurrulefreq') != 'no' && GETPOSTISSET("limityear") && GETPOSTISSET("limitmonth") && GETPOSTISSET("limitday"))) { - break; - } + // If event is not recurrent, we stop here + if (!($userepeatevent && GETPOSTISSET('recurrulefreq') && GETPOST('recurrulefreq') != 'no' && GETPOSTISSET("limityear") && GETPOSTISSET("limitmonth") && GETPOSTISSET("limitday"))) { + break; + } - // increment date for recurrent events - $datep = dol_time_plus_duree($datep, $dayoffset, 'd'); - $datep = dol_time_plus_duree($datep, $monthoffset, 'm'); - $datef = dol_time_plus_duree($datef, $dayoffset, 'd'); - $datef = dol_time_plus_duree($datef, $monthoffset, 'm'); + // increment date for recurrent events + $datep = dol_time_plus_duree($datep, $dayoffset, 'd'); + $datep = dol_time_plus_duree($datep, $monthoffset, 'm'); + $datef = dol_time_plus_duree($datef, $dayoffset, 'd'); + $datef = dol_time_plus_duree($datef, $monthoffset, 'm'); + } } - if (!empty($backtopage)) { + if (!empty($backtopage) && !$error) { dol_syslog("Back to ".$backtopage.($moreparam ? (preg_match('/\?/', $backtopage) ? '&'.$moreparam : '?'.$moreparam) : '')); header("Location: ".$backtopage.($moreparam ? (preg_match('/\?/', $backtopage) ? '&'.$moreparam : '?'.$moreparam) : '')); } elseif ($idaction) { @@ -1075,35 +1187,78 @@ if ($action == 'create') { print '        
'; print img_picto($langs->trans("Recurrence"), 'recurring', 'class="paddingright2"'); print ''; + $selectedrecurrulefreq = 'no'; + $selectedrecurrulebymonthday = ''; + $selectedrecurrulebyday = ''; + $object->recurrule = GETPOSTISSET('recurrulefreq') ? "FREQ=".GETPOST('recurrulefreq', 'alpha') : ""; + $object->recurrule .= GETPOSTISSET('BYMONTHDAY') ? "_BYMONTHDAY".GETPOST('BYMONTHDAY', 'alpha') : ""; + $object->recurrule .= GETPOSTISSET('BYDAY') ? "_BYDAY".GETPOST('BYDAY', 'alpha') : ""; + + if ($object->recurrule && preg_match('/FREQ=([A-Z]+)/i', $object->recurrule, $reg1)) { + $selectedrecurrulefreq = $reg1[1]; + } + if ($object->recurrule && preg_match('/FREQ=MONTHLY.*BYMONTHDAY(\d+)/i', $object->recurrule, $reg2)) { + $selectedrecurrulebymonthday = $reg2[1]; + } + if ($object->recurrule && preg_match('/FREQ=WEEKLY.*BYDAY(\d+)/i', $object->recurrule, $reg3)) { + $selectedrecurrulebyday = $reg3[1]; + } + print $form->selectarray('recurrulefreq', $arrayrecurrulefreq, $selectedrecurrulefreq, 0, 0, 0, '', 0, 0, 0, '', 'marginrightonly'); + // print ''; // For recursive event + + + // If recurrulefreq is MONTHLY + print ''; + // If recurrulefreq is WEEKLY + print ''; + // limit date $repeateventlimitdate = $repeateventlimitdate ? $repeateventlimitdate : ''; print ''; - print ''; + }); + '; print '
'; //print ''; } From 79924afabcaca0d4a76857e2f3c22fd53eec582e Mon Sep 17 00:00:00 2001 From: ButterflyOfFire <42316180+BoFFire@users.noreply.github.com> Date: Thu, 7 Jul 2022 09:08:08 +0100 Subject: [PATCH 150/826] Adding NIF verification for Algeria MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adding NIF verification for Algeria and link to validate professional ID via the Ministère des Finances. --- htdocs/societe/class/societe.class.php | 212 +++++++++++-------------- 1 file changed, 89 insertions(+), 123 deletions(-) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index d13893ca7dd..e8a530f3507 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -17,6 +17,7 @@ * Copyright (C) 2019-2020 Josep Lluís Amador * Copyright (C) 2019-2021 Frédéric France * Copyright (C) 2020 Open-Dsi + * Copyright (C) 2022 ButterflyOfFire * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -73,18 +74,18 @@ class Societe extends CommonObject * @var array List of child tables. To test if we can delete object. */ protected $childtables = array( - 'supplier_proposal' => array('name' => 'SupplierProposal'), - 'propal' => array('name' => 'Proposal'), - 'commande' => array('name' => 'Order'), - 'facture' => array('name' => 'Invoice'), - 'facture_rec' => array('name' => 'RecurringInvoiceTemplate'), - 'contrat' => array('name' => 'Contract'), - 'fichinter' => array('name' => 'Fichinter'), - 'facture_fourn' => array('name' => 'SupplierInvoice'), - 'commande_fournisseur' => array('name' => 'SupplierOrder'), - 'projet' => array('name' => 'Project'), - 'expedition' => array('name' => 'Shipment'), - 'prelevement_lignes' => array('name' => 'DirectDebitRecord'), + "supplier_proposal" => 'SupplierProposal', + "propal" => 'Proposal', + "commande" => 'Order', + "facture" => 'Invoice', + "facture_rec" => 'RecurringInvoiceTemplate', + "contrat" => 'Contract', + "fichinter" => 'Fichinter', + "facture_fourn" => 'SupplierInvoice', + "commande_fournisseur" => 'SupplierOrder', + "projet" => 'Project', + "expedition" => 'Shipment', + "prelevement_lignes" => 'DirectDebitRecord', ); /** @@ -92,22 +93,22 @@ class Societe extends CommonObject * if name like with @ClassName:FilePathClass:ParentFkFieldName' it will call method deleteByParentField (with parentId as parameters) and FieldName to fetch and delete child object */ protected $childtablesoncascade = array( - 'societe_prices', - 'societe_address', - 'product_fournisseur_price', - 'product_customer_price_log', - 'product_customer_price', - '@Contact:/contact/class/contact.class.php:fk_soc', - 'adherent', - 'societe_account', - 'societe_rib', - 'societe_remise', - 'societe_remise_except', - 'societe_commerciaux', - 'categorie', - 'notify', - 'notify_def', - 'actioncomm', + "societe_prices", + "societe_address", + "product_fournisseur_price", + "product_customer_price_log", + "product_customer_price", + "@Contact:/contact/class/contact.class.php:fk_soc", + "adherent", + "societe_account", + "societe_rib", + "societe_remise", + "societe_remise_except", + "societe_commerciaux", + "categorie", + "notify", + "notify_def", + "actioncomm", ); /** @@ -193,8 +194,8 @@ class Societe extends CommonObject 'tva_intra' =>array('type'=>'varchar(20)', 'label'=>'Tva intra', 'enabled'=>1, 'visible'=>-1, 'position'=>210), 'capital' =>array('type'=>'double(24,8)', 'label'=>'Capital', 'enabled'=>1, 'visible'=>-1, 'position'=>215), 'fk_stcomm' =>array('type'=>'integer', 'label'=>'CommercialStatus', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>220), - 'note_public' =>array('type'=>'text', 'label'=>'NotePublic', 'enabled'=>1, 'visible'=>0, 'position'=>225), - 'note_private' =>array('type'=>'text', 'label'=>'NotePrivate', 'enabled'=>1, 'visible'=>0, 'position'=>230), + 'note_private' =>array('type'=>'text', 'label'=>'NotePublic', 'enabled'=>1, 'visible'=>0, 'position'=>225), + 'note_public' =>array('type'=>'text', 'label'=>'NotePrivate', 'enabled'=>1, 'visible'=>0, 'position'=>230), 'prefix_comm' =>array('type'=>'varchar(5)', 'label'=>'Prefix comm', 'enabled'=>'$conf->global->SOCIETE_USEPREFIX', 'visible'=>-1, 'position'=>235), 'client' =>array('type'=>'tinyint(4)', 'label'=>'Client', 'enabled'=>1, 'visible'=>-1, 'position'=>240), 'fournisseur' =>array('type'=>'tinyint(4)', 'label'=>'Fournisseur', 'enabled'=>1, 'visible'=>-1, 'position'=>245), @@ -209,7 +210,6 @@ class Societe extends CommonObject //'remise_supplier' =>array('type'=>'double', 'label'=>'SupplierDiscount', 'enabled'=>1, 'visible'=>-1, 'position'=>290, 'isameasure'=>1), 'mode_reglement' =>array('type'=>'tinyint(4)', 'label'=>'Mode reglement', 'enabled'=>1, 'visible'=>-1, 'position'=>295), 'cond_reglement' =>array('type'=>'tinyint(4)', 'label'=>'Cond reglement', 'enabled'=>1, 'visible'=>-1, 'position'=>300), - 'deposit_percent' =>array('type'=>'varchar(63)', 'label'=>'DepositPercent', 'enabled'=>1, 'visible'=>-1, 'position'=>301), 'mode_reglement_supplier' =>array('type'=>'integer', 'label'=>'Mode reglement supplier', 'enabled'=>1, 'visible'=>-1, 'position'=>305), 'cond_reglement_supplier' =>array('type'=>'integer', 'label'=>'Cond reglement supplier', 'enabled'=>1, 'visible'=>-1, 'position'=>308), 'outstanding_limit' =>array('type'=>'double(24,8)', 'label'=>'OutstandingBill', 'enabled'=>1, 'visible'=>-1, 'position'=>310, 'isameasure'=>1), @@ -408,40 +408,18 @@ class Societe extends CommonObject */ public $idprof1; - /** - * @var string Professional ID 1 - * @deprecated - * @see $idprof1 - */ - public $siren; - - /** * Professional ID 2 (Ex: Siret in France) * @var string */ public $idprof2; - /** - * @var string Professional ID 2 - * @deprecated - * @see $idprof2 - */ - public $siret; - /** * Professional ID 3 (Ex: Ape in France) * @var string */ public $idprof3; - /** - * @var string Professional ID 3 - * @deprecated - * @see $idprof3 - */ - public $ape; - /** * Professional ID 4 (Ex: RCS in France) * @var string @@ -505,9 +483,6 @@ class Societe extends CommonObject public $remise_percent; public $remise_supplier_percent; - public $mode_reglement_id; - public $cond_reglement_id; - public $deposit_percent; public $mode_reglement_supplier_id; public $cond_reglement_supplier_id; public $transport_mode_supplier_id; @@ -526,19 +501,18 @@ class Societe extends CommonObject /** * Date of last update - * @var integer|string + * @var string */ public $date_modification; /** * User that made last update - * @var User + * @var string */ public $user_modification; /** - * Date of creation - * @var integer|string + * @var integer|string date_creation */ public $date_creation; @@ -942,8 +916,8 @@ class Societe extends CommonObject $sql .= ", accountancy_code_sell"; } $sql .= ") VALUES ('".$this->db->escape($this->name)."', '".$this->db->escape($this->name_alias)."', ".((int) $this->entity).", '".$this->db->idate($now)."'"; - $sql .= ", ".(!empty($user->id) ? ((int) $user->id) : "null"); $sql .= ", ".(!empty($this->typent_id) ? ((int) $this->typent_id) : "null"); + $sql .= ", ".(!empty($user->id) ? ((int) $user->id) : "null"); $sql .= ", ".(!empty($this->canvas) ? "'".$this->db->escape($this->canvas)."'" : "null"); $sql .= ", ".((int) $this->status); $sql .= ", ".(!empty($this->ref_ext) ? "'".$this->db->escape($this->ref_ext)."'" : "null"); @@ -979,7 +953,7 @@ class Societe extends CommonObject $sql .= ", accountancy_code_sell"; $sql .= ") VALUES ("; $sql .= $this->id; - $sql .= ", ".((int) $conf->entity); + $sql .= ", ".$conf->entity; $sql .= ", '".$this->db->escape($this->accountancy_code_customer)."'"; $sql .= ", '".$this->db->escape($this->accountancy_code_supplier)."'"; $sql .= ", '".$this->db->escape($this->accountancy_code_buy)."'"; @@ -1105,7 +1079,7 @@ class Societe extends CommonObject } } - if (empty($error)) { + if (!empty($error)) { dol_syslog(get_class($this)."::create_individual success"); $this->db->commit(); } else { @@ -1477,19 +1451,16 @@ class Societe extends CommonObject $sql .= ",prefix_comm = ".(!empty($this->prefix_comm) ? "'".$this->db->escape($this->prefix_comm)."'" : "null"); - $sql .= ",fk_effectif = ".($this->effectif_id > 0 ? ((int) $this->effectif_id) : "null"); + $sql .= ",fk_effectif = ".(!empty($this->effectif_id) ? "'".$this->db->escape($this->effectif_id)."'" : "null"); if (isset($this->stcomm_id)) { - $sql .= ",fk_stcomm=".($this->stcomm_id > 0 ? ((int) $this->stcomm_id) : "0"); - } - if (isset($this->typent_id)) { - $sql .= ",fk_typent = ".($this->typent_id > 0 ? ((int) $this->typent_id) : "0"); + $sql .= ",fk_stcomm=".(!empty($this->stcomm_id) ? $this->stcomm_id : "0"); } + $sql .= ",fk_typent = ".(!empty($this->typent_id) ? "'".$this->db->escape($this->typent_id)."'" : "0"); $sql .= ",fk_forme_juridique = ".(!empty($this->forme_juridique_code) ? "'".$this->db->escape($this->forme_juridique_code)."'" : "null"); $sql .= ",mode_reglement = ".(!empty($this->mode_reglement_id) ? "'".$this->db->escape($this->mode_reglement_id)."'" : "null"); $sql .= ",cond_reglement = ".(!empty($this->cond_reglement_id) ? "'".$this->db->escape($this->cond_reglement_id)."'" : "null"); - $sql .= ",deposit_percent = ".(!empty($this->deposit_percent) ? "'".$this->db->escape($this->deposit_percent)."'" : "null"); $sql .= ",transport_mode = ".(!empty($this->transport_mode_id) ? "'".$this->db->escape($this->transport_mode_id)."'" : "null"); $sql .= ",mode_reglement_supplier = ".(!empty($this->mode_reglement_supplier_id) ? "'".$this->db->escape($this->mode_reglement_supplier_id)."'" : "null"); $sql .= ",cond_reglement_supplier = ".(!empty($this->cond_reglement_supplier_id) ? "'".$this->db->escape($this->cond_reglement_supplier_id)."'" : "null"); @@ -1719,7 +1690,7 @@ class Societe extends CommonObject $sql .= ', spe.accountancy_code_customer as code_compta, spe.accountancy_code_supplier as code_compta_fournisseur, spe.accountancy_code_buy, spe.accountancy_code_sell'; } $sql .= ', s.code_client, s.code_fournisseur, s.parent, s.barcode'; - $sql .= ', s.fk_departement as state_id, s.fk_pays as country_id, s.fk_stcomm, s.mode_reglement, s.cond_reglement, s.deposit_percent, s.transport_mode'; + $sql .= ', s.fk_departement as state_id, s.fk_pays as country_id, s.fk_stcomm, s.mode_reglement, s.cond_reglement, s.transport_mode'; $sql .= ', s.fk_account, s.tva_assuj'; $sql .= ', s.mode_reglement_supplier, s.cond_reglement_supplier, s.transport_mode_supplier'; $sql .= ', s.localtax1_assuj, s.localtax1_value, s.localtax2_assuj, s.localtax2_value, s.fk_prospectlevel, s.default_lang, s.logo, s.logo_squarred'; @@ -1897,7 +1868,6 @@ class Societe extends CommonObject $this->mode_reglement_id = $obj->mode_reglement; $this->cond_reglement_id = $obj->cond_reglement; - $this->deposit_percent = $obj->deposit_percent; $this->transport_mode_id = $obj->transport_mode; $this->mode_reglement_supplier_id = $obj->mode_reglement_supplier; $this->cond_reglement_supplier_id = $obj->cond_reglement_supplier; @@ -2561,10 +2531,9 @@ class Societe extends CommonObject * @param int $notooltip 1=Disable tooltip * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking * @param int $noaliasinname 1=Do not add alias into the link ref - * @param string $target add attribute target * @return string String with URL */ - public function getNomUrl($withpicto = 0, $option = '', $maxlen = 0, $notooltip = 0, $save_lastsearch_value = -1, $noaliasinname = 0, $target = '') + public function getNomUrl($withpicto = 0, $option = '', $maxlen = 0, $notooltip = 0, $save_lastsearch_value = -1, $noaliasinname = 0) { global $conf, $langs, $hookmanager; @@ -2737,10 +2706,13 @@ class Societe extends CommonObject } $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"'; $linkclose .= ' class="classfortooltip refurl"'; - $target_value = array('_self', '_blank', '_parent', '_top'); - if (in_array($target, $target_value)) { - $linkclose .= ' target="'.dol_escape_htmltag($target).'"'; - } + + /* + $hookmanager->initHooks(array('thirdpartydao')); + $parameters=array('id'=>$this->id); + $reshook=$hookmanager->executeHooks('getnomurltooltip',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks + if ($reshook > 0) $linkclose = $hookmanager->resPrint; + */ } $linkstart .= $linkclose.'>'; $linkend = ''; @@ -2764,7 +2736,7 @@ class Societe extends CommonObject $hookmanager->initHooks(array('thirdpartydao')); $parameters = array( 'id'=>$this->id, - 'getnomurl' => &$result, + 'getnomurl'=>$result, 'withpicto '=> $withpicto, 'option'=> $option, 'maxlen'=> $maxlen, @@ -2784,30 +2756,29 @@ class Societe extends CommonObject /** * Return link(s) on type of thirdparty (with picto) * - * @param int $withpicto Add picto into link (0=No picto, 1=Include picto with link, 2=Picto only) - * @param string $option ''=All - * @param int $notooltip 1=Disable tooltip - * @param string $tag Tag 'a' or 'span' - * @return string String with URL + * @param int $withpicto Add picto into link (0=No picto, 1=Include picto with link, 2=Picto only) + * @param string $option ''=All + * @param int $notooltip 1=Disable tooltip + * @return string String with URL */ - public function getTypeUrl($withpicto = 0, $option = '', $notooltip = 0, $tag = 'a') + public function getTypeUrl($withpicto = 0, $option = '', $notooltip = 0) { global $conf, $langs; $s = ''; if (empty($option) || preg_match('/prospect/', $option)) { if (($this->client == 2 || $this->client == 3) && empty($conf->global->SOCIETE_DISABLE_PROSPECTS)) { - $s .= '<'.$tag.' class="customer-back opacitymedium" title="'.$langs->trans("Prospect").'" href="'.DOL_URL_ROOT.'/comm/card.php?socid='.$this->id.'">'.dol_substr($langs->trans("Prospect"), 0, 1).''; + $s .= ''.dol_substr($langs->trans("Prospect"), 0, 1).''; } } if (empty($option) || preg_match('/customer/', $option)) { if (($this->client == 1 || $this->client == 3) && empty($conf->global->SOCIETE_DISABLE_CUSTOMERS)) { - $s .= '<'.$tag.' class="customer-back" title="'.$langs->trans("Customer").'" href="'.DOL_URL_ROOT.'/comm/card.php?socid='.$this->id.'">'.dol_substr($langs->trans("Customer"), 0, 1).''; + $s .= ''.dol_substr($langs->trans("Customer"), 0, 1).''; } } if (empty($option) || preg_match('/supplier/', $option)) { if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) && $this->fournisseur) { - $s .= '<'.$tag.' class="vendor-back" title="'.$langs->trans("Supplier").'" href="'.DOL_URL_ROOT.'/fourn/card.php?socid='.$this->id.'">'.dol_substr($langs->trans("Supplier"), 0, 1).''; + $s .= ''.dol_substr($langs->trans("Supplier"), 0, 1).''; } } return $s; @@ -3487,37 +3458,6 @@ class Societe extends CommonObject } } - /** - * Get parents for company - * - * @param int $company_id ID of company to search parent - * @param array $parents List of companies ID found - * @return array - */ - public function getParentsForCompany($company_id, $parents = []) - { - global $langs; - - if ($company_id > 0) { - $sql = "SELECT parent FROM " . MAIN_DB_PREFIX . "societe WHERE rowid = $company_id"; - $resql = $this->db->query($sql); - if ($resql) { - if ($obj = $this->db->fetch_object($resql)) { - $parent = $obj->parent; - if ($parent > 0 && !in_array($parent, $parents)) { - $parents[] = $parent; - return $this->getParentsForCompany($parent, $parents); - } else { - return $parents; - } - } - $this->db->free($resql); - } else { - setEventMessage($langs->trans('GetCompanyParentsError', $this->db->lasterror()), 'errors'); - } - } - } - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Returns if a profid sould be verified to be unique @@ -3789,6 +3729,20 @@ class Societe extends CommonObject return -1; } } + + //Verify NIF if country is DZ + //Returns: 1 if NIF ok, -1 if NIF bad, 0 if unexpected bad + if ($idprof == 1 && $soc->country_code == 'DZ') { + $string = trim($this->idprof1); + $string = preg_replace('/(\s)/', '', $string); + + //Check NIF + if (preg_match('/(^[0-9]{15}$)/', $string)) { + return 1; + } else { + return -1; + } + } return $ok; } @@ -3832,6 +3786,9 @@ class Societe extends CommonObject if ($idprof == 1 && $thirdparty->country_code == 'IN') { $url = 'http://www.tinxsys.com/TinxsysInternetWeb/dealerControllerServlet?tinNumber='.$strippedIdProf1.';&searchBy=TIN&backPage=searchByTin_Inter.jsp'; } + if ($idprof == 1 && $thirdparty->country_code == 'DZ') { + $url = 'http://nif.mfdgi.gov.dz/nif.asp?Nif='.$strippedIdProf1; + } if ($idprof == 1 && $thirdparty->country_code == 'PT') { $url = 'http://www.nif.pt/'.$strippedIdProf1; } @@ -3877,7 +3834,7 @@ class Societe extends CommonObject */ public function info($id) { - $sql = "SELECT s.rowid, s.nom as name, s.datec, tms as datem,"; + $sql = "SELECT s.rowid, s.nom as name, s.datec as date_creation, tms as date_modification,"; $sql .= " fk_user_creat, fk_user_modif"; $sql .= " FROM ".MAIN_DB_PREFIX."societe as s"; $sql .= " WHERE s.rowid = ".((int) $id); @@ -3889,12 +3846,21 @@ class Societe extends CommonObject $this->id = $obj->rowid; - $this->user_creation_id = $obj->fk_user_creat; - $this->user_modification_id = $obj->fk_user_modif; - $this->date_creation = $this->db->jdate($obj->datec); - $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem); + if ($obj->fk_user_creat) { + $cuser = new User($this->db); + $cuser->fetch($obj->fk_user_creat); + $this->user_creation = $cuser; + } + + if ($obj->fk_user_modif) { + $muser = new User($this->db); + $muser->fetch($obj->fk_user_modif); + $this->user_modification = $muser; + } $this->ref = $obj->name; + $this->date_creation = $this->db->jdate($obj->date_creation); + $this->date_modification = $this->db->jdate($obj->date_modification); } $this->db->free($result); From 2c346bc616e68592041f0639b9f764d318f060ab Mon Sep 17 00:00:00 2001 From: ButterflyOfFire <42316180+BoFFire@users.noreply.github.com> Date: Thu, 7 Jul 2022 09:22:49 +0100 Subject: [PATCH 151/826] Update societe.class.php Reverting first commit to initial and rework NIF DZ. --- htdocs/societe/class/societe.class.php | 195 ++++++++++++++++--------- 1 file changed, 123 insertions(+), 72 deletions(-) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index e8a530f3507..5ade14c7377 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -17,7 +17,6 @@ * Copyright (C) 2019-2020 Josep Lluís Amador * Copyright (C) 2019-2021 Frédéric France * Copyright (C) 2020 Open-Dsi - * Copyright (C) 2022 ButterflyOfFire * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -74,18 +73,18 @@ class Societe extends CommonObject * @var array List of child tables. To test if we can delete object. */ protected $childtables = array( - "supplier_proposal" => 'SupplierProposal', - "propal" => 'Proposal', - "commande" => 'Order', - "facture" => 'Invoice', - "facture_rec" => 'RecurringInvoiceTemplate', - "contrat" => 'Contract', - "fichinter" => 'Fichinter', - "facture_fourn" => 'SupplierInvoice', - "commande_fournisseur" => 'SupplierOrder', - "projet" => 'Project', - "expedition" => 'Shipment', - "prelevement_lignes" => 'DirectDebitRecord', + 'supplier_proposal' => array('name' => 'SupplierProposal'), + 'propal' => array('name' => 'Proposal'), + 'commande' => array('name' => 'Order'), + 'facture' => array('name' => 'Invoice'), + 'facture_rec' => array('name' => 'RecurringInvoiceTemplate'), + 'contrat' => array('name' => 'Contract'), + 'fichinter' => array('name' => 'Fichinter'), + 'facture_fourn' => array('name' => 'SupplierInvoice'), + 'commande_fournisseur' => array('name' => 'SupplierOrder'), + 'projet' => array('name' => 'Project'), + 'expedition' => array('name' => 'Shipment'), + 'prelevement_lignes' => array('name' => 'DirectDebitRecord'), ); /** @@ -93,22 +92,22 @@ class Societe extends CommonObject * if name like with @ClassName:FilePathClass:ParentFkFieldName' it will call method deleteByParentField (with parentId as parameters) and FieldName to fetch and delete child object */ protected $childtablesoncascade = array( - "societe_prices", - "societe_address", - "product_fournisseur_price", - "product_customer_price_log", - "product_customer_price", - "@Contact:/contact/class/contact.class.php:fk_soc", - "adherent", - "societe_account", - "societe_rib", - "societe_remise", - "societe_remise_except", - "societe_commerciaux", - "categorie", - "notify", - "notify_def", - "actioncomm", + 'societe_prices', + 'societe_address', + 'product_fournisseur_price', + 'product_customer_price_log', + 'product_customer_price', + '@Contact:/contact/class/contact.class.php:fk_soc', + 'adherent', + 'societe_account', + 'societe_rib', + 'societe_remise', + 'societe_remise_except', + 'societe_commerciaux', + 'categorie', + 'notify', + 'notify_def', + 'actioncomm', ); /** @@ -194,8 +193,8 @@ class Societe extends CommonObject 'tva_intra' =>array('type'=>'varchar(20)', 'label'=>'Tva intra', 'enabled'=>1, 'visible'=>-1, 'position'=>210), 'capital' =>array('type'=>'double(24,8)', 'label'=>'Capital', 'enabled'=>1, 'visible'=>-1, 'position'=>215), 'fk_stcomm' =>array('type'=>'integer', 'label'=>'CommercialStatus', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>220), - 'note_private' =>array('type'=>'text', 'label'=>'NotePublic', 'enabled'=>1, 'visible'=>0, 'position'=>225), - 'note_public' =>array('type'=>'text', 'label'=>'NotePrivate', 'enabled'=>1, 'visible'=>0, 'position'=>230), + 'note_public' =>array('type'=>'text', 'label'=>'NotePublic', 'enabled'=>1, 'visible'=>0, 'position'=>225), + 'note_private' =>array('type'=>'text', 'label'=>'NotePrivate', 'enabled'=>1, 'visible'=>0, 'position'=>230), 'prefix_comm' =>array('type'=>'varchar(5)', 'label'=>'Prefix comm', 'enabled'=>'$conf->global->SOCIETE_USEPREFIX', 'visible'=>-1, 'position'=>235), 'client' =>array('type'=>'tinyint(4)', 'label'=>'Client', 'enabled'=>1, 'visible'=>-1, 'position'=>240), 'fournisseur' =>array('type'=>'tinyint(4)', 'label'=>'Fournisseur', 'enabled'=>1, 'visible'=>-1, 'position'=>245), @@ -210,6 +209,7 @@ class Societe extends CommonObject //'remise_supplier' =>array('type'=>'double', 'label'=>'SupplierDiscount', 'enabled'=>1, 'visible'=>-1, 'position'=>290, 'isameasure'=>1), 'mode_reglement' =>array('type'=>'tinyint(4)', 'label'=>'Mode reglement', 'enabled'=>1, 'visible'=>-1, 'position'=>295), 'cond_reglement' =>array('type'=>'tinyint(4)', 'label'=>'Cond reglement', 'enabled'=>1, 'visible'=>-1, 'position'=>300), + 'deposit_percent' =>array('type'=>'varchar(63)', 'label'=>'DepositPercent', 'enabled'=>1, 'visible'=>-1, 'position'=>301), 'mode_reglement_supplier' =>array('type'=>'integer', 'label'=>'Mode reglement supplier', 'enabled'=>1, 'visible'=>-1, 'position'=>305), 'cond_reglement_supplier' =>array('type'=>'integer', 'label'=>'Cond reglement supplier', 'enabled'=>1, 'visible'=>-1, 'position'=>308), 'outstanding_limit' =>array('type'=>'double(24,8)', 'label'=>'OutstandingBill', 'enabled'=>1, 'visible'=>-1, 'position'=>310, 'isameasure'=>1), @@ -408,18 +408,40 @@ class Societe extends CommonObject */ public $idprof1; + /** + * @var string Professional ID 1 + * @deprecated + * @see $idprof1 + */ + public $siren; + + /** * Professional ID 2 (Ex: Siret in France) * @var string */ public $idprof2; + /** + * @var string Professional ID 2 + * @deprecated + * @see $idprof2 + */ + public $siret; + /** * Professional ID 3 (Ex: Ape in France) * @var string */ public $idprof3; + /** + * @var string Professional ID 3 + * @deprecated + * @see $idprof3 + */ + public $ape; + /** * Professional ID 4 (Ex: RCS in France) * @var string @@ -483,6 +505,9 @@ class Societe extends CommonObject public $remise_percent; public $remise_supplier_percent; + public $mode_reglement_id; + public $cond_reglement_id; + public $deposit_percent; public $mode_reglement_supplier_id; public $cond_reglement_supplier_id; public $transport_mode_supplier_id; @@ -501,18 +526,19 @@ class Societe extends CommonObject /** * Date of last update - * @var string + * @var integer|string */ public $date_modification; /** * User that made last update - * @var string + * @var User */ public $user_modification; /** - * @var integer|string date_creation + * Date of creation + * @var integer|string */ public $date_creation; @@ -916,8 +942,8 @@ class Societe extends CommonObject $sql .= ", accountancy_code_sell"; } $sql .= ") VALUES ('".$this->db->escape($this->name)."', '".$this->db->escape($this->name_alias)."', ".((int) $this->entity).", '".$this->db->idate($now)."'"; - $sql .= ", ".(!empty($this->typent_id) ? ((int) $this->typent_id) : "null"); $sql .= ", ".(!empty($user->id) ? ((int) $user->id) : "null"); + $sql .= ", ".(!empty($this->typent_id) ? ((int) $this->typent_id) : "null"); $sql .= ", ".(!empty($this->canvas) ? "'".$this->db->escape($this->canvas)."'" : "null"); $sql .= ", ".((int) $this->status); $sql .= ", ".(!empty($this->ref_ext) ? "'".$this->db->escape($this->ref_ext)."'" : "null"); @@ -953,7 +979,7 @@ class Societe extends CommonObject $sql .= ", accountancy_code_sell"; $sql .= ") VALUES ("; $sql .= $this->id; - $sql .= ", ".$conf->entity; + $sql .= ", ".((int) $conf->entity); $sql .= ", '".$this->db->escape($this->accountancy_code_customer)."'"; $sql .= ", '".$this->db->escape($this->accountancy_code_supplier)."'"; $sql .= ", '".$this->db->escape($this->accountancy_code_buy)."'"; @@ -1079,7 +1105,7 @@ class Societe extends CommonObject } } - if (!empty($error)) { + if (empty($error)) { dol_syslog(get_class($this)."::create_individual success"); $this->db->commit(); } else { @@ -1451,16 +1477,19 @@ class Societe extends CommonObject $sql .= ",prefix_comm = ".(!empty($this->prefix_comm) ? "'".$this->db->escape($this->prefix_comm)."'" : "null"); - $sql .= ",fk_effectif = ".(!empty($this->effectif_id) ? "'".$this->db->escape($this->effectif_id)."'" : "null"); + $sql .= ",fk_effectif = ".($this->effectif_id > 0 ? ((int) $this->effectif_id) : "null"); if (isset($this->stcomm_id)) { - $sql .= ",fk_stcomm=".(!empty($this->stcomm_id) ? $this->stcomm_id : "0"); + $sql .= ",fk_stcomm=".($this->stcomm_id > 0 ? ((int) $this->stcomm_id) : "0"); + } + if (isset($this->typent_id)) { + $sql .= ",fk_typent = ".($this->typent_id > 0 ? ((int) $this->typent_id) : "0"); } - $sql .= ",fk_typent = ".(!empty($this->typent_id) ? "'".$this->db->escape($this->typent_id)."'" : "0"); $sql .= ",fk_forme_juridique = ".(!empty($this->forme_juridique_code) ? "'".$this->db->escape($this->forme_juridique_code)."'" : "null"); $sql .= ",mode_reglement = ".(!empty($this->mode_reglement_id) ? "'".$this->db->escape($this->mode_reglement_id)."'" : "null"); $sql .= ",cond_reglement = ".(!empty($this->cond_reglement_id) ? "'".$this->db->escape($this->cond_reglement_id)."'" : "null"); + $sql .= ",deposit_percent = ".(!empty($this->deposit_percent) ? "'".$this->db->escape($this->deposit_percent)."'" : "null"); $sql .= ",transport_mode = ".(!empty($this->transport_mode_id) ? "'".$this->db->escape($this->transport_mode_id)."'" : "null"); $sql .= ",mode_reglement_supplier = ".(!empty($this->mode_reglement_supplier_id) ? "'".$this->db->escape($this->mode_reglement_supplier_id)."'" : "null"); $sql .= ",cond_reglement_supplier = ".(!empty($this->cond_reglement_supplier_id) ? "'".$this->db->escape($this->cond_reglement_supplier_id)."'" : "null"); @@ -1690,7 +1719,7 @@ class Societe extends CommonObject $sql .= ', spe.accountancy_code_customer as code_compta, spe.accountancy_code_supplier as code_compta_fournisseur, spe.accountancy_code_buy, spe.accountancy_code_sell'; } $sql .= ', s.code_client, s.code_fournisseur, s.parent, s.barcode'; - $sql .= ', s.fk_departement as state_id, s.fk_pays as country_id, s.fk_stcomm, s.mode_reglement, s.cond_reglement, s.transport_mode'; + $sql .= ', s.fk_departement as state_id, s.fk_pays as country_id, s.fk_stcomm, s.mode_reglement, s.cond_reglement, s.deposit_percent, s.transport_mode'; $sql .= ', s.fk_account, s.tva_assuj'; $sql .= ', s.mode_reglement_supplier, s.cond_reglement_supplier, s.transport_mode_supplier'; $sql .= ', s.localtax1_assuj, s.localtax1_value, s.localtax2_assuj, s.localtax2_value, s.fk_prospectlevel, s.default_lang, s.logo, s.logo_squarred'; @@ -1868,6 +1897,7 @@ class Societe extends CommonObject $this->mode_reglement_id = $obj->mode_reglement; $this->cond_reglement_id = $obj->cond_reglement; + $this->deposit_percent = $obj->deposit_percent; $this->transport_mode_id = $obj->transport_mode; $this->mode_reglement_supplier_id = $obj->mode_reglement_supplier; $this->cond_reglement_supplier_id = $obj->cond_reglement_supplier; @@ -2531,9 +2561,10 @@ class Societe extends CommonObject * @param int $notooltip 1=Disable tooltip * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking * @param int $noaliasinname 1=Do not add alias into the link ref + * @param string $target add attribute target * @return string String with URL */ - public function getNomUrl($withpicto = 0, $option = '', $maxlen = 0, $notooltip = 0, $save_lastsearch_value = -1, $noaliasinname = 0) + public function getNomUrl($withpicto = 0, $option = '', $maxlen = 0, $notooltip = 0, $save_lastsearch_value = -1, $noaliasinname = 0, $target = '') { global $conf, $langs, $hookmanager; @@ -2706,13 +2737,10 @@ class Societe extends CommonObject } $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"'; $linkclose .= ' class="classfortooltip refurl"'; - - /* - $hookmanager->initHooks(array('thirdpartydao')); - $parameters=array('id'=>$this->id); - $reshook=$hookmanager->executeHooks('getnomurltooltip',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks - if ($reshook > 0) $linkclose = $hookmanager->resPrint; - */ + $target_value = array('_self', '_blank', '_parent', '_top'); + if (in_array($target, $target_value)) { + $linkclose .= ' target="'.dol_escape_htmltag($target).'"'; + } } $linkstart .= $linkclose.'>'; $linkend = ''; @@ -2736,7 +2764,7 @@ class Societe extends CommonObject $hookmanager->initHooks(array('thirdpartydao')); $parameters = array( 'id'=>$this->id, - 'getnomurl'=>$result, + 'getnomurl' => &$result, 'withpicto '=> $withpicto, 'option'=> $option, 'maxlen'=> $maxlen, @@ -2756,29 +2784,30 @@ class Societe extends CommonObject /** * Return link(s) on type of thirdparty (with picto) * - * @param int $withpicto Add picto into link (0=No picto, 1=Include picto with link, 2=Picto only) - * @param string $option ''=All - * @param int $notooltip 1=Disable tooltip - * @return string String with URL + * @param int $withpicto Add picto into link (0=No picto, 1=Include picto with link, 2=Picto only) + * @param string $option ''=All + * @param int $notooltip 1=Disable tooltip + * @param string $tag Tag 'a' or 'span' + * @return string String with URL */ - public function getTypeUrl($withpicto = 0, $option = '', $notooltip = 0) + public function getTypeUrl($withpicto = 0, $option = '', $notooltip = 0, $tag = 'a') { global $conf, $langs; $s = ''; if (empty($option) || preg_match('/prospect/', $option)) { if (($this->client == 2 || $this->client == 3) && empty($conf->global->SOCIETE_DISABLE_PROSPECTS)) { - $s .= ''.dol_substr($langs->trans("Prospect"), 0, 1).''; + $s .= '<'.$tag.' class="customer-back opacitymedium" title="'.$langs->trans("Prospect").'" href="'.DOL_URL_ROOT.'/comm/card.php?socid='.$this->id.'">'.dol_substr($langs->trans("Prospect"), 0, 1).''; } } if (empty($option) || preg_match('/customer/', $option)) { if (($this->client == 1 || $this->client == 3) && empty($conf->global->SOCIETE_DISABLE_CUSTOMERS)) { - $s .= ''.dol_substr($langs->trans("Customer"), 0, 1).''; + $s .= '<'.$tag.' class="customer-back" title="'.$langs->trans("Customer").'" href="'.DOL_URL_ROOT.'/comm/card.php?socid='.$this->id.'">'.dol_substr($langs->trans("Customer"), 0, 1).''; } } if (empty($option) || preg_match('/supplier/', $option)) { if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) && $this->fournisseur) { - $s .= ''.dol_substr($langs->trans("Supplier"), 0, 1).''; + $s .= '<'.$tag.' class="vendor-back" title="'.$langs->trans("Supplier").'" href="'.DOL_URL_ROOT.'/fourn/card.php?socid='.$this->id.'">'.dol_substr($langs->trans("Supplier"), 0, 1).''; } } return $s; @@ -3458,6 +3487,37 @@ class Societe extends CommonObject } } + /** + * Get parents for company + * + * @param int $company_id ID of company to search parent + * @param array $parents List of companies ID found + * @return array + */ + public function getParentsForCompany($company_id, $parents = []) + { + global $langs; + + if ($company_id > 0) { + $sql = "SELECT parent FROM " . MAIN_DB_PREFIX . "societe WHERE rowid = $company_id"; + $resql = $this->db->query($sql); + if ($resql) { + if ($obj = $this->db->fetch_object($resql)) { + $parent = $obj->parent; + if ($parent > 0 && !in_array($parent, $parents)) { + $parents[] = $parent; + return $this->getParentsForCompany($parent, $parents); + } else { + return $parents; + } + } + $this->db->free($resql); + } else { + setEventMessage($langs->trans('GetCompanyParentsError', $this->db->lasterror()), 'errors'); + } + } + } + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Returns if a profid sould be verified to be unique @@ -3834,7 +3894,7 @@ class Societe extends CommonObject */ public function info($id) { - $sql = "SELECT s.rowid, s.nom as name, s.datec as date_creation, tms as date_modification,"; + $sql = "SELECT s.rowid, s.nom as name, s.datec, tms as datem,"; $sql .= " fk_user_creat, fk_user_modif"; $sql .= " FROM ".MAIN_DB_PREFIX."societe as s"; $sql .= " WHERE s.rowid = ".((int) $id); @@ -3846,21 +3906,12 @@ class Societe extends CommonObject $this->id = $obj->rowid; - if ($obj->fk_user_creat) { - $cuser = new User($this->db); - $cuser->fetch($obj->fk_user_creat); - $this->user_creation = $cuser; - } - - if ($obj->fk_user_modif) { - $muser = new User($this->db); - $muser->fetch($obj->fk_user_modif); - $this->user_modification = $muser; - } + $this->user_creation_id = $obj->fk_user_creat; + $this->user_modification_id = $obj->fk_user_modif; + $this->date_creation = $this->db->jdate($obj->datec); + $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem); $this->ref = $obj->name; - $this->date_creation = $this->db->jdate($obj->date_creation); - $this->date_modification = $this->db->jdate($obj->date_modification); } $this->db->free($result); From 6fb76ac6a536bbe30c9eb9512df6ade93273a61c Mon Sep 17 00:00:00 2001 From: ButterflyOfFire <42316180+BoFFire@users.noreply.github.com> Date: Thu, 7 Jul 2022 09:24:35 +0100 Subject: [PATCH 152/826] Adding missing contributor --- htdocs/societe/class/societe.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 5ade14c7377..b5456cf789d 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -17,6 +17,7 @@ * Copyright (C) 2019-2020 Josep Lluís Amador * Copyright (C) 2019-2021 Frédéric France * Copyright (C) 2020 Open-Dsi + * Copyright (C) 2022 ButterflyOfFire * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by From 799cff66a38c69fd84be091990f25c2958392ba2 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Thu, 7 Jul 2022 08:41:59 +0000 Subject: [PATCH 153/826] Fixing style errors. --- htdocs/societe/class/societe.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index b5456cf789d..90766323080 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -3790,7 +3790,7 @@ class Societe extends CommonObject return -1; } } - + //Verify NIF if country is DZ //Returns: 1 if NIF ok, -1 if NIF bad, 0 if unexpected bad if ($idprof == 1 && $soc->country_code == 'DZ') { From 440ed897ffa30eadb601872ed8fa7b120cb658d2 Mon Sep 17 00:00:00 2001 From: jyhere Date: Thu, 7 Jul 2022 11:32:42 +0200 Subject: [PATCH 154/826] ADD multiselect support in Form::formconfirm() Use 'multiselect' type to add a multi select field in form confirm questions. --- htdocs/core/class/html.form.class.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 9568ec25828..b969d664ca3 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -4911,7 +4911,7 @@ class Form * @param string $question Question * @param string $action Action * @param array|string $formquestion An array with complementary inputs to add into forms: array(array('label'=> ,'type'=> , 'size'=>, 'morecss'=>, 'moreattr'=>)) - * type can be 'hidden', 'text', 'password', 'checkbox', 'radio', 'date', 'morecss', 'other' or 'onecolumn'... + * type can be 'hidden', 'text', 'password', 'checkbox', 'radio', 'date', 'select', 'multiselect', 'morecss', 'other' or 'onecolumn'... * @param string $selectedchoice '' or 'no', or 'yes' or '1' or '0' * @param int|string $useajax 0=No, 1=Yes, 2=Yes but submit page with &confirm=no if choice is No, 'xxx'=Yes and preoutput confirm box with div id=dialog-confirm-xxx * @param int|string $height Force height of box (0 = auto) @@ -4982,7 +4982,7 @@ class Form $moreonecolumn .= $input['value']; $moreonecolumn .= ''; $moreonecolumn .= '
'; - } elseif ($input['type'] == 'select') { + } elseif (in_array($input['type'],['select', 'multiselect'])) { if (empty($morecss)) { $morecss = 'minwidth100'; } @@ -4999,7 +4999,11 @@ class Form if (!empty($input['label'])) { $more .= $input['label'].'
'; } - $more .= $this->selectarray($input['name'], $input['values'], isset($input['default'])?$input['default']:'', $show_empty, $key_in_label, $value_as_key, $moreattr, $translate, $maxlen, $disabled, $sort, $morecss); + if ($input['type'] == 'select') { + $more .= $this->selectarray($input['name'], $input['values'], $input['default'], $show_empty, $key_in_label, $value_as_key, $moreattr, $translate, $maxlen, $disabled, $sort, $morecss); + } else { + $more .= $this->multiselectarray($input['name'], $input['values'], is_array($input['default']) ? $input['default'] : [$input['default']], $key_in_label, $value_as_key, $morecss, $translate, $maxlen, $moreattr); + } $more .= '
'."\n"; } elseif ($input['type'] == 'checkbox') { $more .= '
'; From f2961d4bf41544540442231270d5ea6d4f7d41a7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 7 Jul 2022 11:41:40 +0200 Subject: [PATCH 155/826] Fix sql --- htdocs/install/mysql/migration/16.0.0-17.0.0.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql index dad3712d3f3..1e3663768a1 100644 --- a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql +++ b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql @@ -35,6 +35,7 @@ -- Missing in v16 or lower +ALTER TABLE llx_c_action_trigger MODIFY elementtype VARCHAR(64); From fc6eb42ae7fd5e4d6825c8d866e7a8da84d03efd Mon Sep 17 00:00:00 2001 From: jyhere Date: Thu, 7 Jul 2022 11:52:44 +0200 Subject: [PATCH 156/826] Missing space --- htdocs/core/class/html.form.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index b969d664ca3..aeaa02035bd 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -4982,7 +4982,7 @@ class Form $moreonecolumn .= $input['value']; $moreonecolumn .= ''; $moreonecolumn .= '
'; - } elseif (in_array($input['type'],['select', 'multiselect'])) { + } elseif (in_array($input['type'], ['select', 'multiselect'])) { if (empty($morecss)) { $morecss = 'minwidth100'; } From 79dbba1cc6640911f0928abc6cd5c98dafb3c26a Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Thu, 7 Jul 2022 13:01:21 +0200 Subject: [PATCH 157/826] Update index.php help_url DE --- htdocs/exports/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/exports/index.php b/htdocs/exports/index.php index 3ba5e0a3591..41d6cd18ed0 100644 --- a/htdocs/exports/index.php +++ b/htdocs/exports/index.php @@ -41,7 +41,7 @@ $result = restrictedArea($user, 'export'); $form = new Form($db); -$help_url = 'EN:Module_Exports_En|FR:Module_Exports|ES:Módulo_Exportaciones'; +$help_url = 'EN:Module_Exports_En|FR:Module_Exports|ES:Módulo_Exportaciones|DE:Modul_DatenExporte'; llxHeader('', $langs->trans("ExportsArea"), $help_url); From 55c035097c6db16fc2656a42dad4ee8067621c74 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 7 Jul 2022 16:48:13 +0200 Subject: [PATCH 158/826] Fix contextpage --- htdocs/salaries/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/salaries/list.php b/htdocs/salaries/list.php index e578e8e0d02..26b26b34053 100644 --- a/htdocs/salaries/list.php +++ b/htdocs/salaries/list.php @@ -40,7 +40,7 @@ $show_files = GETPOST('show_files', 'int'); // Show files area generated by bulk $confirm = GETPOST('confirm', 'alpha'); // Result of a confirmation $cancel = GETPOST('cancel', 'alpha'); // We click on a Cancel button $toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected into a list -$contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'bomlist'; // To manage different context of search +$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : str_replace('_', '', __FILE__); // To manage different context of search $backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page $optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print') From c6bc767834706ca5824307307c26c62a793489b6 Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Thu, 7 Jul 2022 17:05:47 +0200 Subject: [PATCH 159/826] send formconfirm as a POST --- htdocs/core/class/html.form.class.php | 29 ++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 9568ec25828..f3c88b55af4 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -5148,8 +5148,9 @@ class Form closeOnEscape: false, buttons: { "'.dol_escape_js($langs->transnoentities($labelbuttonyes)).'": function() { - var options = "&token='.urlencode(newToken()).'"; + var options = "token='.urlencode(newToken()).'"; var inputok = '.json_encode($inputok).'; /* List of fields into form */ + var page = "'.dol_escape_js(!empty($page) ? $page : '').'"; var pageyes = "'.dol_escape_js(!empty($pageyes) ? $pageyes : '').'"; if (inputok.length>0) { $.each(inputok, function(i, inputname) { @@ -5166,12 +5167,20 @@ class Form options += "&" + inputname + "=" + encodeURIComponent(inputvalue); }); } - var urljump = pageyes + (pageyes.indexOf("?") < 0 ? "?" : "") + options; - if (pageyes.length > 0) { location.href = urljump; } + if (pageyes.length > 0) { + console.log(page); + console.log(pageyes); + console.log(options); + var post = $.post( + pageyes, + options, + () => {location.assign(page)} + ); + } $(this).dialog("close"); }, "'.dol_escape_js($langs->transnoentities($labelbuttonno)).'": function() { - var options = "&token='.urlencode(newToken()).'"; + var options = "token='.urlencode(newToken()).'"; var inputko = '.json_encode($inputko).'; /* List of fields into form */ var pageno="'.dol_escape_js(!empty($pageno) ? $pageno : '').'"; if (inputko.length>0) { @@ -5183,9 +5192,15 @@ class Form options += "&" + inputname + "=" + encodeURIComponent(inputvalue); }); } - var urljump=pageno + (pageno.indexOf("?") < 0 ? "?" : "") + options; - //alert(urljump); - if (pageno.length > 0) { location.href = urljump; } + if (pageno.length > 0) { + console.log(pageno); + console.log(options); + var post = $.post( + pageno, + options, + () => {location.assign(page)} + ); + } $(this).dialog("close"); } } From 11e97df5581c1fb283006657176ca111516fb019 Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Thu, 7 Jul 2022 17:38:41 +0200 Subject: [PATCH 160/826] forgot a 'page' parameter for 'no' button --- htdocs/core/class/html.form.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index f3c88b55af4..2b70d91b5c4 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -5182,6 +5182,7 @@ class Form "'.dol_escape_js($langs->transnoentities($labelbuttonno)).'": function() { var options = "token='.urlencode(newToken()).'"; var inputko = '.json_encode($inputko).'; /* List of fields into form */ + var page = "'.dol_escape_js(!empty($page) ? $page : '').'"; var pageno="'.dol_escape_js(!empty($pageno) ? $pageno : '').'"; if (inputko.length>0) { $.each(inputko, function(i, inputname) { From 1e1be459b3c21c0ad26b4a6d021f392e570f83be Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 7 Jul 2022 21:15:28 +0200 Subject: [PATCH 161/826] Update accounting-files.php --- htdocs/compta/accounting-files.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/accounting-files.php b/htdocs/compta/accounting-files.php index 24d0c191d33..ab8175c4d38 100644 --- a/htdocs/compta/accounting-files.php +++ b/htdocs/compta/accounting-files.php @@ -196,7 +196,7 @@ if (($action == 'searchfiles' || $action == 'dl')) { if (!empty($projectid)) $sql .= " AND fk_projet = ".((int) $projectid); } // Expense reports - if (GETPOST('selectexpensereports') && !empty($listofchoices['selectexpensereports']['perms']) and empty($projectid)) { + if (GETPOST('selectexpensereports') && !empty($listofchoices['selectexpensereports']['perms']) && empty($projectid)) { if (!empty($sql)) { $sql .= " UNION ALL"; } From 2ffdb19bdff4cb506bb24dd31ead04dbd403aa90 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 7 Jul 2022 21:20:09 +0200 Subject: [PATCH 162/826] Because button are reserved for action on workflow, i comment this to not break consistency of position of feature. I will think to a better place... --- htdocs/projet/card.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index 7a3690fb39f..d5db377fe08 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -1281,6 +1281,7 @@ if ($action == 'create' && $user->rights->projet->creer) { } // Accounting Report + /* $accouting_module_activated = !empty($conf->comptabilite->enabled) || !empty($conf->accounting->enabled); if ($accouting_module_activated && $object->statut != Project::STATUS_DRAFT) { $start = dol_getdate((int) $object->date_start); @@ -1290,7 +1291,8 @@ if ($action == 'create' && $user->rights->projet->creer) { if (!empty($object->date_end)) $url .= '&date_stopday='.$end['mday'].'&date_stopmonth='.$end['mon'].'&date_stopyear='.$end['year']; print dolGetButtonAction('', $langs->trans('ExportAccountingReportButtonLabel'), 'default', $url, ''); } - + */ + // Modify if ($object->statut != Project::STATUS_CLOSED && $user->rights->projet->creer) { if ($userWrite > 0) { From f6a39383d326c86273554f6da01ea807dd72650b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 7 Jul 2022 22:35:56 +0200 Subject: [PATCH 163/826] Fix error management --- htdocs/compta/facture/class/facture.class.php | 6 ++++-- htdocs/takepos/invoice.php | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 345ffd10acb..74595267a7c 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -3140,6 +3140,7 @@ class Facture extends CommonInvoice } else { $num = $this->ref; } + $this->newref = dol_sanitizeFileName($num); if ($num) { @@ -3147,7 +3148,7 @@ class Facture extends CommonInvoice // Validate $sql = 'UPDATE '.MAIN_DB_PREFIX.'facture'; - $sql .= " SET ref='".$num."', fk_statut = ".self::STATUS_VALIDATED.", fk_user_valid = ".($user->id > 0 ? $user->id : "null").", date_valid = '".$this->db->idate($now)."'"; + $sql .= " SET ref = '".$this->db->escape($num)."', fk_statut = ".self::STATUS_VALIDATED.", fk_user_valid = ".($user->id > 0 ? $user->id : "null").", date_valid = '".$this->db->idate($now)."'"; if (!empty($conf->global->FAC_FORCE_DATE_VALIDATION)) { // If option enabled, we force invoice date $sql .= ", datef='".$this->db->idate($this->date)."'"; $sql .= ", date_lim_reglement='".$this->db->idate($this->date_lim_reglement)."'"; @@ -4383,7 +4384,6 @@ class Facture extends CommonInvoice $mybool = false; - $file = $addon.'.php'; $classname = $addon; @@ -4421,8 +4421,10 @@ class Facture extends CommonInvoice } $obj = new $classname(); + $numref = $obj->getNextValue($soc, $this, $mode); + /** * $numref can be empty in case we ask for the last value because if there is no invoice created with the * set up mask. diff --git a/htdocs/takepos/invoice.php b/htdocs/takepos/invoice.php index 35855b60e23..bdc11c79b2f 100644 --- a/htdocs/takepos/invoice.php +++ b/htdocs/takepos/invoice.php @@ -177,6 +177,7 @@ if (!empty($conf->multicurrency->enabled) && !empty($_SESSION["takeposcustomercu } } + /* * Actions */ @@ -278,7 +279,8 @@ if (empty($reshook)) { $res = $invoice->validate($user); if ($res < 0) { $error++; - dol_htmloutput_errors($invoice->error, $invoice->errors, 1); + $langs->load("admin"); + dol_htmloutput_errors($invoice->error == 'NotConfigured' ? $langs->trans("NotConfigured").' (TakePos numbering module)': $invoice->error, $invoice->errors, 1); } } From 67d17cf289b372c1c4425bf68e4b2c725c8d23de Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 7 Jul 2022 22:50:42 +0200 Subject: [PATCH 164/826] Trans --- htdocs/langs/en_US/holiday.lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/langs/en_US/holiday.lang b/htdocs/langs/en_US/holiday.lang index 36f1e839e67..831d306cc39 100644 --- a/htdocs/langs/en_US/holiday.lang +++ b/htdocs/langs/en_US/holiday.lang @@ -93,7 +93,7 @@ UseralreadyCPexist=A leave request has already been done on this period for %s. groups=Groups users=Users AutoSendMail=Automatic mailing -NewHolidayForGroup=Collective leaves +NewHolidayForGroup=New collective leave request SendRequestCollectiveCP=Send collective leave request AutoValidationOnCreate=Automatic validation FirstDayOfHoliday=Beginning day of leave request From ff7782eb6b7e7b467c20fd78a0f0e3e52b86ede7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 8 Jul 2022 00:36:42 +0200 Subject: [PATCH 165/826] Fix phpcs --- htdocs/projet/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index a213f417650..0beb68c080c 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -1293,7 +1293,7 @@ if ($action == 'create' && $user->rights->projet->creer) { print dolGetButtonAction('', $langs->trans('ExportAccountingReportButtonLabel'), 'default', $url, ''); } */ - + // Modify if ($object->statut != Project::STATUS_CLOSED && $user->rights->projet->creer) { if ($userWrite > 0) { From 147140bdc29f3e8714765edde4e995918abb061a Mon Sep 17 00:00:00 2001 From: bagtaib Date: Fri, 8 Jul 2022 05:55:23 +0200 Subject: [PATCH 166/826] Show/hide advanced Options --- htdocs/admin/tools/dolibarr_export.php | 19 ++++++++++++++++++- htdocs/langs/en_US/admin.lang | 2 ++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/htdocs/admin/tools/dolibarr_export.php b/htdocs/admin/tools/dolibarr_export.php index 7d02aea0e73..d38fe0f6b37 100644 --- a/htdocs/admin/tools/dolibarr_export.php +++ b/htdocs/admin/tools/dolibarr_export.php @@ -197,8 +197,25 @@ print ''; print ''; print ''; +print ''; -print '
'; +print ''; + +print '"; print ''; From 6aade2e50685cb3f8b19bd059595afacf8b9329e Mon Sep 17 00:00:00 2001 From: lvessiller Date: Wed, 13 Jul 2022 11:19:07 +0200 Subject: [PATCH 217/826] NEW hook formConfirm on action comm card --- htdocs/comm/action/card.php | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/htdocs/comm/action/card.php b/htdocs/comm/action/card.php index e543b7e6bd1..989c909487b 100644 --- a/htdocs/comm/action/card.php +++ b/htdocs/comm/action/card.php @@ -1903,13 +1903,22 @@ if ($id > 0) { } else { print dol_get_fiche_head($head, 'card', $langs->trans("Action"), -1, 'action'); + $formconfirm = ''; + // Clone event if ($action == 'clone') { - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.GETPOST('id'), $langs->trans('ToClone'), $langs->trans('ConfirmCloneEvent', $object->label), 'confirm_clone', $formquestion, 'yes', 1); - - print $formconfirm; + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.GETPOST('id'), $langs->trans('ToClone'), $langs->trans('ConfirmCloneEvent', $object->label), 'confirm_clone', array(), 'yes', 1); } + // Call Hook formConfirm + $parameters = array(); + $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if (empty($reshook)) $formconfirm.=$hookmanager->resPrint; + elseif ($reshook > 0) $formconfirm=$hookmanager->resPrint; + + // Print form confirm + print $formconfirm; + $linkback = ''; // Link to other agenda views $linkback .= ''; From 5a7652fd75c75b74a02f50acbc4327528f8eaa64 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 14 Jul 2022 10:15:03 +0200 Subject: [PATCH 218/826] Add test to fetch lines --- htdocs/contrat/class/contrat.class.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 322f3f4652e..1e8da8a9a81 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -668,7 +668,7 @@ class Contrat extends CommonObject if (!$id) { $sql .= " WHERE entity IN (".getEntity('contract').")"; } else { - $sql .= " WHERE rowid=".(int) $id; + $sql .= " WHERE rowid = ".(int) $id; } if ($ref_customer) { $sql .= " AND ref_customer = '".$this->db->escape($ref_customer)."'"; @@ -677,7 +677,7 @@ class Contrat extends CommonObject $sql .= " AND ref_supplier = '".$this->db->escape($ref_supplier)."'"; } if ($ref) { - $sql .= " AND ref='".$this->db->escape($ref)."'"; + $sql .= " AND ref = '".$this->db->escape($ref)."'"; } dol_syslog(get_class($this)."::fetch", LOG_DEBUG); @@ -724,10 +724,13 @@ class Contrat extends CommonObject // Retrieve all extrafields // fetch optionals attributes and labels - $this->fetch_optionals(); + $result = $this->fetch_optionals(); // Lines - $result = $this->fetch_lines(); + if ($result >= 0 && !empty($this->table_element_line)) { + $result = $this->fetch_lines(); + } + if ($result < 0) { $this->error = $this->db->lasterror(); return -3; From 75693ce34a23f6c732402e4020b0b39c126c87df Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 14 Jul 2022 10:56:55 +0200 Subject: [PATCH 219/826] FIX php8 --- htdocs/core/class/extrafields.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index f2463804e32..c12cfc480fc 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -908,7 +908,7 @@ class ExtraFields $this->attributes[$tab->elementtype]['param'][$tab->name] = ($tab->param ? jsonOrUnserialize($tab->param) : ''); $this->attributes[$tab->elementtype]['pos'][$tab->name] = $tab->pos; $this->attributes[$tab->elementtype]['alwayseditable'][$tab->name] = $tab->alwayseditable; - $this->attributes[$tab->elementtype]['perms'][$tab->name] = (strlen($tab->perms) == 0 ? 1 : $tab->perms); + $this->attributes[$tab->elementtype]['perms'][$tab->name] = ((is_null($tab->perms) || strlen($tab->perms) == 0) ? 1 : $tab->perms); $this->attributes[$tab->elementtype]['langfile'][$tab->name] = $tab->langs; $this->attributes[$tab->elementtype]['list'][$tab->name] = $tab->list; $this->attributes[$tab->elementtype]['printable'][$tab->name] = $tab->printable; From add38d0d04f777c0554468c07dea9d94a1ec5464 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 14 Jul 2022 14:59:28 +0200 Subject: [PATCH 220/826] Fix http header --- htdocs/install/inc.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/htdocs/install/inc.php b/htdocs/install/inc.php index 6ca9a99cdcf..a20c3489866 100644 --- a/htdocs/install/inc.php +++ b/htdocs/install/inc.php @@ -195,6 +195,10 @@ if (preg_match('/install\.lock/i', $_SERVER["SCRIPT_FILENAME"])) { $langs->setDefaultLang('auto'); } $langs->load("install"); + + header("X-Content-Type-Options: nosniff"); + header("X-Frame-Options: SAMEORIGIN"); // Frames allowed only if on same domain (stop some XSS attacks) + print $langs->trans("YouTryInstallDisabledByDirLock"); if (!empty($dolibarr_main_url_root)) { print 'Click on following link, '; @@ -216,6 +220,10 @@ if (@file_exists($lockfile)) { $langs->setDefaultLang('auto'); } $langs->load("install"); + + header("X-Content-Type-Options: nosniff"); + header("X-Frame-Options: SAMEORIGIN"); // Frames allowed only if on same domain (stop some XSS attacks) + print $langs->trans("YouTryInstallDisabledByFileLock"); if (!empty($dolibarr_main_url_root)) { print $langs->trans("ClickOnLinkOrRemoveManualy").'
'; From e5877cb2e3242d01c86a04c97ab0ff1d9b67de26 Mon Sep 17 00:00:00 2001 From: lvessiller Date: Fri, 15 Jul 2022 09:33:27 +0200 Subject: [PATCH 221/826] FIX product filter in inventory list (Issue #21504) --- htdocs/core/class/commonobject.class.php | 20 +++++++++++++------ .../inventory/class/inventory.class.php | 2 +- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 4d83acfe44c..b0ea04adb3e 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -7633,16 +7633,24 @@ abstract class CommonObject } if ($result > 0) { if ($object->element === 'product') { - $getnomurlparam3 = (!isset($InfoFieldList[5]) ? 0 : $InfoFieldList[5]); - $getnomurlparam4 = (!isset($InfoFieldList[6]) ? -1 : $InfoFieldList[6]); - $getnomurlparam5 = (!isset($InfoFieldList[7]) ? 0 : $InfoFieldList[7]); - $getnomurlparam6 = (!isset($InfoFieldList[8]) ? '' : $InfoFieldList[8]); - $getnomurlparam7 = (!isset($InfoFieldList[9]) ? 0 : $InfoFieldList[9]); + $get_name_url_param_arr = array($getnomurlparam, $getnomurlparam2, 0, -1, 0, '', 0); + if (isset($val['get_name_url_params'])) { + $get_name_url_params = explode(':', $val['get_name_url_params']); + if (!empty($get_name_url_params)) { + $param_num_max = count($get_name_url_param_arr) - 1; + foreach ($get_name_url_params as $param_num => $param_value) { + if ($param_num > $param_num_max) { + break; + } + $get_name_url_param_arr[$param_num] = $param_value; + } + } + } /** * @var Product $object */ - $value = $object->getNomUrl($getnomurlparam, $getnomurlparam2, $getnomurlparam3, $getnomurlparam4, $getnomurlparam5, $getnomurlparam6, $getnomurlparam7); + $value = $object->getNomUrl($get_name_url_param_arr[0], $get_name_url_param_arr[1], $get_name_url_param_arr[2], $get_name_url_param_arr[3], $get_name_url_param_arr[4], $get_name_url_param_arr[5], $get_name_url_param_arr[6]); } else { $value = $object->getNomUrl($getnomurlparam, $getnomurlparam2); } diff --git a/htdocs/product/inventory/class/inventory.class.php b/htdocs/product/inventory/class/inventory.class.php index 7229b14ea28..4dff257e257 100644 --- a/htdocs/product/inventory/class/inventory.class.php +++ b/htdocs/product/inventory/class/inventory.class.php @@ -101,7 +101,7 @@ class Inventory extends CommonObject 'entity' => array('type'=>'integer', 'label'=>'Entity', 'visible'=>0, 'enabled'=>1, 'position'=>20, 'notnull'=>1, 'index'=>1,), 'title' => array('type'=>'varchar(255)', 'label'=>'Label', 'visible'=>1, 'enabled'=>1, 'position'=>25, 'css'=>'minwidth300', 'csslist'=>'tdoverflowmax200'), 'fk_warehouse' => array('type'=>'integer:Entrepot:product/stock/class/entrepot.class.php', 'label'=>'Warehouse', 'visible'=>1, 'enabled'=>1, 'position'=>30, 'index'=>1, 'help'=>'InventoryForASpecificWarehouse', 'picto'=>'stock', 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'csslist'=>'tdoverflowmax200'), - 'fk_product' => array('type'=>'integer:Product:product/class/product.class.php::::0:-1:0::1', 'label'=>'Product', 'visible'=>1, 'enabled'=>1, 'position'=>32, 'index'=>1, 'help'=>'InventoryForASpecificProduct', 'picto'=>'product', 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'csslist'=>'tdoverflowmax200'), + 'fk_product' => array('type'=>'integer:Product:product/class/product.class.php', 'label'=>'Product', 'get_name_url_params' => '0::0:-1:0::1', 'visible'=>1, 'enabled'=>1, 'position'=>32, 'index'=>1, 'help'=>'InventoryForASpecificProduct', 'picto'=>'product', 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'csslist'=>'tdoverflowmax200'), 'date_inventory' => array('type'=>'date', 'label'=>'DateValue', 'visible'=>1, 'enabled'=>'$conf->global->STOCK_INVENTORY_ADD_A_VALUE_DATE', 'position'=>35), // This date is not used so disabled by default. 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>500), 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>501), From 3bace7437857b00d1d69db0048cc76422a122ab0 Mon Sep 17 00:00:00 2001 From: David Beniamine Date: Fri, 15 Jul 2022 11:03:47 +0200 Subject: [PATCH 222/826] Add search on member nature morphy --- htdocs/adherents/list.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/htdocs/adherents/list.php b/htdocs/adherents/list.php index 3075225abb9..1995485eb4e 100644 --- a/htdocs/adherents/list.php +++ b/htdocs/adherents/list.php @@ -63,6 +63,7 @@ $search_email = GETPOST("search_email", 'alpha'); $search_categ = GETPOST("search_categ", 'int'); $search_filter = GETPOST("search_filter", 'alpha'); $search_status = GETPOST("search_status", 'intcomma'); +$search_morphy = GETPOST("search_morphy", 'alpha'); $search_import_key = trim(GETPOST("search_import_key", "alpha")); $catid = GETPOST("catid", 'int'); $optioncss = GETPOST('optioncss', 'alpha'); @@ -382,6 +383,9 @@ if ($search_status != '') { // Peut valoir un nombre ou liste de nombre separes par virgules $sql .= " AND d.statut in (".$db->sanitize($db->escape($search_status)).")"; } +if ($search_morphy != '') { + $sql .= natural_search("d.morphy", $search_morphy); +} if ($search_ref) { $sql .= natural_search("d.ref", $search_ref); } @@ -731,6 +735,11 @@ if (!empty($arrayfields['d.login']['checked'])) { } if (!empty($arrayfields['d.morphy']['checked'])) { print ''; + $arraymorphy = array('mor'=>$langs->trans("Moral"), 'phy'=>$langs->trans("Physical")); + print $form->selectarray('search_morphy', $arraymorphy, $search_morphy, 1); + print ''; +} +if (!empty($arrayfields['t.libelle']['checked'])) { print ''; } if (!empty($arrayfields['t.libelle']['checked'])) { From b000ee7c503e010f8e3fddda1a557d2188d930a3 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 15 Jul 2022 13:41:02 +0200 Subject: [PATCH 223/826] NEW Add API for partnership module Debug module builder --- htdocs/api/index.php | 2 + htdocs/core/lib/functions.lib.php | 11 +- htdocs/modulebuilder/admin/setup.php | 18 +- htdocs/modulebuilder/index.php | 17 +- .../class/api_partnership.class.php | 394 ++++++++++++++++++ 5 files changed, 420 insertions(+), 22 deletions(-) create mode 100644 htdocs/partnership/class/api_partnership.class.php diff --git a/htdocs/api/index.php b/htdocs/api/index.php index afb0289aa32..8543e284533 100644 --- a/htdocs/api/index.php +++ b/htdocs/api/index.php @@ -257,6 +257,8 @@ if (!empty($reg[1]) && $reg[1] == 'explorer' && ($reg[2] == '/swagger.json' || $ continue; } + //dol_syslog("We scan to search api file with into ".$dir_part.$file_searched); + $regapi = array(); if (is_readable($dir_part.$file_searched) && preg_match("/^api_(.*)\.class\.php$/i", $file_searched, $regapi)) { $classname = ucwords($regapi[1]); diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 381280289ee..51d26491826 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -3887,15 +3887,18 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ if (strpos($pictowithouttext, 'fontawesome_') !== false || preg_match('/^fa-/', $pictowithouttext)) { // This is a font awesome image 'fonwtawesome_xxx' or 'fa-xxx' + $pictowithouttext = str_replace('fontawesome_', '', $pictowithouttext); $pictowithouttext = str_replace('fa-', '', $pictowithouttext); + $pictowithouttextarray = explode('_', $pictowithouttext); $marginleftonlyshort = 0; if (!empty($pictowithouttextarray[1])) { - $fakey = 'fa-'.$pictowithouttextarray[1]; - $fa = empty($pictowithouttextarray[2]) ? 'fa' : $pictowithouttextarray[2]; - $facolor = empty($pictowithouttextarray[3]) ? '' : $pictowithouttextarray[3]; - $fasize = empty($pictowithouttextarray[4]) ? '' : $pictowithouttextarray[4]; + // Syntax is 'fontawesome_fakey_faprefix_facolor_fasize' or 'fa-fakey_faprefix_facolor_fasize' + $fakey = 'fa-'.$pictowithouttextarray[0]; + $fa = empty($pictowithouttextarray[1]) ? 'fa' : $pictowithouttextarray[1]; + $facolor = empty($pictowithouttextarray[2]) ? '' : $pictowithouttextarray[2]; + $fasize = empty($pictowithouttextarray[3]) ? '' : $pictowithouttextarray[3]; } else { $fakey = 'fa-'.$pictowithouttext; $fa = 'fa'; diff --git a/htdocs/modulebuilder/admin/setup.php b/htdocs/modulebuilder/admin/setup.php index da2cff7eff4..50c86e38cc0 100644 --- a/htdocs/modulebuilder/admin/setup.php +++ b/htdocs/modulebuilder/admin/setup.php @@ -111,7 +111,7 @@ print '
'; print ''; print ''; -print ''; +print ''; print ''; print "\n"; @@ -134,35 +134,35 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { print ''; print ''; - print ''; + print ''; print ''; print ''; print ''; - print ''; + print ''; print ''; print ''; print ''; - print ''; + print ''; print ''; print ''; print ''; - print ''; + print ''; print ''; print ''; print ''; - print ''; + print ''; print ''; @@ -170,14 +170,14 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { } print ''; -print ''; +print ''; print ''; print ''; print ''; -print ''; +print ''; print ''; print ''; print ''; -print ''; +print ''; print '
'.$langs->trans("Key").''.$langs->trans("Parameter").''.$langs->trans("Value").'
'.$langs->trans("UseSpecificEditorName").''.$langs->trans("UseSpecificEditorName").''; print ''; print '
'.$langs->trans("UseSpecificEditorURL").''.$langs->trans("UseSpecificEditorURL").''; print ''; print '
'.$langs->trans("UseSpecificFamily").''.$langs->trans("UseSpecificFamily").''; print ''; print '
'.$langs->trans("UseSpecificAuthor").''.$langs->trans("UseSpecificAuthor").''; print ''; print '
'.$langs->trans("UseSpecificVersion").''.$langs->trans("UseSpecificVersion").''; print ''; print '
'.$langs->trans("UseSpecificReadme").''.$langs->trans("UseSpecificReadme").''; print ''; print '
'.$langs->trans("AsciiToHtmlConverter").''.$langs->trans("AsciiToHtmlConverter").''; print ''; print ' '.$langs->trans("Example").': asciidoc, asciidoctor'; @@ -185,7 +185,7 @@ print '
'.$langs->trans("AsciiToPdfConverter").''.$langs->trans("AsciiToPdfConverter").''; print ''; print ' '.$langs->trans("Example").': asciidoctor-pdf'; diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index c6dec95481c..3283d7c7666 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -343,10 +343,10 @@ if ($dirins && $action == 'initmodule' && $modulename) { '---Put here your own copyright and developer email---'=>dol_print_date($now, '%Y').' '.$user->getFullName($langs).($user->email ? ' <'.$user->email.'>' : ''), 'Editor name'=>$editorname, 'https://www.example.com'=>$editorurl, - '1.0'=>$version, - 'idpicto'=>(empty($picto)) ? 'generic' : $picto, + '$this->version = \'1.0\''=>'$this->version = \''.$version.'\'', + '$this->picto = \'generic\';'=>(empty($picto)) ? '$this->picto = \'generic\'' : '$this->picto = \''.$picto.'\';', "modulefamily" =>$family, - 500000=>$idmodule + '500000'=>$idmodule ); if (!empty($conf->global->MODULEBUILDER_SPECIFIC_EDITOR_NAME)) { @@ -382,7 +382,6 @@ if ($dirins && $action == 'initmodule' && $modulename) { if (!$error) { setEventMessages('ModuleInitialized', null); $module = $modulename; - $modulename = ''; clearstatcache(true); if (function_exists('opcache_invalidate')) { @@ -2115,8 +2114,8 @@ if ($module == 'initmodule') { print ''; print '
'; print ajax_combobox("family"); - print ''.$langs->trans("Picto").' '; - print $form->textwithpicto('', $langs->trans("Example").': generic, globe, ... any font awesome code'); + print ''.$langs->trans("Picto").' '; + print $form->textwithpicto('', $langs->trans("Example").': fa-generic, fa-globe, ... any font awesome code.
Advanced syntax is fa-fakey[_faprefix[_facolor[_fasize]]]'); print '
'; print ''.$langs->trans("Description").'
'; @@ -2269,7 +2268,7 @@ if ($module == 'initmodule') { print '
'; print '
'; - print load_fiche_titre($langs->trans("DescriptorFile"), '', ''); + print load_fiche_titre($form->textwithpicto($langs->trans("DescriptorFile"), $pathtofile), '', ''); if (!empty($moduleobj)) { print '
'; @@ -2347,7 +2346,7 @@ if ($module == 'initmodule') { print '

'; // Readme file - print load_fiche_titre($langs->trans("ReadmeFile"), '', ''); + print load_fiche_titre($form->textwithpicto($langs->trans("ReadmeFile"), $pathtofilereadme), '', ''); print ''; if (dol_is_file($dirread.'/'.$pathtofilereadme)) { @@ -2359,7 +2358,7 @@ if ($module == 'initmodule') { print '

'; // ChangeLog - print load_fiche_titre($langs->trans("ChangeLog"), '', ''); + print load_fiche_titre($form->textwithpicto($langs->trans("ChangeLog"), $pathtochangelog), '', ''); print ''; if (dol_is_file($dirread.'/'.$pathtochangelog)) { diff --git a/htdocs/partnership/class/api_partnership.class.php b/htdocs/partnership/class/api_partnership.class.php new file mode 100644 index 00000000000..1e1c7ca80fe --- /dev/null +++ b/htdocs/partnership/class/api_partnership.class.php @@ -0,0 +1,394 @@ + + * Copyright (C) 2022 Alice Adminson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +use Luracast\Restler\RestException; + +dol_include_once('/partnership/class/partnership.class.php'); + + + +/** + * \file partnership/class/api_partnership.class.php + * \ingroup partnership + * \brief File for API management of partnership. + */ + +/** + * API class for partnership partnership + * + * @access protected + * @class DolibarrApiAccess {@requires user,external} + */ +class PartnershipApi extends DolibarrApi +{ + /** + * @var Partnership $partnership {@type Partnership} + */ + public $partnership; + + /** + * Constructor + * + * @url GET / + * + */ + public function __construct() + { + global $db; + $this->db = $db; + $this->partnership = new Partnership($this->db); + } + + /** + * Get properties of a partnership object + * + * Return an array with partnership informations + * + * @param int $id ID of partnership + * @return array|mixed data without useless information + * + * @url GET partnerships/{id} + * + * @throws RestException 401 Not allowed + * @throws RestException 404 Not found + */ + public function get($id) + { + if (!DolibarrApiAccess::$user->rights->partnership->read) { + throw new RestException(401); + } + + $result = $this->partnership->fetch($id); + if (!$result) { + throw new RestException(404, 'Partnership not found'); + } + + if (!DolibarrApi::_checkAccessToResource('partnership', $this->partnership->id, 'partnership')) { + throw new RestException(401, 'Access to instance id='.$this->partnership->id.' of object not allowed for login '.DolibarrApiAccess::$user->login); + } + + return $this->_cleanObjectDatas($this->partnership); + } + + + /** + * List partnerships + * + * Get a list of partnerships + * + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')" + * @return array Array of order objects + * + * @throws RestException + * + * @url GET /partnerships/ + */ + public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $sqlfilters = '') + { + global $db, $conf; + + $obj_ret = array(); + $tmpobject = new Partnership($this->db); + + if (!DolibarrApiAccess::$user->rights->partnership->read) { + throw new RestException(401); + } + + $socid = DolibarrApiAccess::$user->socid ? DolibarrApiAccess::$user->socid : ''; + + $restrictonsocid = 0; // Set to 1 if there is a field socid in table of object + + // If the internal user must only see his customers, force searching by him + $search_sale = 0; + if ($restrictonsocid && !DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) { + $search_sale = DolibarrApiAccess::$user->id; + } + + $sql = "SELECT t.rowid"; + if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { + $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) + } + $sql .= " FROM ".MAIN_DB_PREFIX.$tmpobject->table_element." as t"; + + if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { + $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale + } + $sql .= " WHERE 1 = 1"; + + // Example of use $mode + //if ($mode == 1) $sql.= " AND s.client IN (1, 3)"; + //if ($mode == 2) $sql.= " AND s.client IN (2, 3)"; + + if ($tmpobject->ismultientitymanaged) { + $sql .= ' AND t.entity IN ('.getEntity($tmpobject->element).')'; + } + if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { + $sql .= " AND t.fk_soc = sc.fk_soc"; + } + if ($restrictonsocid && $socid) { + $sql .= " AND t.fk_soc = ".((int) $socid); + } + if ($restrictonsocid && $search_sale > 0) { + $sql .= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale + } + // Insert sale filter + if ($restrictonsocid && $search_sale > 0) { + $sql .= " AND sc.fk_user = ".((int) $search_sale); + } + if ($sqlfilters) { + $errormessage = ''; + if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { + throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage); + } + $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; + $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; + } + + $sql .= $this->db->order($sortfield, $sortorder); + if ($limit) { + if ($page < 0) { + $page = 0; + } + $offset = $limit * $page; + + $sql .= $this->db->plimit($limit + 1, $offset); + } + + $result = $this->db->query($sql); + $i = 0; + if ($result) { + $num = $this->db->num_rows($result); + while ($i < $num) { + $obj = $this->db->fetch_object($result); + $tmp_object = new Partnership($this->db); + if ($tmp_object->fetch($obj->rowid)) { + $obj_ret[] = $this->_cleanObjectDatas($tmp_object); + } + $i++; + } + } else { + throw new RestException(503, 'Error when retrieving partnership list: '.$this->db->lasterror()); + } + if (!count($obj_ret)) { + throw new RestException(404, 'No partnership found'); + } + return $obj_ret; + } + + /** + * Create partnership object + * + * @param array $request_data Request datas + * @return int ID of partnership + * + * @throws RestException + * + * @url POST partnerships/ + */ + public function post($request_data = null) + { + if (!DolibarrApiAccess::$user->rights->partnership->write) { + throw new RestException(401); + } + + // Check mandatory fields + $result = $this->_validate($request_data); + + foreach ($request_data as $field => $value) { + $this->partnership->$field = $this->_checkValForAPI($field, $value, $this->partnership); + } + + // Clean data + // $this->partnership->abc = sanitizeVal($this->partnership->abc, 'alphanohtml'); + + if ($this->partnership->create(DolibarrApiAccess::$user)<0) { + throw new RestException(500, "Error creating Partnership", array_merge(array($this->partnership->error), $this->partnership->errors)); + } + return $this->partnership->id; + } + + /** + * Update partnership + * + * @param int $id Id of partnership to update + * @param array $request_data Datas + * @return int + * + * @throws RestException + * + * @url PUT partnerships/{id} + */ + public function put($id, $request_data = null) + { + if (!DolibarrApiAccess::$user->rights->partnership->write) { + throw new RestException(401); + } + + $result = $this->partnership->fetch($id); + if (!$result) { + throw new RestException(404, 'Partnership not found'); + } + + if (!DolibarrApi::_checkAccessToResource('partnership', $this->partnership->id, 'partnership')) { + throw new RestException(401, 'Access to instance id='.$this->partnership->id.' of object not allowed for login '.DolibarrApiAccess::$user->login); + } + + foreach ($request_data as $field => $value) { + if ($field == 'id') { + continue; + } + $this->partnership->$field = $this->_checkValForAPI($field, $value, $this->partnership); + } + + // Clean data + // $this->partnership->abc = sanitizeVal($this->partnership->abc, 'alphanohtml'); + + if ($this->partnership->update(DolibarrApiAccess::$user, false) > 0) { + return $this->get($id); + } else { + throw new RestException(500, $this->partnership->error); + } + } + + /** + * Delete partnership + * + * @param int $id Partnership ID + * @return array + * + * @throws RestException + * + * @url DELETE partnerships/{id} + */ + public function delete($id) + { + if (!DolibarrApiAccess::$user->rights->partnership->delete) { + throw new RestException(401); + } + $result = $this->partnership->fetch($id); + if (!$result) { + throw new RestException(404, 'Partnership not found'); + } + + if (!DolibarrApi::_checkAccessToResource('partnership', $this->partnership->id, 'partnership')) { + throw new RestException(401, 'Access to instance id='.$this->partnership->id.' of object not allowed for login '.DolibarrApiAccess::$user->login); + } + + if (!$this->partnership->delete(DolibarrApiAccess::$user)) { + throw new RestException(500, 'Error when deleting Partnership : '.$this->partnership->error); + } + + return array( + 'success' => array( + 'code' => 200, + 'message' => 'Partnership deleted' + ) + ); + } + + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore + /** + * Clean sensible object datas + * + * @param Object $object Object to clean + * @return Object Object with cleaned properties + */ + protected function _cleanObjectDatas($object) + { + // phpcs:enable + $object = parent::_cleanObjectDatas($object); + + unset($object->rowid); + unset($object->canvas); + + /*unset($object->name); + unset($object->lastname); + unset($object->firstname); + unset($object->civility_id); + unset($object->statut); + unset($object->state); + unset($object->state_id); + unset($object->state_code); + unset($object->region); + unset($object->region_code); + unset($object->country); + unset($object->country_id); + unset($object->country_code); + unset($object->barcode_type); + unset($object->barcode_type_code); + unset($object->barcode_type_label); + unset($object->barcode_type_coder); + unset($object->total_ht); + unset($object->total_tva); + unset($object->total_localtax1); + unset($object->total_localtax2); + unset($object->total_ttc); + unset($object->fk_account); + unset($object->comments); + unset($object->note); + unset($object->mode_reglement_id); + unset($object->cond_reglement_id); + unset($object->cond_reglement); + unset($object->shipping_method_id); + unset($object->fk_incoterms); + unset($object->label_incoterms); + unset($object->location_incoterms); + */ + + // If object has lines, remove $db property + if (isset($object->lines) && is_array($object->lines) && count($object->lines) > 0) { + $nboflines = count($object->lines); + for ($i = 0; $i < $nboflines; $i++) { + $this->_cleanObjectDatas($object->lines[$i]); + + unset($object->lines[$i]->lines); + unset($object->lines[$i]->note); + } + } + + return $object; + } + + /** + * Validate fields before create or update object + * + * @param array $data Array of data to validate + * @return array + * + * @throws RestException + */ + private function _validate($data) + { + $partnership = array(); + foreach ($this->partnership->fields as $field => $propfield) { + if (in_array($field, array('rowid', 'entity', 'date_creation', 'tms', 'fk_user_creat')) || $propfield['notnull'] != 1) { + continue; // Not a mandatory field + } + if (!isset($data[$field])) { + throw new RestException(400, "$field field missing"); + } + $partnership[$field] = $data[$field]; + } + return $partnership; + } +} From 801fa03a80415ba3ce9a9e291de245a297ac4f92 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 15 Jul 2022 13:41:36 +0200 Subject: [PATCH 224/826] Debug --- htdocs/modulebuilder/index.php | 6 +++++- htdocs/modulebuilder/template/langs/en_US/mymodule.lang | 1 + htdocs/partnership/partnership_card.php | 4 ++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 3283d7c7666..0bbd1df913f 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -2779,8 +2779,10 @@ if ($module == 'initmodule') { if (empty($forceddirread) && empty($dirread)) { $result = dol_include_once($pathtoclass); + $stringofinclude = "dol_include_once(".$pathtoclass.")"; } else { $result = @include_once $dirread.'/'.$pathtoclass; + $stringofinclude = "@include_once ".$dirread.'/'.$pathtoclass; } if (class_exists($tabobj)) { try { @@ -2788,6 +2790,8 @@ if ($module == 'initmodule') { } catch (Exception $e) { dol_syslog('Failed to load Constructor of class: '.$e->getMessage(), LOG_WARNING); } + } else { + print ''.$langs->trans('Failed to find the class '.$tabobj.' despite the '.$stringofinclude).'
'; } if (!empty($tmpobjet)) { @@ -3122,7 +3126,7 @@ if ($module == 'initmodule') { print ''; } else { - print ''.$langs->trans('Failed to init the object with the new.').''; + print ''.$langs->trans('Failed to init the object with the new '.$tabobj.'($db)').''; } } catch (Exception $e) { print $e->getMessage(); diff --git a/htdocs/modulebuilder/template/langs/en_US/mymodule.lang b/htdocs/modulebuilder/template/langs/en_US/mymodule.lang index ca8aa250748..cc518391c33 100644 --- a/htdocs/modulebuilder/template/langs/en_US/mymodule.lang +++ b/htdocs/modulebuilder/template/langs/en_US/mymodule.lang @@ -44,6 +44,7 @@ MyModuleAboutPage = MyModule about page # # Sample page # +MyModuleArea = Home MyModule MyPageName = My page name # diff --git a/htdocs/partnership/partnership_card.php b/htdocs/partnership/partnership_card.php index 08164421f60..25f8b286fb5 100644 --- a/htdocs/partnership/partnership_card.php +++ b/htdocs/partnership/partnership_card.php @@ -83,8 +83,8 @@ $managedfor = getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR', 'thirdparty'); if (empty($conf->partnership->enabled)) accessforbidden(); if (empty($permissiontoread)) accessforbidden(); -if ($object->id > 0 && $object->fk_member > 0 && $managedfor != 'member') accessforbidden(); -if ($object->id > 0 && $object->fk_soc > 0 && $managedfor != 'thirdparty') accessforbidden(); +if ($object->id > 0 && !($object->fk_member > 0) && $managedfor == 'member') accessforbidden(); +if ($object->id > 0 && !($object->fk_soc > 0) && $managedfor == 'thirdparty') accessforbidden(); /* From 45af1a6c9ce671061142ce7d4e6886004cd934ef Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 15 Jul 2022 14:31:00 +0200 Subject: [PATCH 225/826] Debug --- htdocs/modulebuilder/index.php | 87 ++++++++++++++++++++++++---------- 1 file changed, 61 insertions(+), 26 deletions(-) diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 0bbd1df913f..7d359ec0966 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -2607,10 +2607,63 @@ if ($module == 'initmodule') { $pathtonote = strtolower($module).'/'.strtolower($tabobj).'_note.php'; $pathtocontact = strtolower($module).'/'.strtolower($tabobj).'_contact.php'; $pathtophpunit = strtolower($module).'/test/phpunit/'.strtolower($tabobj).'Test.php'; - $pathtosql = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'.sql'; - $pathtosqlextra = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'_extrafields.sql'; - $pathtosqlkey = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'.key.sql'; - $pathtosqlextrakey = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'_extrafields.key.sql'; + + // Try to load object class file + clearstatcache(true); + if (function_exists('opcache_invalidate')) { + opcache_invalidate($dirread.'/'.$pathtoclass, true); // remove the include cache hell ! + } + + if (empty($forceddirread) && empty($dirread)) { + $result = dol_include_once($pathtoclass); + $stringofinclude = "dol_include_once(".$pathtoclass.")"; + } else { + $result = @include_once $dirread.'/'.$pathtoclass; + $stringofinclude = "@include_once ".$dirread.'/'.$pathtoclass; + } + if (class_exists($tabobj)) { + try { + $tmpobjet = @new $tabobj($db); + } catch (Exception $e) { + dol_syslog('Failed to load Constructor of class: '.$e->getMessage(), LOG_WARNING); + } + } else { + print ''.$langs->trans('Failed to find the class '.$tabobj.' despite the '.$stringofinclude).'

'; + } + + // Define path for sql file + $pathtosql = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'-'.strtolower($module).'.sql'; + $result = dol_buildpath($pathtosql); + if (! dol_is_file($result)) { + $pathtosql = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'.sql'; + $result = dol_buildpath($pathtosql); + if (! dol_is_file($result)) { + $pathtosql = 'install/mysql/tables/llx_'.strtolower($module).'_'.strtolower($tabobj).'-'.strtolower($module).'.sql'; + $result = dol_buildpath($pathtosql); + if (! dol_is_file($result)) { + $pathtosql = 'install/mysql/tables/llx_'.strtolower($module).'-'.strtolower($module).'.sql'; + $result = dol_buildpath($pathtosql); + if (! dol_is_file($result)) { + $pathtosql = 'install/mysql/tables/llx_'.strtolower($module).'.sql'; + $pathtosqlextra = 'install/mysql/tables/llx_'.strtolower($module).'_extrafields.sql'; + $result = dol_buildpath($pathtosql); + } else { + $pathtosqlextra = 'install/mysql/tables/llx_'.strtolower($module).'_extrafields-'.strtolower($module).'.sql'; + } + } else { + $pathtosqlextra = 'install/mysql/tables/llx_'.strtolower($module).'_'.strtolower($tabobj).'_extrafields-'.strtolower($module).'.sql'; + } + } else { + $pathtosqlextra = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'_extrafields.sql'; + } + } else { + $pathtosqlextra = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'_extrafields-'.strtolower($module).'.sql'; + } + $pathtosqlroot = preg_replace('/\/llx_.*$/', '', $pathtosql); + + $pathtosqlkey = preg_replace('/\.sql$/', '.key.sql', $pathtosql); + $pathtosqlextrakey = preg_replace('/\.sql$/', '.key.sql', $pathtosqlextra); + $pathtolib = strtolower($module).'/lib/'.strtolower($module).'.lib.php'; $pathtoobjlib = strtolower($module).'/lib/'.strtolower($module).'_'.strtolower($tabobj).'.lib.php'; $pathtopicto = strtolower($module).'/img/object_'.strtolower($tabobj).'.png'; @@ -2642,6 +2695,10 @@ if ($module == 'initmodule') { $urloflist = dol_buildpath('/'.$pathtolist, 1); $urlofcard = dol_buildpath('/'.$pathtocard, 1); + + + + print '
'; // Main DAO class file print ' '.$langs->trans("ClassFile").' : '.(dol_is_file($realpathtoclass) ? '' : '').preg_replace('/^'.strtolower($module).'\//', '', $pathtoclass).(dol_is_file($realpathtoclass) ? '' : '').''; @@ -2772,28 +2829,6 @@ if ($module == 'initmodule') { print '


'; - clearstatcache(true); - if (function_exists('opcache_invalidate')) { - opcache_invalidate($dirread.'/'.$pathtoclass, true); // remove the include cache hell ! - } - - if (empty($forceddirread) && empty($dirread)) { - $result = dol_include_once($pathtoclass); - $stringofinclude = "dol_include_once(".$pathtoclass.")"; - } else { - $result = @include_once $dirread.'/'.$pathtoclass; - $stringofinclude = "@include_once ".$dirread.'/'.$pathtoclass; - } - if (class_exists($tabobj)) { - try { - $tmpobjet = @new $tabobj($db); - } catch (Exception $e) { - dol_syslog('Failed to load Constructor of class: '.$e->getMessage(), LOG_WARNING); - } - } else { - print ''.$langs->trans('Failed to find the class '.$tabobj.' despite the '.$stringofinclude).'
'; - } - if (!empty($tmpobjet)) { $reflector = new ReflectionClass($tabobj); $reflectorproperties = $reflector->getProperties(); // Can also use get_object_vars From 504383c4a27fab16283eb261a5b8b92cfdaa5449 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 15 Jul 2022 14:37:35 +0200 Subject: [PATCH 226/826] Fix reposition --- htdocs/modulebuilder/index.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 7d359ec0966..f256d8d4acc 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -2840,6 +2840,7 @@ if ($module == 'initmodule') { print ''; print ''; print ''; + print ''; print ''; print ''; @@ -3028,8 +3029,8 @@ if ($module == 'initmodule') { print ''; print ''; print ''; - print ''; - print ''; + print ''; + print ''; print ''; } else { print ''; From 1d0ba05e90530c2f3f2c4484e9042744b4f94b0c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 15 Jul 2022 15:35:45 +0200 Subject: [PATCH 227/826] Debug --- htdocs/core/lib/modulebuilder.lib.php | 64 ++++++++++++++++++--------- htdocs/langs/en_US/modulebuilder.lang | 1 + htdocs/modulebuilder/index.php | 10 ++--- 3 files changed, 50 insertions(+), 25 deletions(-) diff --git a/htdocs/core/lib/modulebuilder.lib.php b/htdocs/core/lib/modulebuilder.lib.php index a775569407a..9e17d925dbe 100644 --- a/htdocs/core/lib/modulebuilder.lib.php +++ b/htdocs/core/lib/modulebuilder.lib.php @@ -30,7 +30,7 @@ * @param string $objectname Name of object * @param string $newmask New mask * @param string $readdir Directory source (use $destdir when not defined) - * @param string $addfieldentry Array of the field entry to add array('key'=>,'type'=>,''label'=>,'visible'=>,'enabled'=>,'position'=>,'notnull'=>','index'=>,'searchall'=>,'comment'=>,'help'=>,'isameasure') + * @param string $addfieldentry Array of 1 field entry to add array('key'=>,'type'=>,''label'=>,'visible'=>,'enabled'=>,'position'=>,'notnull'=>','index'=>,'searchall'=>,'comment'=>,'help'=>,'isameasure') * @param string $delfieldentry Id of field to remove * @return int|object <=0 if KO, Object if OK * @see rebuildObjectSql() @@ -40,7 +40,7 @@ function rebuildObjectClass($destdir, $module, $objectname, $newmask, $readdir = global $db, $langs; if (empty($objectname)) { - return -1; + return -6; } if (empty($readdir)) { $readdir = $destdir; @@ -48,9 +48,11 @@ function rebuildObjectClass($destdir, $module, $objectname, $newmask, $readdir = if (!empty($addfieldentry['arrayofkeyval']) && !is_array($addfieldentry['arrayofkeyval'])) { dol_print_error('', 'Bad parameter addfieldentry with a property arrayofkeyval defined but that is not an array.'); - return -1; + return -7; } + $error = 0; + // Check parameters if (is_array($addfieldentry) && count($addfieldentry) > 0) { if (empty($addfieldentry['name'])) { @@ -62,8 +64,8 @@ function rebuildObjectClass($destdir, $module, $objectname, $newmask, $readdir = return -2; } if (!preg_match('/^(integer|price|sellist|varchar|double|text|html|duration)/', $addfieldentry['type']) - && !preg_match('/^(boolean|real|date|datetime|timestamp)$/', $addfieldentry['type'])) { - setEventMessages($langs->trans('BadValueForType', $objectname), null, 'errors'); + && !preg_match('/^(boolean|smallint|real|date|datetime|timestamp|phone|mail|url|ip|password)$/', $addfieldentry['type'])) { + setEventMessages($langs->trans('BadValueForType', $addfieldentry['type']), null, 'errors'); return -2; } } @@ -217,10 +219,14 @@ function rebuildObjectClass($destdir, $module, $objectname, $newmask, $readdir = dol_mkdir(dirname($pathoffiletoedittarget)); //file_put_contents($pathoffiletoedittmp, $contentclass); - file_put_contents(dol_osencode($pathoffiletoedittarget), $contentclass); - @chmod($pathoffiletoedittarget, octdec($newmask)); + $result = file_put_contents(dol_osencode($pathoffiletoedittarget), $contentclass); + if ($result) { + @chmod($pathoffiletoedittarget, octdec($newmask)); + } else { + $error++; + } - return $object; + return $error ? -1 : $object; } catch (Exception $e) { print $e->getMessage(); return -5; @@ -257,13 +263,33 @@ function rebuildObjectSql($destdir, $module, $objectname, $newmask, $readdir = ' // Edit .sql file if ($moduletype == 'internal') { - $pathoffiletoeditsrc = $readdir.'/../install/mysql/tables/llx_'.strtolower($module).'_'.strtolower($objectname).'.sql'; - $pathoffiletoedittarget = $destdir.'/../install/mysql/tables/llx_'.strtolower($module).'_'.strtolower($objectname).'.sql'.($readdir != $destdir ? '.new' : ''); + $pathoffiletoeditsrc = '/../install/mysql/tables/llx_'.strtolower($module).'_'.strtolower($objectname).'.sql'; + if (! dol_is_file($readdir.$pathoffiletoeditsrc)) { + $pathoffiletoeditsrc = '/../install/mysql/tables/llx_'.strtolower($module).'_'.strtolower($objectname).'-'.strtolower($module).'.sql'; + if (! dol_is_file($readdir.$pathoffiletoeditsrc)) { + $pathoffiletoeditsrc = '/../install/mysql/tables/llx_'.strtolower($module).'-'.strtolower($module).'.sql'; + if (! dol_is_file($readdir.$pathoffiletoeditsrc)) { + $pathoffiletoeditsrc = '/../install/mysql/tables/llx_'.strtolower($module).'.sql'; + } + } + } } else { - $pathoffiletoeditsrc = $readdir.'/sql/llx_'.strtolower($module).'_'.strtolower($objectname).'.sql'; - $pathoffiletoedittarget = $destdir.'/sql/llx_'.strtolower($module).'_'.strtolower($objectname).'.sql'.($readdir != $destdir ? '.new' : ''); + $pathoffiletoeditsrc = '/sql/llx_'.strtolower($module).'_'.strtolower($objectname).'.sql'; + if (! dol_is_file($readdir.$pathoffiletoeditsrc)) { + $pathoffiletoeditsrc = '/sql/llx_'.strtolower($module).'_'.strtolower($objectname).'-'.strtolower($module).'.sql'; + if (! dol_is_file($readdir.$pathoffiletoeditsrc)) { + $pathoffiletoeditsrc = '/sql/llx_'.strtolower($module).'-'.strtolower($module).'.sql'; + if (! dol_is_file($readdir.$pathoffiletoeditsrc)) { + $pathoffiletoeditsrc = '/sql/llx_'.strtolower($module).'.sql'; + } + } + } } + // Complete path to be full path + $pathoffiletoedittarget = $destdir.$pathoffiletoeditsrc.($readdir != $destdir ? '.new' : ''); + $pathoffiletoeditsrc = $readdir.$pathoffiletoeditsrc; + if (!dol_is_file($pathoffiletoeditsrc)) { $langs->load("errors"); setEventMessages($langs->trans("ErrorFileNotFound", $pathoffiletoeditsrc), null, 'errors'); @@ -340,16 +366,13 @@ function rebuildObjectSql($destdir, $module, $objectname, $newmask, $readdir = ' @chmod($pathoffiletoedittarget, octdec($newmask)); } else { $error++; + setEventMessages($langs->trans("ErrorFailToCreateFile", $pathoffiletoedittarget), null, 'errors'); } // Edit .key.sql file - if ($moduletype == 'internal') { - $pathoffiletoeditsrc = $readdir.'/../install/mysql/tables/llx_'.strtolower($module).'_'.strtolower($objectname).'.key.sql'; - $pathoffiletoedittarget = $destdir.'/../install/mysql/tables/llx_'.strtolower($module).'_'.strtolower($objectname).'.key.sql'.($readdir != $destdir ? '.new' : ''); - } else { - $pathoffiletoeditsrc = $destdir.'/sql/llx_'.strtolower($module).'_'.strtolower($objectname).'.key.sql'; - $pathoffiletoedittarget = $destdir.'/sql/llx_'.strtolower($module).'_'.strtolower($objectname).'.key.sql'.($readdir != $destdir ? '.new' : ''); - } + $pathoffiletoeditsrc = preg_replace('/\.sql$/', '.key.sql', $pathoffiletoeditsrc); + $pathoffiletoedittarget = preg_replace('/\.sql$/', '.key.sql', $pathoffiletoedittarget); + $pathoffiletoedittarget = preg_replace('/\.sql.new$/', '.key.sql.new', $pathoffiletoedittarget); $contentsql = file_get_contents(dol_osencode($pathoffiletoeditsrc), 'r'); @@ -378,10 +401,11 @@ function rebuildObjectSql($destdir, $module, $objectname, $newmask, $readdir = ' dol_mkdir(dirname($pathoffiletoedittarget)); $result2 = file_put_contents($pathoffiletoedittarget, $contentsql); - if ($result) { + if ($result2) { @chmod($pathoffiletoedittarget, octdec($newmask)); } else { $error++; + setEventMessages($langs->trans("ErrorFailToCreateFile", $pathoffiletoedittarget), null, 'errors'); } return $error ? -1 : 1; diff --git a/htdocs/langs/en_US/modulebuilder.lang b/htdocs/langs/en_US/modulebuilder.lang index 3e029857a10..0bac9e2c435 100644 --- a/htdocs/langs/en_US/modulebuilder.lang +++ b/htdocs/langs/en_US/modulebuilder.lang @@ -155,3 +155,4 @@ LinkToParentMenu=Parent menu (fk_xxxxmenu) ListOfTabsEntries=List of tab entries TabsDefDesc=Define here the tabs provided by your module TabsDefDescTooltip=The tabs provided by your module/application are defined into the array $this->tabs into the module descriptor file. You can edit manually this file or use the embedded editor. +BadValueForType=Bad value for type %s \ No newline at end of file diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index f256d8d4acc..29cfb898a2c 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -1518,9 +1518,10 @@ if ($dirins && $action == 'addproperty' && empty($cancel) && !empty($module) && $error++; }*/ + $moduletype = $listofmodules[strtolower($module)]['moduletype']; + // Edit the class file to write properties if (!$error) { - $moduletype = 'external'; $object = rebuildObjectClass($destdir, $module, $objectname, $newmask, $srcdir, $addfieldentry, $moduletype); if (is_numeric($object) && $object <= 0) { @@ -1530,21 +1531,20 @@ if ($dirins && $action == 'addproperty' && empty($cancel) && !empty($module) && // Edit sql with new properties if (!$error) { - $moduletype = 'external'; - $result = rebuildObjectSql($destdir, $module, $objectname, $newmask, $srcdir, $object, $moduletype); + if ($result <= 0) { $error++; } } if (!$error) { + clearstatcache(true); + setEventMessages($langs->trans('FilesForObjectUpdated', $objectname), null); setEventMessages($langs->trans('WarningDatabaseIsNotUpdated'), null); - clearstatcache(true); - // Make a redirect to reload all data header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabobj='.$objectname.'&nocache='.time()); From 20380fb210b91ea515f8fba778a5f623c31552d0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 15 Jul 2022 15:35:56 +0200 Subject: [PATCH 228/826] Add status suspended --- .../partnership/class/partnership.class.php | 38 +++++++++---------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/htdocs/partnership/class/partnership.class.php b/htdocs/partnership/class/partnership.class.php index 85787075f28..38d8c333749 100644 --- a/htdocs/partnership/class/partnership.class.php +++ b/htdocs/partnership/class/partnership.class.php @@ -105,8 +105,8 @@ class Partnership extends CommonObject public $fields=array( 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>0, 'noteditable'=>'1', 'index'=>1, 'css'=>'left', 'comment'=>"Id"), 'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>'1', 'position'=>10, 'notnull'=>1, 'visible'=>4, 'noteditable'=>'1', 'default'=>'(PROV)', 'index'=>1, 'searchall'=>1, 'showoncombobox'=>'1', 'comment'=>"Reference of object"), - 'entity' => array('type' => 'integer', 'label' => 'Entity', 'default' => 1, 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 15, 'index' => 1), - 'fk_type' => array('type' => 'integer:PartnershipType:partnership/class/partnership_type.class.php:0:active=1', 'label' => 'Type', 'notnull'=>1, 'enabled' => 1, 'visible' => 1, 'position' => 20), + 'entity' => array('type'=>'integer', 'label'=>'Entity', 'enabled'=>'1', 'position'=>15, 'notnull'=>1, 'visible'=>-2, 'default'=>'1', 'index'=>1,), + 'fk_type' => array('type'=>'integer:PartnershipType:partnership/class/partnership_type.class.php:0:active=1', 'label'=>'Type', 'enabled'=>'1', 'position'=>20, 'notnull'=>1, 'visible'=>1,), 'note_public' => array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>'1', 'position'=>61, 'notnull'=>0, 'visible'=>0,), 'note_private' => array('type'=>'html', 'label'=>'NotePrivate', 'enabled'=>'1', 'position'=>62, 'notnull'=>0, 'visible'=>0,), 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>'1', 'position'=>500, 'notnull'=>1, 'visible'=>-2,), @@ -118,38 +118,34 @@ class Partnership extends CommonObject 'model_pdf' => array('type'=>'varchar(255)', 'label'=>'Model pdf', 'enabled'=>'1', 'position'=>1010, 'notnull'=>-1, 'visible'=>0,), 'date_partnership_start' => array('type'=>'date', 'label'=>'DatePartnershipStart', 'enabled'=>'1', 'position'=>52, 'notnull'=>1, 'visible'=>1,), 'date_partnership_end' => array('type'=>'date', 'label'=>'DatePartnershipEnd', 'enabled'=>'1', 'position'=>53, 'notnull'=>0, 'visible'=>1,), - 'status' => array('type'=>'smallint', 'label'=>'Status', 'enabled'=>'1', 'position'=>54, 'notnull'=>0, 'visible'=>2, 'index'=>1, 'arrayofkeyval'=>array('-1'=>'','0'=>'Draft', '1'=>'Accepted', '2'=>'Refused', '9'=>'Terminated'),), - 'url_to_check' => array('type'=>'varchar(255)', 'label'=>'UrlToCheck', 'enabled'=>'1', 'position'=>70, 'notnull'=>0, 'visible'=>-1), + 'status' => array('type'=>'smallint', 'label'=>'Status', 'enabled'=>'1', 'position'=>54, 'notnull'=>0, 'visible'=>2, 'index'=>1, 'arrayofkeyval'=>array('-1'=>'', '0'=>'Draft', '1'=>'Accepted', '2'=>'Refused', '8'=>'Suspended', '9'=>'Terminated'),), + 'url_to_check' => array('type'=>'varchar(255)', 'label'=>'UrlToCheck', 'enabled'=>'1', 'position'=>70, 'notnull'=>0, 'visible'=>-1,), 'count_last_url_check_error' => array('type'=>'integer', 'label'=>'CountLastUrlCheckError', 'enabled'=>'1', 'position'=>71, 'notnull'=>0, 'visible'=>-2, 'default'=>'0',), 'last_check_backlink' => array('type'=>'datetime', 'label'=>'LastCheckBacklink', 'enabled'=>'1', 'position'=>72, 'notnull'=>0, 'visible'=>-2,), 'reason_decline_or_cancel' => array('type'=>'text', 'label'=>'ReasonDeclineOrCancel', 'enabled'=>'1', 'position'=>73, 'notnull'=>0, 'visible'=>-2,), - // fk_member and fk_soc are added into constructor + 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1:status=1 AND entity IN (__SHARED_ENTITIES__)', 'label'=>'ThirdParty', 'picto'=>'company', 'enabled'=>'1', 'position'=>50, 'notnull'=>-1, 'visible'=>1, 'index'=>1, 'css'=>'maxwidth500', 'csslist'=>'tdoverflowmax150',), ); - - /** - * @var int rowid - * @deprecated - * @see $id - */ public $rowid; - - public $fk_soc; // Link to thirdparty - public $fk_member; // Link to member - + public $ref; + public $entity; + public $fk_type; + public $note_public; + public $note_private; + public $date_creation; public $tms; public $fk_user_creat; public $fk_user_modif; - - public $status; + public $last_main_doc; + public $import_key; + public $model_pdf; public $date_partnership_start; public $date_partnership_end; + public $status; + public $url_to_check; public $count_last_url_check_error; public $last_check_backlink; - - /** - * @var string reason_decline_or_cancel - */ public $reason_decline_or_cancel; + public $fk_soc; // END MODULEBUILDER PROPERTIES From 2e42f45c9900ac0bb93b93ea450b1a56a2a28ca1 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 16 Jul 2022 11:40:38 +0200 Subject: [PATCH 229/826] FIX php8 --- .../interface_50_modNotification_Notification.class.php | 4 +++- htdocs/datapolicy/class/actions_datapolicy.class.php | 4 +++- htdocs/societe/paymentmodes.php | 1 + htdocs/societe/societecontact.php | 9 +-------- htdocs/stripe/class/stripe.class.php | 2 +- 5 files changed, 9 insertions(+), 11 deletions(-) diff --git a/htdocs/core/triggers/interface_50_modNotification_Notification.class.php b/htdocs/core/triggers/interface_50_modNotification_Notification.class.php index 6e4f8cb1563..b4d32860c82 100644 --- a/htdocs/core/triggers/interface_50_modNotification_Notification.class.php +++ b/htdocs/core/triggers/interface_50_modNotification_Notification.class.php @@ -90,7 +90,7 @@ class InterfaceNotification extends DolibarrTriggers */ public function getListOfManagedEvents() { - global $conf; + global $conf, $action; global $hookmanager; @@ -100,6 +100,8 @@ class InterfaceNotification extends DolibarrTriggers } $hookmanager->initHooks(array('notification')); + $parameters = array(); + $object = new stdClass(); $reshook = $hookmanager->executeHooks('notifsupported', $parameters, $object, $action); if (empty($reshook)) { if (!empty($hookmanager->resArray['arrayofnotifsupported'])) { diff --git a/htdocs/datapolicy/class/actions_datapolicy.class.php b/htdocs/datapolicy/class/actions_datapolicy.class.php index 5a27b97b691..6b7e27c67aa 100644 --- a/htdocs/datapolicy/class/actions_datapolicy.class.php +++ b/htdocs/datapolicy/class/actions_datapolicy.class.php @@ -417,17 +417,19 @@ class ActionsDatapolicy } if (GETPOST('socid')) { + /* Removed due to awful harcoded values require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php'; $societe = new Societe($this->db); $societe->fetch(GETPOST('socid')); - if (!in_array($object->forme_juridique_code, array(11, 12, 13, 15, 17, 18, 19, 35, 60, 200, 311, 312, 316, 401, 600, 700, 1005)) && $societe->typent_id != 8) { + if (!empty($object->forme_juridique_code) && !in_array($object->forme_juridique_code, array(11, 12, 13, 15, 17, 18, 19, 35, 60, 200, 311, 312, 316, 401, 600, 700, 1005)) && $societe->typent_id != 8) { require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; $jsscript .= ''; } + */ } } elseif ($parameters['currentcontext'] == 'contactcard') { if (GETPOST('action') == 'create' || GETPOST('action') == 'edit') { diff --git a/htdocs/societe/paymentmodes.php b/htdocs/societe/paymentmodes.php index c0bff452b9c..a63b91b024b 100644 --- a/htdocs/societe/paymentmodes.php +++ b/htdocs/societe/paymentmodes.php @@ -682,6 +682,7 @@ $title = $langs->trans("ThirdParty"); if (!empty($conf->global->MAIN_HTML_TITLE) && preg_match('/thirdpartynameonly/', $conf->global->MAIN_HTML_TITLE) && $object->name) { $title = $object->name." - ".$langs->trans('PaymentInformation'); } +$help_url = ''; llxHeader('', $title, $help_url); diff --git a/htdocs/societe/societecontact.php b/htdocs/societe/societecontact.php index df10c0d4bf9..b1e5174820c 100644 --- a/htdocs/societe/societecontact.php +++ b/htdocs/societe/societecontact.php @@ -128,17 +128,10 @@ $contactstatic = new Contact($db); $userstatic = new User($db); -/* *************************************************************************** */ -/* */ -/* Mode vue et edition */ -/* */ -/* *************************************************************************** */ +// View and edit if ($id > 0 || !empty($ref)) { if ($object->fetch($id, $ref) > 0) { - $soc = new Societe($db); - $soc->fetch($object->socid); - $head = societe_prepare_head($object); print dol_get_fiche_head($head, 'contact', $langs->trans("ThirdParty"), -1, 'company'); diff --git a/htdocs/stripe/class/stripe.class.php b/htdocs/stripe/class/stripe.class.php index b14ed0e8ca6..00d3c4a0d94 100644 --- a/htdocs/stripe/class/stripe.class.php +++ b/htdocs/stripe/class/stripe.class.php @@ -115,7 +115,7 @@ class Stripe extends CommonObject $tokenstring = $obj->tokenstring; $tmparray = json_decode($tokenstring); - $key = $tmparray->stripe_user_id; + $key = empty($tmparray->stripe_user_id) ? '' : $tmparray->stripe_user_id; } else { $tokenstring = ''; } From 0ac68c8635893690a7e66d5956dc62030aef876a Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Mon, 18 Jul 2022 09:21:51 +0200 Subject: [PATCH 230/826] fix signature style in email template --- htdocs/core/class/html.formmail.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php index 4356bfd932e..799163fdbf8 100644 --- a/htdocs/core/class/html.formmail.class.php +++ b/htdocs/core/class/html.formmail.class.php @@ -935,7 +935,7 @@ class FormMail extends Form $out .= ''; } else { if (!isset($this->ckeditortoolbar)) { - $this->ckeditortoolbar = 'dolibarr_notes'; + $this->ckeditortoolbar = 'dolibarr_mailings'; } // Editor wysiwyg From 311d69da4e13d39397f6a91620d66910bf166d58 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 18 Jul 2022 11:07:48 +0200 Subject: [PATCH 231/826] FIX Picto google plus --- htdocs/admin/dict.php | 2 ++ htdocs/install/mysql/data/llx_c_socialnetworks.sql | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index 6453210e596..fa5d6deae97 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -2090,6 +2090,8 @@ if ($id > 0) { $valuetoshow = $langs->trans($obj->{$value}); } elseif ($value == 'block_if_negative') { $valuetoshow = yn($obj->{$value}); + } elseif ($value == 'icon') { + $valuetoshow = $obj->{$value}." ".img_picto("", $obj->{$value}); } elseif ($value == 'type_duration') { $TDurationTypes = array('y'=>$langs->trans('Years'), 'm'=>$langs->trans('Month'), 'w'=>$langs->trans('Weeks'), 'd'=>$langs->trans('Days'), 'h'=>$langs->trans('Hours'), 'i'=>$langs->trans('Minutes')); $valuetoshow =$TDurationTypes[$obj->{$value}]; diff --git a/htdocs/install/mysql/data/llx_c_socialnetworks.sql b/htdocs/install/mysql/data/llx_c_socialnetworks.sql index 468086291fc..7741f8cdfef 100644 --- a/htdocs/install/mysql/data/llx_c_socialnetworks.sql +++ b/htdocs/install/mysql/data/llx_c_socialnetworks.sql @@ -37,7 +37,7 @@ INSERT INTO llx_c_socialnetworks (entity, code, label, url, icon, active) VALUES INSERT INTO llx_c_socialnetworks (entity, code, label, url, icon, active) VALUES ( 1, 'gifycat', 'Gificat', '{socialid}', '', 0); INSERT INTO llx_c_socialnetworks (entity, code, label, url, icon, active) VALUES ( 1, 'giphy', 'Giphy', '{socialid}', '', 0); INSERT INTO llx_c_socialnetworks (entity, code, label, url, icon, active) VALUES ( 1, 'github', 'GitHub', 'https://www.github.com/{socialid}', '', 0); -INSERT INTO llx_c_socialnetworks (entity, code, label, url, icon, active) VALUES ( 1, 'googleplus', 'GooglePlus', 'https://www.googleplus.com/{socialid}', 'fa-google-plus-g', 0); +INSERT INTO llx_c_socialnetworks (entity, code, label, url, icon, active) VALUES ( 1, 'googleplus', 'GooglePlus', 'https://www.googleplus.com/{socialid}', 'fa-google-plus', 0); INSERT INTO llx_c_socialnetworks (entity, code, label, url, icon, active) VALUES ( 1, 'instagram', 'Instagram', 'https://www.instagram.com/{socialid}', 'fa-instagram', 1); INSERT INTO llx_c_socialnetworks (entity, code, label, url, icon, active) VALUES ( 1, 'linkedin', 'LinkedIn', 'https://www.linkedin.com/{socialid}', 'fa-linkedin', 1); INSERT INTO llx_c_socialnetworks (entity, code, label, url, icon, active) VALUES ( 1, 'mastodon', 'Mastodon', '{socialid}', '', 0); From 076d93452f31ada7833105d36e4528a8f2a68dcc Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 18 Jul 2022 11:51:28 +0200 Subject: [PATCH 232/826] FIX Debug v16 --- htdocs/contact/card.php | 14 ++++----- htdocs/core/class/html.formcompany.class.php | 15 +++++----- htdocs/core/lib/company.lib.php | 31 +++++++++++++++----- htdocs/societe/card.php | 16 ++++++++++ htdocs/societe/contact.php | 2 +- htdocs/user/class/user.class.php | 11 ++++--- htdocs/user/home.php | 18 ++++++------ 7 files changed, 71 insertions(+), 36 deletions(-) diff --git a/htdocs/contact/card.php b/htdocs/contact/card.php index 67b144ffd89..9e3036e29a0 100644 --- a/htdocs/contact/card.php +++ b/htdocs/contact/card.php @@ -1299,11 +1299,10 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { $action = 'presend'; } + // View mode if (!empty($id) && $action != 'edit' && $action != 'create') { $objsoc = new Societe($db); - // View mode - // Show errors dol_htmloutput_errors(is_numeric($error) ? '' : $error, $errors); @@ -1528,9 +1527,12 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { if ($object->user_id) { $dolibarr_user = new User($db); $result = $dolibarr_user->fetch($object->user_id); - print $dolibarr_user->getLoginUrl(1); + print $dolibarr_user->getLoginUrl(-1); } else { - print $langs->trans("NoDolibarrAccess"); + //print ''.$langs->trans("NoDolibarrAccess").''; + if (!$object->user_id && $user->rights->user->user->creer) { + print '
'.img_picto($langs->trans("CreateDolibarrLogin"), 'add').' '.$langs->trans("CreateDolibarrLogin").''; + } } print ''; @@ -1563,10 +1565,6 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print ''.$langs->trans('Modify').''; } - if (!$object->user_id && $user->rights->user->user->creer) { - print ''.$langs->trans("CreateDolibarrLogin").''; - } - // Activer if ($object->statut == 0 && $user->rights->societe->contact->creer) { print ''.$langs->trans("Reactivate").''; diff --git a/htdocs/core/class/html.formcompany.class.php b/htdocs/core/class/html.formcompany.class.php index 32f2a9b1007..2a900ea53a4 100644 --- a/htdocs/core/class/html.formcompany.class.php +++ b/htdocs/core/class/html.formcompany.class.php @@ -825,13 +825,14 @@ class FormCompany extends Form /** * showContactRoles on view and edit mode * - * @param string $htmlname Html component name and id - * @param Contact $contact Contact Obejct - * @param string $rendermode view, edit - * @param array $selected $key=>$val $val is selected Roles for input mode - * @return string String with contacts roles + * @param string $htmlname Html component name and id + * @param Contact $contact Contact Obejct + * @param string $rendermode view, edit + * @param array $selected $key=>$val $val is selected Roles for input mode + * @param string $morecss More css + * @return string String with contacts roles */ - public function showRoles($htmlname, Contact $contact, $rendermode = 'view', $selected = array()) + public function showRoles($htmlname, Contact $contact, $rendermode = 'view', $selected = array(), $morecss = 'minwidth500') { if ($rendermode === 'view') { $toprint = array(); @@ -856,7 +857,7 @@ class FormCompany extends Form $selected = $newselected; } } - return $this->multiselectarray($htmlname, $contactType, $selected, 0, 0, 'minwidth500'); + return $this->multiselectarray($htmlname, $contactType, $selected, 0, 0, $morecss); } return 'ErrorBadValueForParameterRenderMode'; // Should not happened diff --git a/htdocs/core/lib/company.lib.php b/htdocs/core/lib/company.lib.php index cc99471a69f..e6398065af1 100644 --- a/htdocs/core/lib/company.lib.php +++ b/htdocs/core/lib/company.lib.php @@ -890,14 +890,15 @@ function show_projects($conf, $langs, $db, $object, $backtopage = '', $nocreatel /** * Show html area for list of contacts * - * @param Conf $conf Object conf - * @param Translate $langs Object langs - * @param DoliDB $db Database handler - * @param Societe $object Third party object - * @param string $backtopage Url to go once contact is created + * @param Conf $conf Object conf + * @param Translate $langs Object langs + * @param DoliDB $db Database handler + * @param Societe $object Third party object + * @param string $backtopage Url to go once contact is created + * @param int $showuserlogin 1=Show also user login if it exists * @return int */ -function show_contacts($conf, $langs, $db, $object, $backtopage = '') +function show_contacts($conf, $langs, $db, $object, $backtopage = '', $showuserlogin = 0) { global $user, $conf, $extrafields, $hookmanager; global $contextpage; @@ -1131,13 +1132,16 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') if (in_array($key, array('statut'))) { print $form->selectarray('search_status', array('-1'=>'', '0'=>$contactstatic->LibStatut(0, 1), '1'=>$contactstatic->LibStatut(1, 1)), $search_status); } elseif (in_array($key, array('role'))) { - print $formcompany->showRoles("search_roles", $contactstatic, 'edit', $search_roles); + print $formcompany->showRoles("search_roles", $contactstatic, 'edit', $search_roles, 'minwidth200 maxwidth300'); } else { print ''; } print ''; } } + if ($showuserlogin) { + print ''; + } // Extra fields $extrafieldsobjectkey = $contactstatic->table_element; include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; @@ -1177,6 +1181,9 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') print getTitleFieldOfList($arrayfields['sc.'.$key]['label'], 0, $_SERVER['PHP_SELF'], '', '', $param, ($align ? 'class="'.$align.'"' : ''), $sortfield, $sortorder, $align.' ')."\n"; } } + if ($showuserlogin) { + print ''.$langs->trans("DolibarrLogin").''; + } // Extra fields $extrafieldsobjectkey = $contactstatic->table_element; include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; @@ -1275,6 +1282,16 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') print ''.$contactstatic->getLibStatut(5).''; } + if ($showuserlogin) { + print ''; + $tmpuser= new User($db); + $resfetch = $tmpuser->fetch(0, '', '', 0, -1, '', $contactstatic->id); + if ($resfetch > 0) { + print $tmpuser->getNomUrl(1, '', 0, 0, 24, 1); + } + print ''; + } + // Extra fields $extrafieldsobjectkey = $contactstatic->table_element; include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; diff --git a/htdocs/societe/card.php b/htdocs/societe/card.php index 8e347a6d487..93540eb097c 100644 --- a/htdocs/societe/card.php +++ b/htdocs/societe/card.php @@ -3033,6 +3033,22 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print "\n"; } + // Link user (you must create a contact to get a user) + /* + print ''.$langs->trans("DolibarrLogin").''; + if ($object->user_id) { + $dolibarr_user = new User($db); + $result = $dolibarr_user->fetch($object->user_id); + print $dolibarr_user->getLoginUrl(-1); + } else { + //print ''.$langs->trans("NoDolibarrAccess").''; + if (!$object->user_id && $user->rights->user->user->creer) { + print ''.img_picto($langs->trans("CreateDolibarrLogin"), 'add').' '.$langs->trans("CreateDolibarrLogin").''; + } + } + print ''; + */ + // Webservices url/key if (!empty($conf->syncsupplierwebservices->enabled)) { print ''.$langs->trans("WebServiceURL").''.dol_print_url($object->webservices_url).''; diff --git a/htdocs/societe/contact.php b/htdocs/societe/contact.php index a09c9751f1f..4ecfc2a8cf4 100644 --- a/htdocs/societe/contact.php +++ b/htdocs/societe/contact.php @@ -173,7 +173,7 @@ print '
'; if ($action != 'presend') { // Contacts list if (empty($conf->global->SOCIETE_DISABLE_CONTACTS)) { - $result = show_contacts($conf, $langs, $db, $object, $_SERVER["PHP_SELF"].'?socid='.$object->id); + $result = show_contacts($conf, $langs, $db, $object, $_SERVER["PHP_SELF"].'?socid='.$object->id, 1); } } diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index ee6d0e7bd14..588dba10a19 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -416,9 +416,10 @@ class User extends CommonObject * @param int $loadpersonalconf 1=also load personal conf of user (in $user->conf->xxx), 0=do not load personal conf. * @param int $entity If a value is >= 0, we force the search on a specific entity. If -1, means search depens on default setup. * @param int $email If defined, email to used for search + * @param int $fk_socpeople If defined, id of contact for search * @return int <0 if KO, 0 not found, >0 if OK */ - public function fetch($id = '', $login = '', $sid = '', $loadpersonalconf = 0, $entity = -1, $email = '') + public function fetch($id = '', $login = '', $sid = '', $loadpersonalconf = 0, $entity = -1, $email = '', $fk_socpeople = 0) { global $conf, $user; @@ -486,6 +487,8 @@ class User extends CommonObject $sql .= " AND u.login = '".$this->db->escape($login)."'"; } elseif ($email) { $sql .= " AND u.email = '".$this->db->escape($email)."'"; + } elseif ($fk_socpeople > 0) { + $sql .= " AND u.fk_socpeople = ".((int) $fk_socpeople); } else { $sql .= " AND u.rowid = ".((int) $id); } @@ -2755,10 +2758,10 @@ class User extends CommonObject if (empty($hidethirdpartylogo)) { $companylink = ' '.$thirdpartystatic->getNomUrl(2, (($option == 'nolink') ? 'nolink' : '')); // picto only of company } - $company = ' ('.$langs->trans("Company").': '.dol_string_nohtmltag($thirdpartystatic->name).')'; + $company = ' ('.$langs->trans("Company").': '.img_picto('', 'company').' '.dol_string_nohtmltag($thirdpartystatic->name).')'; } - $type = ($this->socid ? $langs->trans("External").$company : $langs->trans("Internal")); - $label .= '
'.$langs->trans("Type").': '.dol_string_nohtmltag($type); + $type = ($this->socid ? $langs->trans("ExternalUser").$company : $langs->trans("InternalUser")); + $label .= '
'.$langs->trans("Type").': '.$type; $label .= '
'; if ($infologin > 0) { $label .= '
'; diff --git a/htdocs/user/home.php b/htdocs/user/home.php index c8dbdf2c1b8..a8b8bb92086 100644 --- a/htdocs/user/home.php +++ b/htdocs/user/home.php @@ -163,7 +163,7 @@ if ($resql) { $companystatic->canvas = $obj->canvas; $lastcreatedbox .= ''; - $lastcreatedbox .= ''; + $lastcreatedbox .= ''; $lastcreatedbox .= $fuserstatic->getNomUrl(-1); if (!empty($conf->multicompany->enabled) && $obj->admin && !$obj->entity) { $lastcreatedbox .= img_picto($langs->trans("SuperAdministrator"), 'redstar'); @@ -171,17 +171,16 @@ if ($resql) { $lastcreatedbox .= img_picto($langs->trans("Administrator"), 'star'); } $lastcreatedbox .= ""; - $lastcreatedbox .= ''.$obj->login.''; - $lastcreatedbox .= ""; + $lastcreatedbox .= ''.dol_escape_htmltag($obj->login).''; + $texttoshow = ''; if ($obj->fk_soc) { - $lastcreatedbox .= $companystatic->getNomUrl(1); + $texttoshow .= $companystatic->getNomUrl(1); } else { - $lastcreatedbox .= $langs->trans("InternalUser"); + $texttoshow .= ''.$langs->trans("InternalUser").''; } if ($obj->ldap_sid) { - $lastcreatedbox .= ' ('.$langs->trans("DomainUser").')'; + $texttoshow .= ' ('.$langs->trans("DomainUser").')'; } - $entity = $obj->entity; $entitystring = ''; // TODO Set of entitystring should be done with a hook @@ -193,8 +192,9 @@ if ($resql) { $entitystring = $mc->label; } } - $lastcreatedbox .= ($entitystring ? ' ('.$entitystring.')' : ''); - + $texttoshow .= ($entitystring ? ' ('.$entitystring.')' : ''); + $lastcreatedbox .= ''; + $lastcreatedbox .= $texttoshow; $lastcreatedbox .= ''; $lastcreatedbox .= ''.dol_print_date($db->jdate($obj->datec), 'dayhour').''; $lastcreatedbox .= ''; From 9b9d65562fc1e0fd59ab799c0027201ea6e7fc6e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 18 Jul 2022 14:51:03 +0200 Subject: [PATCH 233/826] Fix css --- htdocs/core/class/html.formother.class.php | 5 +++-- htdocs/core/customreports.php | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/htdocs/core/class/html.formother.class.php b/htdocs/core/class/html.formother.class.php index 5bee2f31dd4..103b370dcb0 100644 --- a/htdocs/core/class/html.formother.class.php +++ b/htdocs/core/class/html.formother.class.php @@ -1513,9 +1513,10 @@ class FormOther * @param array $search_xaxis Array of preselected fields * @param array $arrayofxaxis Array of groupby to fill * @param string $showempty '1' or 'text' + * @param string $morecss More css * @return string HTML string component */ - public function selectXAxisField($object, $search_xaxis, &$arrayofxaxis, $showempty = '1') + public function selectXAxisField($object, $search_xaxis, &$arrayofxaxis, $showempty = '1', $morecss = 'minwidth250 maxwidth500') { global $form; @@ -1523,7 +1524,7 @@ class FormOther foreach ($arrayofxaxis as $key => $val) { $arrayofxaxislabel[$key] = $val['label']; } - $result = $form->selectarray('search_xaxis', $arrayofxaxislabel, $search_xaxis, $showempty, 0, 0, '', 0, 0, 0, '', 'minwidth250 maxwidth500', 1); + $result = $form->selectarray('search_xaxis', $arrayofxaxislabel, $search_xaxis, $showempty, 0, 0, '', 0, 0, 0, '', $morecss, 1); return $result; } diff --git a/htdocs/core/customreports.php b/htdocs/core/customreports.php index 2ad0e047346..c1222a6b762 100644 --- a/htdocs/core/customreports.php +++ b/htdocs/core/customreports.php @@ -450,7 +450,7 @@ $simplearrayofmesures = array(); foreach ($arrayofmesures as $key => $val) { $simplearrayofmesures[$key] = $arrayofmesures[$key]['label']; } -print $form->multiselectarray('search_measures', $simplearrayofmesures, $search_measures, 0, 0, 'minwidth400', 1, 0, '', '', $langs->trans("Measures")); // Fill the array $arrayofmeasures with possible fields +print $form->multiselectarray('search_measures', $simplearrayofmesures, $search_measures, 0, 0, 'minwidth300', 1, 0, '', '', $langs->trans("Measures")); // Fill the array $arrayofmeasures with possible fields print '
'; // XAxis @@ -458,7 +458,7 @@ $count = 0; print '
'; print '
'; //var_dump($arrayofxaxis); -print $formother->selectXAxisField($object, $search_xaxis, $arrayofxaxis, $langs->trans("XAxis")); // Fill the array $arrayofxaxis with possible fields +print $formother->selectXAxisField($object, $search_xaxis, $arrayofxaxis, $langs->trans("XAxis"), 'minwidth300 maxwidth400'); // Fill the array $arrayofxaxis with possible fields print '
'; // Group by From 53812c9f13ff1d152abc0e9306bd6610fc654a3e Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com> Date: Mon, 18 Jul 2022 17:29:49 +0200 Subject: [PATCH 234/826] NEW: hook to modify supplier product html select --- htdocs/core/class/html.form.class.php | 65 +++++++++++++++------------ 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 9c14bfeb866..b03aec90908 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -3078,7 +3078,7 @@ class Form public function select_produits_fournisseurs_list($socid, $selected = '', $htmlname = 'productid', $filtertype = '', $filtre = '', $filterkey = '', $statut = -1, $outputmode = 0, $limit = 100, $alsoproductwithnosupplierprice = 0, $morecss = '', $showstockinlist = 0, $placeholder = '') { // phpcs:enable - global $langs, $conf, $db, $user; + global $langs, $conf, $db, $user, $hookmanager; $out = ''; $outarray = array(); @@ -3179,6 +3179,13 @@ class Form $out .= ''; } + if (! is_object($hookmanager)) { + require_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php'; + $hookmanager = new HookManager($this->db); + } + + $hookmanager->initHooks(array('form')); + $i = 0; while ($i < $num) { $objp = $this->db->fetch_object($result); @@ -3189,7 +3196,6 @@ class Form } $outref = $objp->ref; - $outval = ''; $outbarcode = $objp->barcode; $outqty = 1; $outdiscount = 0; @@ -3370,45 +3376,48 @@ class Form } } - $opt = '\n"; + $parameters = array( + 'objp' => &$objp, + 'optstart' => &$optstart, + 'optlabel' => &$optlabel, + 'outvallabel' => &$outvallabel, + 'outarrayentry' => &$outarrayentry + ); + $reshook = $hookmanager->executeHooks('selectProduitsFournisseurListOption', $parameters, $this); // Add new entry // "key" value of json key array is used by jQuery automatically as selected value. Example: 'type' = product or service, 'price_ht' = unit price without tax // "label" value of json key array is used by jQuery automatically as text for combo box - $out .= $opt; - array_push( - $outarray, - array('key'=>$outkey, - 'value'=>$outref, - 'label'=>$outval, - 'qty'=>$outqty, - 'price_ht'=>price2num($objp->unitprice, 'MU'), - 'discount'=>$outdiscount, - 'type'=>$outtype, - 'duration_value'=>$outdurationvalue, - 'duration_unit'=>$outdurationunit, - 'disabled'=>(empty($objp->idprodfournprice) ? true : false), - 'description'=>$objp->description - ) - ); + $out .= $optstart . ' data-html="'.dol_escape_htmltag($optlabel).'">' . $optlabel . "\n"; + array_push($outarray, $outarrayentry); + // Exemple of var_dump $outarray // array(1) {[0]=>array(6) {[key"]=>string(1) "2" ["value"]=>string(3) "ppp" // ["label"]=>string(76) "ppp (fff2) - ppp - 20,00 Euros/1unité (20,00 Euros/unité)" From f6176b6b6184ea38697946351c27ee86cd67f8cf Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 19 Jul 2022 02:08:49 +0200 Subject: [PATCH 235/826] Doc --- htdocs/install/mysql/tables/llx_product_stock.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/install/mysql/tables/llx_product_stock.sql b/htdocs/install/mysql/tables/llx_product_stock.sql index c5a2f4ad005..8132a71cdd3 100644 --- a/htdocs/install/mysql/tables/llx_product_stock.sql +++ b/htdocs/install/mysql/tables/llx_product_stock.sql @@ -16,6 +16,7 @@ -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . -- +-- See also its child table llx_product_batch that contains details per lot -- ============================================================================ create table llx_product_stock From db2d2a7b3b6454cbe896ef4833d968b94a2f1ea8 Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Tue, 19 Jul 2022 11:39:23 +0200 Subject: [PATCH 236/826] Fix : PHP 8.1 warnings --- htdocs/ftp/index.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/ftp/index.php b/htdocs/ftp/index.php index 419727b1cca..8b4b7bf31c4 100644 --- a/htdocs/ftp/index.php +++ b/htdocs/ftp/index.php @@ -510,6 +510,7 @@ if (!function_exists('ftp_connect')) { $nboflines = count($contents); $rawlisthasfailed = false; $i = 0; + $nbofentries = 0; while ($i < $nboflines && $i < 1000) { $vals = preg_split('@ +@', utf8_encode($buff[$i]), 9); //$vals=preg_split('@ +@','drwxr-xr-x 2 root root 4096 Aug 30 2008 backup_apollon1',9); @@ -527,6 +528,7 @@ if (!function_exists('ftp_connect')) { // Is it a directory ? $is_directory = 0; + $is_link = 0; if ($file == '..') { $is_directory = 1; } elseif (!$rawlisthasfailed) { @@ -695,6 +697,7 @@ function dol_ftp_connect($ftp_server, $ftp_port, $ftp_user, $ftp_password, $sect $ok = 1; $conn_id = null; + $mesg=""; if (!is_numeric($ftp_port)) { $mesg = $langs->transnoentitiesnoconv("FailedToConnectToFTPServer", $ftp_server, $ftp_port); From f216816b2fc2d246cbc5e6f059f1fa869c151b64 Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Tue, 19 Jul 2022 12:08:23 +0200 Subject: [PATCH 237/826] Fix ; scrutinizer bug --- htdocs/webhook/target_card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/webhook/target_card.php b/htdocs/webhook/target_card.php index dd0d5e171e8..1e1f6522ea1 100644 --- a/htdocs/webhook/target_card.php +++ b/htdocs/webhook/target_card.php @@ -532,7 +532,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea } // Clone - print dolGetButtonAction($langs->trans('ToClone'), '', 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.(!empty($object->socid)?'&socid='.$object->socid:'').'&action=clone&token='.newToken(), '', $permissiontoadd); + print dolGetButtonAction($langs->trans('ToClone'), '', 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.'&action=clone&token='.newToken(), '', $permissiontoadd); /* if ($permissiontoadd) { From a691c8ebe9721c93c9cf6fd79bbde28111c734f3 Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com> Date: Tue, 19 Jul 2022 12:31:13 +0200 Subject: [PATCH 238/826] FIX: remove useless hookmanager init --- htdocs/core/class/html.form.class.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index b03aec90908..4acd0e1509f 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -3179,13 +3179,6 @@ class Form $out .= ''; } - if (! is_object($hookmanager)) { - require_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php'; - $hookmanager = new HookManager($this->db); - } - - $hookmanager->initHooks(array('form')); - $i = 0; while ($i < $num) { $objp = $this->db->fetch_object($result); From 7316210df6d21a922019f4588648ca93c17d3302 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 19 Jul 2022 19:16:53 +0200 Subject: [PATCH 239/826] Doc --- ChangeLog | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ChangeLog b/ChangeLog index ae767c91649..76709bd8f85 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,9 +4,20 @@ English Dolibarr ChangeLog ***** ChangeLog for 17.0.0 compared to 16.0.0 ***** +For users: +--------------- + +... + + For developers or integrators: ------------------------------ +... + + +WARNING: + Following changes may create regressions for some external modules, but were necessary to make Dolibarr better: * The signature of method getNomUrl() of class ProductFournisseur has been modified to match the signature of method Product @@ -192,6 +203,8 @@ NEW: Add hooks select product list and select thirdparty list function NEW: Add hook to getSellPrice function +WARNING: + Following changes may create regressions for some external modules, but were necessary to make Dolibarr better: * There is a new specific permission to be allowed to enter timesheets. If you use timesheet, don't forget to give the new permission (disable and enable the module project if it is not visible). @@ -489,6 +502,8 @@ NEW: we need to be able to put more filters on deleteByParentField() function NEW: make it easier to set the `keyword`, `keywords` and `description` attributes of an ecm file object NEW: Experimental feature to manage user sessions in database + +WARNING: Following changes may create regressions for some external modules, but were necessary to make Dolibarr better: * ALL EXTERNAL MODULES THAT WERE NOT CORRECTLY DEVELOPPED WILL NOT WORK ON V15 (All modules that forgot to manage the security token field From 87b80912df6308562e68c50a2c37fe3bc8ba2a42 Mon Sep 17 00:00:00 2001 From: Faustin Date: Tue, 19 Jul 2022 20:35:03 +0200 Subject: [PATCH 240/826] merge --- htdocs/comm/action/card.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/htdocs/comm/action/card.php b/htdocs/comm/action/card.php index eef679b7141..8d1f75c4990 100644 --- a/htdocs/comm/action/card.php +++ b/htdocs/comm/action/card.php @@ -1195,15 +1195,16 @@ if ($action == 'create') { $object->recurrule .= GETPOSTISSET('BYMONTHDAY') ? "_BYMONTHDAY".GETPOST('BYMONTHDAY', 'alpha') : ""; $object->recurrule .= GETPOSTISSET('BYDAY') ? "_BYDAY".GETPOST('BYDAY', 'alpha') : ""; - $reg1 = array(); - if ($object->recurrule && preg_match('/FREQ=([A-Z]+)/i', $object->recurrule, $reg1)) { - $selectedrecurrulefreq = $reg1[1]; + + $reg = array(); + if ($object->recurrule && preg_match('/FREQ=([A-Z]+)/i', $object->recurrule, $reg)) { + $selectedrecurrulefreq = $reg[1]; } - if ($object->recurrule && preg_match('/FREQ=MONTHLY.*BYMONTHDAY(\d+)/i', $object->recurrule, $reg2)) { - $selectedrecurrulebymonthday = $reg2[1]; + if ($object->recurrule && preg_match('/FREQ=MONTHLY.*BYMONTHDAY(\d+)/i', $object->recurrule, $reg)) { + $selectedrecurrulebymonthday = $reg[1]; } - if ($object->recurrule && preg_match('/FREQ=WEEKLY.*BYDAY(\d+)/i', $object->recurrule, $reg3)) { - $selectedrecurrulebyday = $reg3[1]; + if ($object->recurrule && preg_match('/FREQ=WEEKLY.*BYDAY(\d+)/i', $object->recurrule, $reg)) { + $selectedrecurrulebyday = $reg[1]; } print $form->selectarray('recurrulefreq', $arrayrecurrulefreq, $selectedrecurrulefreq, 0, 0, 0, '', 0, 0, 0, '', 'marginrightonly'); From 2c898b45e3d0b8e2171b472c22d4640503f73304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?This=20Charl=C3=A8ne?= <1179011+defrance@users.noreply.github.com> Date: Wed, 20 Jul 2022 11:10:54 +0200 Subject: [PATCH 241/826] PHP - cannot use a scalar as an array warning generate an error : cannot use a scalar as an array warning (even on php V7) --- htdocs/variants/combinations.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/variants/combinations.php b/htdocs/variants/combinations.php index b6ffd948bd6..eb19b9fc29a 100644 --- a/htdocs/variants/combinations.php +++ b/htdocs/variants/combinations.php @@ -69,7 +69,7 @@ if ($id > 0 || $ref) { $object->fetch($id, $ref); } -$selectedvariant = !empty($_SESSION['addvariant_'.$object->id]) ? $_SESSION['addvariant_'.$object->id] : 0; +$selectedvariant = !empty($_SESSION['addvariant_'.$object->id]) ? $_SESSION['addvariant_'.$object->id] : Array(); // Security check if (empty($conf->variants->enabled)) { From 8cb1e138de0c4627c45e49ae0aaf1e0396590b5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?This=20Charl=C3=A8ne?= <1179011+defrance@users.noreply.github.com> Date: Wed, 20 Jul 2022 11:15:44 +0200 Subject: [PATCH 242/826] forgotted fields --- htdocs/variants/class/ProductCombination.class.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/variants/class/ProductCombination.class.php b/htdocs/variants/class/ProductCombination.class.php index 0e8f69958dc..a525bb41319 100644 --- a/htdocs/variants/class/ProductCombination.class.php +++ b/htdocs/variants/class/ProductCombination.class.php @@ -281,7 +281,9 @@ class ProductCombination { global $conf; - $sql = "SELECT rowid, fk_product_parent, fk_product_child, variation_price, variation_price_percentage, variation_weight FROM ".MAIN_DB_PREFIX."product_attribute_combination WHERE fk_product_parent = ".((int) $fk_product_parent)." AND entity IN (".getEntity('product').")"; + $sql = "SELECT rowid, fk_product_parent, fk_product_child, variation_price, variation_price_percentage, variation_ref_ext, variation_weight"; + $sql.= " FROM ".MAIN_DB_PREFIX."product_attribute_combination"; + $sql.= " WHERE fk_product_parent = ".((int) $fk_product_parent)." AND entity IN (".getEntity('product').")"; $query = $this->db->query($sql); From 3e8cb1de571c6df02ef98d0a81b6cdb6ed4154e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?This=20Charl=C3=A8ne?= <1179011+defrance@users.noreply.github.com> Date: Wed, 20 Jul 2022 11:31:20 +0200 Subject: [PATCH 243/826] php V8 warning --- htdocs/variants/class/ProductCombination.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/variants/class/ProductCombination.class.php b/htdocs/variants/class/ProductCombination.class.php index a525bb41319..215536ac43a 100644 --- a/htdocs/variants/class/ProductCombination.class.php +++ b/htdocs/variants/class/ProductCombination.class.php @@ -491,10 +491,10 @@ class ProductCombination $child->price_autogen = $parent->price_autogen; $child->weight = $parent->weight; // Only when Parent Status are updated - if ($parent->oldcopy && ($parent->status != $parent->oldcopy->status)) { + if (!empty($parent->oldcopy) && ($parent->status != $parent->oldcopy->status)) { $child->status = $parent->status; } - if ($parent->oldcopy && ($parent->status_buy != $parent->oldcopy->status_buy)) { + if (!empty($parent->oldcopy) && ($parent->status_buy != $parent->oldcopy->status_buy)) { $child->status_buy = $parent->status_buy; } From 54c2cc245d663f4e887471e19833bf3da13e18a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?This=20Charl=C3=A8ne?= <1179011+defrance@users.noreply.github.com> Date: Wed, 20 Jul 2022 11:34:01 +0200 Subject: [PATCH 244/826] PHP V8 warning --- htdocs/variants/combinations.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/variants/combinations.php b/htdocs/variants/combinations.php index eb19b9fc29a..fd4f116f51b 100644 --- a/htdocs/variants/combinations.php +++ b/htdocs/variants/combinations.php @@ -154,7 +154,7 @@ if (($action == 'add' || $action == 'create') && empty($massaction) && !GETPOST( $price_impact = price2num($price_impact); // for conf PRODUIT_MULTIPRICES - if ($conf->global->PRODUIT_MULTIPRICES) { + if (!empty($conf->global->PRODUIT_MULTIPRICES)) { $level_price_impact = array_map('price2num', $level_price_impact); } else { $level_price_impact = array(1 => $price_impact); @@ -279,7 +279,7 @@ if (($action == 'add' || $action == 'create') && empty($massaction) && !GETPOST( $prodcomb->variation_weight = price2num($weight_impact); // for conf PRODUIT_MULTIPRICES - if ($conf->global->PRODUIT_MULTIPRICES) { + if (!empty($conf->global->PRODUIT_MULTIPRICES)) { $level_price_impact = array_map('price2num', $level_price_impact); $prodcomb->variation_price = $level_price_impact[1]; @@ -292,7 +292,7 @@ if (($action == 'add' || $action == 'create') && empty($massaction) && !GETPOST( $prodcomb->variation_price_percentage = $price_impact_percent; } - if ($conf->global->PRODUIT_MULTIPRICES) { + if (!empty($conf->global->PRODUIT_MULTIPRICES)) { $prodcomb->combination_price_levels = array(); for ($i = 1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i++) { $productCombinationLevel = new ProductCombinationLevel($db); From 1f9afaadb1df40589d622570ef7199b9a64a8b1f Mon Sep 17 00:00:00 2001 From: Faustin Date: Wed, 20 Jul 2022 13:08:28 +0200 Subject: [PATCH 245/826] Removing daily event for the moment --- htdocs/comm/action/card.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/comm/action/card.php b/htdocs/comm/action/card.php index 8d1f75c4990..1ab81b01bd7 100644 --- a/htdocs/comm/action/card.php +++ b/htdocs/comm/action/card.php @@ -1065,8 +1065,8 @@ $formproject = new FormProjets($db); $arrayrecurrulefreq = array( 'no'=>$langs->trans("OnceOnly"), 'MONTHLY'=>$langs->trans("EveryMonth"), - 'WEEKLY'=>$langs->trans("EveryWeek"), - 'DAILY'=>$langs->trans("EveryDay") + 'WEEKLY'=>$langs->trans("EveryWeek") + // 'DAILY'=>$langs->trans("EveryDay") ); From eb38875119cdd19d37068e292175efaff6824c90 Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Wed, 20 Jul 2022 16:35:51 +0200 Subject: [PATCH 246/826] Fix : PHP 8.1 warnings --- htdocs/adherents/card.php | 2 +- htdocs/comm/card.php | 6 ++++-- htdocs/contact/card.php | 1 + htdocs/contact/consumption.php | 2 +- htdocs/contact/list.php | 3 +++ htdocs/core/lib/functions.lib.php | 4 ++-- .../core/modules/member/doc/pdf_standard.class.php | 14 +++++++------- .../core/tpl/extrafields_list_print_fields.tpl.php | 3 +++ htdocs/product/stock/card.php | 4 +++- htdocs/product/stock/info.php | 4 ++-- htdocs/product/stock/movement_list.php | 1 + htdocs/product/stock/productlot_list.php | 1 + htdocs/product/stock/tpl/stocktransfer.tpl.php | 4 ++-- 13 files changed, 31 insertions(+), 18 deletions(-) diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php index c60308138d2..03d3c1f3d06 100644 --- a/htdocs/adherents/card.php +++ b/htdocs/adherents/card.php @@ -1511,7 +1511,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { $outputlangs->loadLangs(array("main", "members", "companies", "install", "other")); // Get email content from template $arraydefaultmessage = null; - $labeltouse = $conf->global->ADHERENT_EMAIL_TEMPLATE_MEMBER_VALIDATION; + $labeltouse = getDolGlobalString("ADHERENT_EMAIL_TEMPLATE_MEMBER_VALIDATION"); if (!empty($labeltouse)) { $arraydefaultmessage = $formmail->getEMailTemplate($db, 'member', $user, $outputlangs, 0, 1, $labeltouse); diff --git a/htdocs/comm/card.php b/htdocs/comm/card.php index 4b51a519223..57f2662bcfc 100644 --- a/htdocs/comm/card.php +++ b/htdocs/comm/card.php @@ -914,8 +914,10 @@ if ($object->id > 0) { * Latest orders */ if (!empty($conf->commande->enabled) && $user->rights->commande->lire) { + $param =""; + $sql = "SELECT s.nom, s.rowid"; - $sql .= ", c.rowid as cid, c.total_ht"; + $sql .= ", c.rowid as cid, c.entity, c.total_ht"; $sql .= ", c.total_tva"; $sql .= ", c.total_ttc"; $sql .= ", c.ref, c.ref_client, c.fk_statut, c.facture"; @@ -1024,7 +1026,7 @@ if ($object->id > 0) { */ if (!empty($conf->expedition->enabled) && $user->rights->expedition->lire) { $sql = 'SELECT e.rowid as id'; - $sql .= ', e.ref'; + $sql .= ', e.ref, e.entity'; $sql .= ', e.date_creation'; $sql .= ', e.fk_statut as statut'; $sql .= ', s.nom'; diff --git a/htdocs/contact/card.php b/htdocs/contact/card.php index 06149063806..52cde1877b8 100644 --- a/htdocs/contact/card.php +++ b/htdocs/contact/card.php @@ -1199,6 +1199,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { // Categories if (!empty($conf->categorie->enabled) && !empty($user->rights->categorie->lire)) { + $arrayselected = array(); print ''.$form->editfieldkey('Categories', 'contcats', '', $object, 0).''; print ''; $cate_arbo = $form->select_all_categories(Categorie::TYPE_CONTACT, null, null, null, null, 1); diff --git a/htdocs/contact/consumption.php b/htdocs/contact/consumption.php index 41a6a74dd4b..0ba88228666 100644 --- a/htdocs/contact/consumption.php +++ b/htdocs/contact/consumption.php @@ -167,7 +167,7 @@ if ($object->thirdparty->client) { } } -if ($conf->ficheinter->enabled && $user->rights->ficheinter->lire) { +if (!empty($conf->ficheinter->enabled) && $user->rights->ficheinter->lire) { $elementTypeArray['fichinter'] = $langs->transnoentitiesnoconv('Interventions'); } diff --git a/htdocs/contact/list.php b/htdocs/contact/list.php index 801c859924e..1e497b0ab2e 100644 --- a/htdocs/contact/list.php +++ b/htdocs/contact/list.php @@ -342,6 +342,9 @@ $formother = new FormOther($db); $formcompany = new FormCompany($db); $contactstatic = new Contact($db); +$morejs=array(); +$morecss = array(); + if (!empty($conf->global->THIRDPARTY_ENABLE_PROSPECTION_ON_ALTERNATIVE_ADRESSES)) { $contactstatic->loadCacheOfProspStatus(); } diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 51d26491826..dd79b67c380 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -7461,8 +7461,8 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, $substitutionarray['__MEMBER_PHONEMOBILE__'] = (isset($object->phone_mobile) ? dol_print_phone($object->phone_mobile) : ''); $substitutionarray['__MEMBER_TYPE__'] = (isset($object->type) ? $object->type : ''); $substitutionarray['__MEMBER_FIRST_SUBSCRIPTION_DATE__'] = dol_print_date($object->first_subscription_date, 'dayrfc'); - $substitutionarray['__MEMBER_FIRST_SUBSCRIPTION_DATE_START__'] = dol_print_date($object->first_subscription_date_start, 'dayrfc'); - $substitutionarray['__MEMBER_FIRST_SUBSCRIPTION_DATE_END__'] = dol_print_date($object->first_subscription_date_end, 'dayrfc'); + $substitutionarray['__MEMBER_FIRST_SUBSCRIPTION_DATE_START__'] = (isset($object->first_subscription_date_start) ? dol_print_date($object->first_subscription_date_start, 'dayrfc') : ''); + $substitutionarray['__MEMBER_FIRST_SUBSCRIPTION_DATE_END__'] = (isset($object->first_subscription_date_end) ? dol_print_date($object->first_subscription_date_end, 'dayrfc') : ''); $substitutionarray['__MEMBER_LAST_SUBSCRIPTION_DATE__'] = dol_print_date($object->last_subscription_date, 'dayrfc'); $substitutionarray['__MEMBER_LAST_SUBSCRIPTION_DATE_START__'] = dol_print_date($object->last_subscription_date_start, 'dayrfc'); $substitutionarray['__MEMBER_LAST_SUBSCRIPTION_DATE_END__'] = dol_print_date($object->last_subscription_date_end, 'dayrfc'); diff --git a/htdocs/core/modules/member/doc/pdf_standard.class.php b/htdocs/core/modules/member/doc/pdf_standard.class.php index 0fc13cbe134..842495c242d 100644 --- a/htdocs/core/modules/member/doc/pdf_standard.class.php +++ b/htdocs/core/modules/member/doc/pdf_standard.class.php @@ -173,7 +173,7 @@ class pdf_standard extends CommonStickerGenerator $widthtouse = $maxwidthtouse; $heighttouse = 0; // old value for image $tmp = dol_getImageSize($photo, false); - if ($tmp['height']) { + if (isset($tmp['height'])) { $imgratio = $tmp['width'] / $tmp['height']; if ($imgratio >= $defaultratio) { $widthtouse = $maxwidthtouse; @@ -314,10 +314,10 @@ class pdf_standard extends CommonStickerGenerator complete_substitutions_array($substitutionarray, $langs); // For business cards - $textleft = make_substitutions($conf->global->ADHERENT_CARD_TEXT, $substitutionarray); - $textheader = make_substitutions($conf->global->ADHERENT_CARD_HEADER_TEXT, $substitutionarray); - $textfooter = make_substitutions($conf->global->ADHERENT_CARD_FOOTER_TEXT, $substitutionarray); - $textright = make_substitutions($conf->global->ADHERENT_CARD_TEXT_RIGHT, $substitutionarray); + $textleft = make_substitutions(getDolGlobalString("ADHERENT_CARD_TEXT"), $substitutionarray); + $textheader = make_substitutions(getDolGlobalString("ADHERENT_CARD_HEADER_TEXT"), $substitutionarray); + $textfooter = make_substitutions(getDolGlobalString("ADHERENT_CARD_FOOTER_TEXT"), $substitutionarray); + $textright = make_substitutions(getDolGlobalString("ADHERENT_CARD_TEXT_RIGHT"), $substitutionarray); $nb = $_Avery_Labels[$this->code]['NX'] * $_Avery_Labels[$this->code]['NY']; if ($nb <= 0) { @@ -330,8 +330,8 @@ class pdf_standard extends CommonStickerGenerator 'textheader'=>$textheader, 'textfooter'=>$textfooter, 'textright'=>$textright, - 'id'=>$object->rowid, - 'photo'=>$object->photo + 'id'=>(isset($object->rowid) ? $object->rowid : ""), + 'photo'=>(isset($object->photo) ? $object->photo : "") ); } diff --git a/htdocs/core/tpl/extrafields_list_print_fields.tpl.php b/htdocs/core/tpl/extrafields_list_print_fields.tpl.php index aeafac07962..2a12a07fd23 100644 --- a/htdocs/core/tpl/extrafields_list_print_fields.tpl.php +++ b/htdocs/core/tpl/extrafields_list_print_fields.tpl.php @@ -68,6 +68,9 @@ if (!empty($extrafieldsobjectkey) && !empty($extrafields->attributes[$extrafield $totalarray['totalizable'][$key]['pos'] = $totalarray['nbfield']; } if (is_numeric($obj->$tmpkey)) { + if (!isset($totalarray['totalizable'][$key]['total'])) { + $totalarray['totalizable'][$key]['total'] = 0; + } $totalarray['totalizable'][$key]['total'] += $obj->$tmpkey; } } diff --git a/htdocs/product/stock/card.php b/htdocs/product/stock/card.php index 311b04a4c89..b4730778d32 100644 --- a/htdocs/product/stock/card.php +++ b/htdocs/product/stock/card.php @@ -720,7 +720,9 @@ if ($action == 'create') { $productstatic->type = $objp->type; $productstatic->entity = $objp->entity; $productstatic->status_batch = $objp->tobatch; - $productstatic->fk_unit = $objp->fk_unit; + if (!empty($conf->global->PRODUCT_USE_UNITS)) { + $productstatic->fk_unit = $objp->fk_unit; + } $productstatic->status = $objp->tosell; $productstatic->status_buy = $objp->tobuy; $productstatic->barcode = $objp->barcode; diff --git a/htdocs/product/stock/info.php b/htdocs/product/stock/info.php index de9f72fbcd6..29e337c3728 100644 --- a/htdocs/product/stock/info.php +++ b/htdocs/product/stock/info.php @@ -35,7 +35,7 @@ $ref = GETPOST('ref', 'alpha'); // Security check //$result=restrictedArea($user,'stock', $id, 'entrepot&stock'); $result = restrictedArea($user, 'stock'); - +$usercancreate = $user->rights->stock->creer; /* * View @@ -75,7 +75,7 @@ if (!empty($conf->project->enabled)) { $morehtmlref .= ''; $morehtmlref .= ''; } else { - $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, (!empty($object->socid) ? $object->socid : 0), $object->fk_project, 'none', 0, 0, 0, 1); } } else { if (!empty($object->fk_project)) { diff --git a/htdocs/product/stock/movement_list.php b/htdocs/product/stock/movement_list.php index 561ee5d5d4d..6a5499734bd 100644 --- a/htdocs/product/stock/movement_list.php +++ b/htdocs/product/stock/movement_list.php @@ -59,6 +59,7 @@ $confirm = GETPOST('confirm', 'alpha'); // Result of a confirmation $cancel = GETPOST('cancel', 'alpha'); $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'movementlist'; $toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected into a list +$backtopage = GETPOST("backtopage", "alpha"); $idproduct = GETPOST('idproduct', 'int'); $sall = trim((GETPOST('search_all', 'alphanohtml') != '') ?GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml')); diff --git a/htdocs/product/stock/productlot_list.php b/htdocs/product/stock/productlot_list.php index 2743c4a5ea7..ba6b81abd79 100644 --- a/htdocs/product/stock/productlot_list.php +++ b/htdocs/product/stock/productlot_list.php @@ -42,6 +42,7 @@ $backtopage = GETPOST('backtopage', 'alpha'); $toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected into a list $contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'productlotlist'; // To manage different context of search $optioncss = GETPOST('optioncss', 'alpha'); +$mode = GETPOST('mode', 'alpha'); $search_entity = GETPOST('search_entity', 'int'); $search_product = GETPOST('search_product', 'alpha'); diff --git a/htdocs/product/stock/tpl/stocktransfer.tpl.php b/htdocs/product/stock/tpl/stocktransfer.tpl.php index cfb46231a72..53803b0929d 100644 --- a/htdocs/product/stock/tpl/stocktransfer.tpl.php +++ b/htdocs/product/stock/tpl/stocktransfer.tpl.php @@ -112,12 +112,12 @@ if (!empty($conf->productbatch->enabled) && print ''; if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) { print ''.$langs->trans("SellByDate").''; - print $form->selectDate(($d_sellby ? $d_sellby : $pdluo->sellby), 'sellby', '', '', 1, "", 1, 0, ($pdluoid > 0 ? 1 : 0)); // If form was opened for a specific pdluoid, field is disabled + print $form->selectDate((!empty($d_sellby) ? $d_sellby : $pdluo->sellby), 'sellby', '', '', 1, "", 1, 0, ($pdluoid > 0 ? 1 : 0)); // If form was opened for a specific pdluoid, field is disabled print ''; } if (empty($conf->global->PRODUCT_DISABLE_EATBY)) { print ''.$langs->trans("EatByDate").''; - print $form->selectDate(($d_eatby ? $d_eatby : $pdluo->eatby), 'eatby', '', '', 1, "", 1, 0, ($pdluoid > 0 ? 1 : 0)); // If form was opened for a specific pdluoid, field is disabled + print $form->selectDate((!empty($d_eatby) ? $d_eatby : $pdluo->eatby), 'eatby', '', '', 1, "", 1, 0, ($pdluoid > 0 ? 1 : 0)); // If form was opened for a specific pdluoid, field is disabled print ''; } print ''; From cd6bd2ae4e1c581adf26cc2c2e62ea3fc376347c Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Wed, 20 Jul 2022 18:39:11 +0200 Subject: [PATCH 247/826] FIX - php8 migration --- htdocs/core/class/menubase.class.php | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/htdocs/core/class/menubase.class.php b/htdocs/core/class/menubase.class.php index 6b45cd08f98..caeece975f2 100644 --- a/htdocs/core/class/menubase.class.php +++ b/htdocs/core/class/menubase.class.php @@ -181,21 +181,21 @@ class Menubase if (!isset($this->enabled)) { $this->enabled = '1'; } - $this->menu_handler = trim($this->menu_handler); - $this->module = trim($this->module); - $this->type = trim($this->type); - $this->mainmenu = trim($this->mainmenu); - $this->leftmenu = trim($this->leftmenu); + $this->menu_handler = trim((string) $this->menu_handler); + $this->module = trim((string) $this->module); + $this->type = trim((string) $this->type); + $this->mainmenu = trim((string) $this->mainmenu); + $this->leftmenu = trim((string) $this->leftmenu); $this->fk_menu = (int) $this->fk_menu; // If -1, fk_mainmenu and fk_leftmenu must be defined - $this->fk_mainmenu = trim($this->fk_mainmenu); - $this->fk_leftmenu = trim($this->fk_leftmenu); + $this->fk_mainmenu = trim((string) $this->fk_mainmenu); + $this->fk_leftmenu = trim((string) $this->fk_leftmenu); $this->position = (int) $this->position; - $this->url = trim($this->url); - $this->target = trim($this->target); - $this->title = trim($this->title); - $this->langs = trim($this->langs); - $this->perms = trim($this->perms); - $this->enabled = trim($this->enabled); + $this->url = trim((string) $this->url); + $this->target = trim((string) $this->target); + $this->title = trim((string) $this->title); + $this->langs = trim((string) $this->langs); + $this->perms = trim((string) $this->perms); + $this->enabled = trim((string) $this->enabled); $this->user = (int) $this->user; if (empty($this->position)) { $this->position = 0; From 1bc8398adfdae9182d834a4f6680a0557b701a2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20NASSIET?= Date: Wed, 20 Jul 2022 22:12:11 +0200 Subject: [PATCH 248/826] correction warning php Undefined property: stdClass:: in /space/www/deveop/htdocs/societe/index.php on line 181 lorsque le module fournisseur n'est pas actif en se rendant sur le module Tiers --- htdocs/societe/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/societe/index.php b/htdocs/societe/index.php index f4637186b4d..a13d8a3de99 100644 --- a/htdocs/societe/index.php +++ b/htdocs/societe/index.php @@ -178,7 +178,7 @@ if (!empty($conf->use_javascript_ajax) && ((round($third['prospect']) ? 1 : 0) + $statstring .= ""; } $statstring2 = ''; - if (((isModEnabled('societe') && $user->rights->fournisseur->facture->lire && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (isModEnabled('supplier_order') && $user->rights->supplier_order->lire) || (isModEnabled('supplier_invoice') && $user->rights->supplier_invoice->lire)) && empty($conf->global->SOCIETE_DISABLE_SUPPLIERS_STATS)) { + if (((isModEnabled('fournisseur') && $user->rights->fournisseur->facture->lire && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (isModEnabled('supplier_order') && $user->rights->supplier_order->lire) || (isModEnabled('supplier_invoice') && $user->rights->supplier_invoice->lire)) && empty($conf->global->SOCIETE_DISABLE_SUPPLIERS_STATS)) { $statstring2 = ""; $statstring2 .= ''.$langs->trans("Suppliers").''.round($third['supplier']).''; $statstring2 .= ""; From 3079ab27371872ffdc34f2561ae92c9fbb76df76 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 21 Jul 2022 10:59:15 +0200 Subject: [PATCH 249/826] FIX phpv8 --- htdocs/admin/notification.php | 16 ++++++++++------ htdocs/compta/paiement/class/paiement.class.php | 2 ++ htdocs/projet/tasks.php | 1 + htdocs/projet/tasks/comment.php | 2 +- htdocs/projet/tasks/contact.php | 2 +- htdocs/projet/tasks/document.php | 2 +- htdocs/projet/tasks/note.php | 2 +- htdocs/projet/tasks/task.php | 6 +++--- 8 files changed, 20 insertions(+), 13 deletions(-) diff --git a/htdocs/admin/notification.php b/htdocs/admin/notification.php index 38245b5e204..760df948d34 100644 --- a/htdocs/admin/notification.php +++ b/htdocs/admin/notification.php @@ -188,6 +188,7 @@ print '
'; print ''; print ''; +print '
'; print ''; print ''; print ''; @@ -198,7 +199,7 @@ print ''; print ''; print ''; @@ -224,7 +225,7 @@ if ($conf->use_javascript_ajax) { print ajax_constantonoff('NOTIFICATION_EMAIL_DISABLE_CONFIRM_MESSAGE_USER'); } else { $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); - print $form->selectarray("NOTIFICATION_EMAIL_DISABLE_CONFIRM_MESSAGE_USER", $arrval, $conf->global->NOTIFICATION_EMAIL_DISABLE_CONFIRM_MESSAGE_USER); + print $form->selectarray("NOTIFICATION_EMAIL_DISABLE_CONFIRM_MESSAGE_USER", $arrval, getDolGlobalString('NOTIFICATION_EMAIL_DISABLE_CONFIRM_MESSAGE_USER')); } print ''; print ''; @@ -236,11 +237,12 @@ if ($conf->use_javascript_ajax) { print ajax_constantonoff('NOTIFICATION_EMAIL_DISABLE_CONFIRM_MESSAGE_FIX'); } else { $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); - print $form->selectarray("NOTIFICATION_EMAIL_DISABLE_CONFIRM_MESSAGE_FIX", $arrval, $conf->global->NOTIFICATION_EMAIL_DISABLE_CONFIRM_MESSAGE_FIX); + print $form->selectarray("NOTIFICATION_EMAIL_DISABLE_CONFIRM_MESSAGE_FIX", $arrval, getDolGlobalString('NOTIFICATION_EMAIL_DISABLE_CONFIRM_MESSAGE_FIX')); } print ''; print ''; print '
'.$langs->trans("Parameter").'
'; print $langs->trans("NotificationEMailFrom").''; print img_picto('', 'email', 'class="pictofixedwidth"'); -print ''; +print ''; if (!empty($conf->global->NOTIFICATION_EMAIL_FROM) && !isValidEmail($conf->global->NOTIFICATION_EMAIL_FROM)) { print ' '.img_warning($langs->trans("ErrorBadEMail")); } @@ -212,7 +213,7 @@ if ($conf->use_javascript_ajax) { print ajax_constantonoff('NOTIFICATION_EMAIL_DISABLE_CONFIRM_MESSAGE_CONTACT'); } else { $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); - print $form->selectarray("NOTIFICATION_EMAIL_DISABLE_CONFIRM_MESSAGE_CONTACT", $arrval, $conf->global->NOTIFICATION_EMAIL_DISABLE_CONFIRM_MESSAGE_CONTACT); + print $form->selectarray("NOTIFICATION_EMAIL_DISABLE_CONFIRM_MESSAGE_CONTACT", $arrval, getDolGlobalString('NOTIFICATION_EMAIL_DISABLE_CONFIRM_MESSAGE_CONTACT')); } print '
'; +print '
'; print $form->buttonsSaveCancel("Save", ''); @@ -387,6 +389,7 @@ if (!empty($conf->societe->enabled)) { } print ''; +print '
'; print ''; print ''; print ''; @@ -449,7 +452,7 @@ foreach ($listofnotifiedevents as $notifiedevent) { $param = 'NOTIFICATION_FIXEDEMAIL_'.$notifiedevent['code'].'_THRESHOLD_HIGHER_'.$reg[1]; $value = GETPOST('NOTIF_'.$notifiedevent['code'].'_old_'.$reg[1].'_key') ?GETPOST('NOTIF_'.$notifiedevent['code'].'_old_'.$reg[1].'_key', 'alpha') : $conf->global->$param; - $s = ''; // Do not use type="email" here, we must be able to enter a list of email with , separator. + $s = ''; // Do not use type="email" here, we must be able to enter a list of email with , separator. $arrayemail = explode(',', $value); $showwarning = 0; foreach ($arrayemail as $keydet => $valuedet) { @@ -468,7 +471,7 @@ foreach ($listofnotifiedevents as $notifiedevent) { } // New entry input fields if (empty($inputfieldalreadyshown) || !$codehasnotrigger) { - $s = ''; // Do not use type="email" here, we must be able to enter a list of email with , separator. + $s = ''; // Do not use type="email" here, we must be able to enter a list of email with , separator. print $form->textwithpicto($s, $langs->trans("YouCanUseCommaSeparatorForSeveralRecipients").'
'.$langs->trans("YouCanAlsoUseSupervisorKeyword"), 1, 'help', '', 0, 2); } print ''; @@ -501,6 +504,7 @@ foreach ($listofnotifiedevents as $notifiedevent) { print ''; } print '
'.$langs->trans("Module").'
'; +print '
'; print $form->buttonsSaveCancel("Save", ''); diff --git a/htdocs/compta/paiement/class/paiement.class.php b/htdocs/compta/paiement/class/paiement.class.php index f63d58db933..25543ed9d82 100644 --- a/htdocs/compta/paiement/class/paiement.class.php +++ b/htdocs/compta/paiement/class/paiement.class.php @@ -57,6 +57,7 @@ class Paiement extends CommonObject public $facid; public $datepaye; + public $date; // same than $datepaye /** * @deprecated @@ -153,6 +154,7 @@ class Paiement extends CommonObject */ public $ref_ext; + /** * Constructor * diff --git a/htdocs/projet/tasks.php b/htdocs/projet/tasks.php index f527a13644e..52902604cec 100644 --- a/htdocs/projet/tasks.php +++ b/htdocs/projet/tasks.php @@ -1062,6 +1062,7 @@ if ($action == 'create' && $user->rights->projet->creer && (empty($object->third print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); print "\n"; + $nboftaskshown = 0; if (count($tasksarray) > 0) { // Show all lines in taskarray (recursive function to go down on tree) $j = 0; $level = 0; diff --git a/htdocs/projet/tasks/comment.php b/htdocs/projet/tasks/comment.php index 82628d5136b..bed307d65bf 100644 --- a/htdocs/projet/tasks/comment.php +++ b/htdocs/projet/tasks/comment.php @@ -175,7 +175,7 @@ if ($id > 0 || !empty($ref)) { print '
'; } if (!empty($conf->eventorganization->enabled)) { - print 'usage_organize_event ? ' checked="checked"' : '')).'"> '; + print 'usage_organize_event ? ' checked="checked"' : '')).'"> '; $htmltext = $langs->trans("EventOrganizationDescriptionLong"); print $form->textwithpicto($langs->trans("ManageOrganizeEvent"), $htmltext); } diff --git a/htdocs/projet/tasks/contact.php b/htdocs/projet/tasks/contact.php index 718af1bf17b..680f8ecc70a 100644 --- a/htdocs/projet/tasks/contact.php +++ b/htdocs/projet/tasks/contact.php @@ -239,7 +239,7 @@ if ($id > 0 || !empty($ref)) { print '
'; } if (!empty($conf->eventorganization->enabled)) { - print 'usage_organize_event ? ' checked="checked"' : '')).'"> '; + print 'usage_organize_event ? ' checked="checked"' : '')).'"> '; $htmltext = $langs->trans("EventOrganizationDescriptionLong"); print $form->textwithpicto($langs->trans("ManageOrganizeEvent"), $htmltext); } diff --git a/htdocs/projet/tasks/document.php b/htdocs/projet/tasks/document.php index 25bf2f94d5d..f86d9c8f441 100644 --- a/htdocs/projet/tasks/document.php +++ b/htdocs/projet/tasks/document.php @@ -195,7 +195,7 @@ if ($object->id > 0) { print '
'; } if (!empty($conf->eventorganization->enabled)) { - print 'usage_organize_event ? ' checked="checked"' : '')).'"> '; + print 'usage_organize_event ? ' checked="checked"' : '')).'"> '; $htmltext = $langs->trans("EventOrganizationDescriptionLong"); print $form->textwithpicto($langs->trans("ManageOrganizeEvent"), $htmltext); } diff --git a/htdocs/projet/tasks/note.php b/htdocs/projet/tasks/note.php index b877c7c8a8d..6b7142dc0f2 100644 --- a/htdocs/projet/tasks/note.php +++ b/htdocs/projet/tasks/note.php @@ -185,7 +185,7 @@ if ($object->id > 0) { print '
'; } if (!empty($conf->eventorganization->enabled)) { - print 'usage_organize_event ? ' checked="checked"' : '')).'"> '; + print 'usage_organize_event ? ' checked="checked"' : '')).'"> '; $htmltext = $langs->trans("EventOrganizationDescriptionLong"); print $form->textwithpicto($langs->trans("ManageOrganizeEvent"), $htmltext); } diff --git a/htdocs/projet/tasks/task.php b/htdocs/projet/tasks/task.php index 1a0666d1067..24cadfd38f4 100644 --- a/htdocs/projet/tasks/task.php +++ b/htdocs/projet/tasks/task.php @@ -282,7 +282,7 @@ if ($id > 0 || !empty($ref)) { print ''; // Usage - if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES) || empty($conf->global->PROJECT_HIDE_TASKS) || !empty($conf->eventorganization->enabled)) { + if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES) || empty($conf->global->PROJECT_HIDE_TASKS) || isModEnabled('eventorganization')) { print ''; @@ -305,8 +305,8 @@ if ($id > 0 || !empty($ref)) { print $form->textwithpicto($langs->trans("BillTime"), $htmltext); print '
'; } - if (!empty($conf->eventorganization->enabled)) { - print 'usage_organize_event ? ' checked="checked"' : '')).'"> '; + if (isModEnabled('eventorganization')) { + print 'usage_organize_event ? ' checked="checked"' : '')).'"> '; $htmltext = $langs->trans("EventOrganizationDescriptionLong"); print $form->textwithpicto($langs->trans("ManageOrganizeEvent"), $htmltext); } From e9bed0bd3198c2caab911275f1c869c30b089359 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 21 Jul 2022 11:08:02 +0200 Subject: [PATCH 250/826] Fix remove "use Stripe\" --- htdocs/compta/deplacement/class/deplacement.class.php | 2 -- htdocs/core/modules/bank/doc/pdf_sepamandate.modules.php | 2 -- 2 files changed, 4 deletions(-) diff --git a/htdocs/compta/deplacement/class/deplacement.class.php b/htdocs/compta/deplacement/class/deplacement.class.php index fb4f9eb17d4..226c4bc350e 100644 --- a/htdocs/compta/deplacement/class/deplacement.class.php +++ b/htdocs/compta/deplacement/class/deplacement.class.php @@ -1,6 +1,4 @@ * Copyright (C) 2004-2011 Laurent Destailleur * Copyright (C) 2009-2012 Regis Houssin diff --git a/htdocs/core/modules/bank/doc/pdf_sepamandate.modules.php b/htdocs/core/modules/bank/doc/pdf_sepamandate.modules.php index 8afafd8c06c..314a1fa7853 100644 --- a/htdocs/core/modules/bank/doc/pdf_sepamandate.modules.php +++ b/htdocs/core/modules/bank/doc/pdf_sepamandate.modules.php @@ -1,6 +1,4 @@ * Copyright (C) 2020 Josep Lluís Amador * From 1f25452d65ccab8fcb0135701b1c12d9b03d7ea1 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 21 Jul 2022 12:51:58 +0200 Subject: [PATCH 251/826] FIX doleval with @ --- htdocs/core/lib/functions.lib.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 51d26491826..192c6522d63 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -8599,7 +8599,8 @@ function dol_eval($s, $returnvalue = 0, $hideerrors = 1, $onlysimplestring = '1' if ($onlysimplestring == '1') { // We must accept: '1 && getDolGlobalInt("doesnotexist1") && $conf->global->MAIN_FEATURES_LEVEL' // We must accept: '$conf->barcode->enabled && preg_match(\'/^(AAA|BBB)/\',$leftmenu)' - if (preg_match('/[^a-z0-9\s'.preg_quote('^$_+-.*>&|=!?():"\',/', '/').']/i', $s)) { + // We must accept: '$user->rights->cabinetmed->read && $object->canvas=="patient@cabinetmed"' + if (preg_match('/[^a-z0-9\s'.preg_quote('^$_+-.*>&|=!?():"\',/@', '/').']/i', $s)) { if ($returnvalue) { return 'Bad string syntax to evaluate (found chars that are not chars for simplestring): '.$s; } else { @@ -9020,6 +9021,7 @@ function complete_head_from_modules($conf, $langs, $object, &$head, &$h, $type, if ($values[0] != $type) { continue; } + //var_dump(verifCond($values[4])); if (verifCond($values[4])) { if ($values[3]) { From 1701982ab5b4204be378abbc283d106fd01e9f18 Mon Sep 17 00:00:00 2001 From: Quatadah Nasdami Date: Thu, 21 Jul 2022 14:36:18 +0200 Subject: [PATCH 252/826] pushing first tempalte --- .../websites/website_template-style01.png | Bin 0 -> 46056 bytes .../websites/website_template-style01.zip | Bin 0 -> 16436 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 htdocs/install/doctemplates/websites/website_template-style01.png create mode 100644 htdocs/install/doctemplates/websites/website_template-style01.zip diff --git a/htdocs/install/doctemplates/websites/website_template-style01.png b/htdocs/install/doctemplates/websites/website_template-style01.png new file mode 100644 index 0000000000000000000000000000000000000000..4e409583f92ea376461cfdf3eeed22bd57b88950 GIT binary patch literal 46056 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 literal 0 HcmV?d00001 diff --git a/htdocs/install/doctemplates/websites/website_template-style01.zip b/htdocs/install/doctemplates/websites/website_template-style01.zip new file mode 100644 index 0000000000000000000000000000000000000000..100e66ad6b2a9be304f5a0adbac7a22a04d37d7d GIT binary patch literal 16436 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 Date: Thu, 21 Jul 2022 14:41:22 +0200 Subject: [PATCH 253/826] NEW project label insted of title in substitue variables --- htdocs/core/lib/functions.lib.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 50d72272e89..70152891497 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -7318,8 +7318,8 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, if ($onlykey) { $substitutionarray['__ID__'] = '__ID__'; $substitutionarray['__REF__'] = '__REF__'; - $substitutionarray['__NAME__'] = '__NAME__'; $substitutionarray['__NEWREF__'] = '__NEWREF__'; + $substitutionarray['__LABEL__'] = '__LABEL__'; $substitutionarray['__REF_CLIENT__'] = '__REF_CLIENT__'; $substitutionarray['__REF_SUPPLIER__'] = '__REF_SUPPLIER__'; $substitutionarray['__NOTE_PUBLIC__'] = '__NOTE_PUBLIC__'; @@ -7413,8 +7413,8 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, } else { $substitutionarray['__ID__'] = $object->id; $substitutionarray['__REF__'] = $object->ref; - $substitutionarray['__NAME__'] = $object->title; $substitutionarray['__NEWREF__'] = $object->newref; + $substitutionarray['__LABEL__'] = (isset($object->label) ? $object->label : (isset($object->title) ? $object->title : null)); $substitutionarray['__REF_CLIENT__'] = (isset($object->ref_client) ? $object->ref_client : (isset($object->ref_customer) ? $object->ref_customer : null)); $substitutionarray['__REF_SUPPLIER__'] = (isset($object->ref_supplier) ? $object->ref_supplier : null); $substitutionarray['__NOTE_PUBLIC__'] = (isset($object->note_public) ? $object->note_public : null); From 82eaf4524a935c69045486b0747b7dc3a0553e87 Mon Sep 17 00:00:00 2001 From: Quatadah Nasdami Date: Thu, 21 Jul 2022 15:01:53 +0200 Subject: [PATCH 254/826] adding second template --- .../websites/website_template-style01.png | Bin 46056 -> 0 bytes .../websites/website_template-style01.zip | Bin 16436 -> 0 bytes .../websites/website_template-style02.jpg | Bin 0 -> 342722 bytes .../websites/website_template-style02.zip | Bin 0 -> 15973 bytes 4 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 htdocs/install/doctemplates/websites/website_template-style01.png delete mode 100644 htdocs/install/doctemplates/websites/website_template-style01.zip create mode 100644 htdocs/install/doctemplates/websites/website_template-style02.jpg create mode 100644 htdocs/install/doctemplates/websites/website_template-style02.zip diff --git a/htdocs/install/doctemplates/websites/website_template-style01.png b/htdocs/install/doctemplates/websites/website_template-style01.png deleted file mode 100644 index 4e409583f92ea376461cfdf3eeed22bd57b88950..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46056 zcmeFZXH-*b*EMVf8=?Xt-9{4u>C#0h(xvw5vfeZqB*y=R3!DJm>d2#&`ZW23wMS?RBj+*PL@*n@?|)WJs=2Upsg19Et2}N!4@b zE(@GHcj4`o3&0h5+jo!7ox6WdR#HOU>-;9%Q=5Es;b8kvyezw8)JW-0sJzVWr<2zY z3_sSh9Ux%$P0#yontmd2=97;2^iw;t{E*{r8-hm4*mI@c*mx3sp-^cYQ(LDL2cJsx z78__n<13H-Zz?@GeGqW&!j=1f`6uAcrPK5~O7C1>oI8K%*5CdiW~N|G{dVbZzYctw zMJgbsBqk|i=*sUOP!(dO`~6zZmCwVms$`Y-e!uezIp&;4e_6=cx-!Vmt3p+6-rarl z+fpvQMrFJGel6zV3pp)0#X-~ezdh4A*3_8D->wCy0^cE*e^od9?+Hn zJJ}yNO?%Ygr&+y;US|8kwRz*dni(1y|BeC(frML{TSmzcTyyXq0{vM<<@j!vJ z;l>>{?~~2i;KK2f(R!`&b@!AWO_ys$EcolGV)Eqe<{RU@*UrwaFKhyK;V^p6 zP}A;0tuW0}{5OST0`y1=%&2Ts!y@p;ZU!>r@=0v}36uTF7g*FXyEnz(dUUe^cn8LPEp%rBnbfow1he6yaQSCvG9 z=H`BVWTlQ+Q7biNs*Xud+1vF~Azvl@kOPMh|CWWAs3zgpC`G78{14me`7Fch28D_r zfaGcLsHkpijxv9uFaP?M)HWjML&KOYO?s17`$e><7fYyV%U1aI1>hlsLGzj07DNNI z&pq_X+vDo7)FJ~>zuzRNX+{ZUbcB_k;`7;pPGG_78k=h<9s<4S!8AK^hsfye_2<5* zA1t8)4)BBTv~PFT*aY5&Q@&P|XPYTQ5kD!-UW!>Rw>b+Hcmb6hmv;JuZ{O8X{8*O$ zuYd>OLY?>pN8ub!?OI*(_7O@B@Y;&KPOSp|C*?v(c5aS_?a=g2oa6D>%MyCnsp$RC zg)Z0CMoxqNr6JoY2hIq}H6Dw)py+~^(dm*ZwD+hTT+EKUi0ELUnKkaK9LH4u*WI)( zIP&EX^IK((*{B)TKQYXTylmc>8jt_3Oiic0jSPlqE{`1yB=>dr#0B)ZXWp(8Z%iC4W5omORt0Ooj{E8#ms&JYck#08W%q{=xS;vd-#O7 zy7H8LCvGv*;$x=QcK2B6iCnibwa7hj`&^dLZ2?En{03)zrNxMa3b{eI2KS`uVFwVS zs5FsUUxLH~EmHVuvG+-EsehyMw^D=9fh2=+lD~sQlQ6lLFRKA{f2tEMvRV5OxPb@l zbGMNLx-M2$YZR)HP+w@!7zkhxb%vK_J_mekb3(kDrY@$CA@u^ATwz0wE$>~23zjbF z&2XQq@0>8rt(g=B3A0VjvdgL^sxES&(pf|GfwPHW@n65H(Wb(C>wB7I8IQx$`A1s# znT&P{bRV6ru&ayra-2Vnx(P zS+8aZNJ!mcP4afohbT81vGu}*^DCo~DMIX_3&2K(X$T1GHh4!N2(&^e2{C@6^A<4h z#R$)RjqLyccO_Lut$68(ZaO=u9#53`KR}0S7V@Q$AOHlLCu1gy{wi=6h)aWy|r?Dk<{z&dXs-me(lv737u0ozW>L;a$Y#dSL%A30C)iP2b6X zq8UrgIn0+dUXPRaEg30UOz5;u_oj#^9d%tw=ul2a_#atWD-<2M z!`$KI2VD#r#L}WChe{yxl5Sd@B5@>Hw_f9e-ypzwIVB* zWQ-iq>HYv1Rb{E?iH07|nb_ziN#x;yoFk4(A2b*(w%9lrFs%EW1|&#e-Rip%`r#*@ zJKm9DNzT|7sbWpN##fZyJd4EU>jHN#%`e0jGSuQaOXI$4D3iDM343%8+!H@4d24K= zJ3V@QeL22}b%=2Jk{sFGWr@!Y2+gK;5F#{o*xHj`q_3LoW^z@<#g|4~qP)$KgOL+~miG z)#imPq4=M{V4zWM6EWJ1!9W;8Aej$uXI-zU5q_TEaKPq{TIYjDh`;f+pMl`gUwx2L z(Jym>1Vul2JK6amiUA4r)go`F{Pby=npobKV{QH0DV|h?JSs)VAkUz~bZlc&%;}jy z)@`YwSyWeEbm3V@P=V`R%z;dLUt=wL4DPd^D zGTY(As=HL?*L`EvL`jfowJwG@o~s`V$qUA2YZB4%YXG8 z?Q;Tjuh*qMn)zVDe3p!ITIaG>2M0OBmT#nS&Mh~^M%PYy|@2IgIXYj;7rI2!74vA2;!H*VBZda^k_dD4##Q~rpiHO}Z zelsblLeB1{>5twz+&gyleiO>ai0y=1;?n$mBB*fygR_Tu2n)eLK-Y_c`}&06W49jA zscNZ^+uwC|2H-B%@lFcR)7HAk;LFSJVEbQ_=!uj+I$bMDNcsAeV19h#TL0f#>iw%g zevjr3oHK~ftj8&)@Mx`@kAlPqQTEBh{_6-^?Y54z9+sG$gip`VPo$iAyz@g45gqk8iC+} z)7pSA9KaebOI$(6xvo}3UgVKp>5+v2SK}H_?@DdU`PJ1K!~7heqyU!p>({xlKWO%1 z=>)1zQY8iob4NZDPkUzDpHn!I{qwr5oO)Bcs7DWGf7%m3r7h)jaRNXC2kP-vC;Of` z7VKh&2QXL6X=_JRVYQtv+C{%sy6>#CHqdaOa?ZO`cgpM)>S$44MEdSMU;Po=-_f2b z;)&4T_;kYYH^h8_xD>AD(*-5T;|x8Wol%}PNfx^(tsH?h%KsrM9iFzgd$K)Z!H*fz zL(86)D+GTwdBohGNW*1m*je_)B|T@)@K8>oUM4CmfydEqbZ?z~W<7Tg_@!4N5u>83 z;Ki5j6ThCUt*g|V&&=Oedr0~8S~3?*0|RzZcR*xSi^v)I+=4ijqf6w*?4NtRYy-lP z+pG8Nv7hRjFn(_bw|jhy1JmSU1N&?3Gd;vVG3OUAgoBF7}97j2r#fp zXX7BI#;qfHrKsd83_$$m7dwW@BV8hrWEaPl!!}(V8`-wEGg(f{eWPYE^%f&5z$4|n z7k6=4O7}eg8vbar?3llPLi7Ct^dsrK+#L2Ojh;O0?v9b_$S}~s&c5i3!fj|(l+*>D zWazwBcC8jlhl!YF9@TuO+W8431+%D~nyadgtrXJ%!1TRNDYfx_Xy)=AdqjD~V$-+b z+rl?#u>gKW*5k50LUo3E0775yJOU6o(L!}kCspA0)X1gaaUWIGGP5tQT1asg($4Pm z*W(KP@rqcD8{bDV3|IIJi68PcE^}BqV4mgH~4AE`JG2&SWrb`+k5!#(xs-sUjPy}?64(n zD_cSw^O{13Gw?uqH~iY?oOu4+?x$VtA+MI{8AKV8+kexWfcTkTzn};^NC0YN?&|G! z+tK66)@m209sq7rdo18YGcK$RPwx)eAARTEry;z_t&^{ni-5U>>DFjBG!{dPtH$XI4@XLx$XgEO~ZgRPS% z*&F3|mw;S|UhVg{|I}j9FXpnoCxaFPSgZZ<28PoQe@HL#lus`P;1<+v;Nxj`ROY5I zzdCvQlze>8>IeY%z(>O}y^h+t0HRgGJZm?}D(N!@z;7zRx0gs$?cl#T&qm_@ajGr{Sn^ME)`{oZ z+}PF#f~+OPXOU?!9w17-2gBypgno0joI0QV={xqw-2p({l~Gjy3>j27A?9}S zHY^R4Es7ELlccu2k9QEhtm&5+zX}NMlfh5XOYtYR6K8Ul zAQ#IgCYvVl7s(XpcWtd?TMVSKR~am?yN_m$qV{l7g`jwhhX;0-Z#VDEhaSZwG_dG; zUa1BYU$=5`E@vpmf?8%qVF&Pur7w-cFrbRp#5ojv>;!WTsdyR=*PM6C6~xv=eNx;G zS%S3aQsF{3Xz$b-t85_fIj8)SO8Zd`u`pLRear=3-#Q@nZ?tiSB zG_8^gUc}2pf;B|ufWij6A%H;v5>GbI9dioJ8VS=Vb^Uep384J2xX<_Tnw1RCj*g~W zfi`zns=Vj(ysD&8g|+Lz7c&LyX(r;#8;a%xa_*;{+GYF&px(|~U^ zW-wImfK$Rn(c(+qW;9dnJo>AwoRlye*$CVao22ubZl@-J_0nWv(cho(rmS0vP~cy=&G5t;o%5 zKz;&RMeh)eQ4w6TZBzwZ3#(DV$9B@1D+7&DU3cmax&)GkVI&NUp_y7^)NuogWXeb& zxdBBgsZs~Xq-H6m;x8Qg_xx8h{ANnv%gLA0VYHsR{dCr!YJhg>INgv1{=l)bhTc(p z2k?9L{TrOR^_thZhVQrm3?13vi2-QpFssH*2k)aL*3tsLN?rTCX?Gw9f#2q}78d=1 z)(I#rPc$4rFO{0_dDuhokoU^mI-#WMhMafE*cDb!^L;t3hlHcLsm%6s{Kez)ozB#U z9;dcZreKd|ot$F5+kVolIH9&0Sx-y~paLJG+_e9TR3gA)@IQKOgJIFE?_ai^0KKy@ zXz;)<)$ZnCj&Ud<2gne$WUbJaP&X@FQ|#_Fhn*Z? zLs~6*!6$o(T^Hq*eKd-1*BXEE3xjO=o(`pwKd`SLbPmz^9s+57s#UNF)Y5BDMS%EI z0ltWviXqfz>$(vkhpRl3CC+xVNV?Etb#Wnk`;HWwx~#nNgca`&H_>oJ_fO?y)LiyD z_uC^NG6p?br$4j6~L448n!-gmcI%K@1KICasK zalGEABA@>1o*$EUy2=5hi6re7*JHo0CmM|aK_C1ixI63{Nz21xmnout3K$_HcR9YO z`2u-F3d9XZ8;p9wc<1uR~Jt+k^8j+xp4+=mWH|88b z;tByyvt_T>aYU`ptM zAi$C7qK6=q%kccTBOIW_fba!8DWT{2?{q6~OF8%dpa8c0DU#j^03!fTsZ%PNqoTq6 z+IN*sk#HPoc5e|ZF_v+s)WE243^3x9s|6Q8R6i5NMg4b+@EC4@6HQt7P_8QdZwLtV4vj*l57uI?2aapeexu}YJXMWyR6sj4ZtE;CgTSG0%-P`69;&W=*%mS8IKx3 z{Q=vyd5x%8$7eu`H)!fWNL`8olk?_x(JGZW(g!92FoF1gYi03o?P z-L?KKpvi9zMKkZzIV_SzrvbIUQb5v}S=+_ZnIG;0&97|v?c+Kq@1@@u_^VSL zKyrB}dN^ka1=tVLy@{4PU=)BUC;<*PAiw~O#TCtz0h?s@Ft3XlqgQ`W_OT049)Kf_ z1~wdMt8QAto^Bq6qeW8V_+iU_2RN)zLYH-EeW-+x0Vtslfc^#&X6MOXFt=l+*kixp z?DSRT#A@TUHd!M1*)C?|$y3P*4@>>f2)oa#xFTYjlggFrMw^nsd}!=mqrH z7K`3U{W7c9M~?whdxrGh(>ym~W{osZ(NjoQpI!QJ&gBgN2Y$FBPXSd3G#IHf8m3KApw~%Tl47!qazp|0TUcEiw2KE|B1065M#m(pdHU)n9cR;QQh3{==Bh1X(N*bMv=>5cTi>26T9&IAZ2#MuHue4~vY=`r z6`|i!(Dt8(*xDnxE&Tskleq2>&wtMX{C7Zp!2VBBZqN&2q5Eq`xE~O}_fH#HWUXdG z^V|CVEs?*>2mUjq|F=Z`zdHGUsYL!Qi+?!c@^9z(pF;lsS?Bn-EdDKv|KTbBIeGUl zq52KmR6FwhBs?NW;ap2(~YCSf^ zZ2ivaMEt>V_i$S5wFa5SO~08x^z9Mn)z8BOdB{GxLGT;kOc1;SFBnqj>+O{Ynt0@m z=}FT)=V6;4D$vq}+;EPD6zwDhzF1=VEl zt}5^lp9#UHWI!|T9-mnxljQ*eS|q+>=`iQbMB&2W%kURzA3AIlr@LWVd1!paz}G2~ z4|`7xVZ$9I9ttu;h`0c))cy_5#=))ayS$_~6$;-x#XJ%gv)h)hV`BcC?41oN%RkiW zcPvbBT(M12oRQ1;qk{f(X1bY}9aw;|d|+l^TF~7ajlXy`3n%o_J~%m?vbSKfKU9!9 zV)l323hZgX%P5DQUFP9Bh6@bpYkaGFu4*8}G)#}^WbSMAfR$&w^9Qv)NmqDYaJE6} z$u8n<)8(i?+=?ceJNI)|w`k5`&JJ9Yv&|Vker`J0PPs0SFc1;ln4tuI2C9Z`C8VKq zKsxaoBp{2K2?uzC)pJyoFEw1r4St2)W+9JnyIb$e^@&s{Ccn~BBH4v7iEJ#Hq&jS= z;duVhoH>u7{pZks%viA;`aJSkef%JU!Vl30Oj!B$q#sfn!%DLFV zPP$+E!e|-iytVvL$=CPhtRLf;9kY*z>I6b(>NH4ybNq+vi;mRNABRr~TG3^7?k34} zEjw3#J^9ll7{B&;xHz_3kL}7I5k%y^2+a82$=lk$rGLq>I74Y7;og%{MT2D1n)`LJ zFpa#~)H1vG$qZrEyUvfU9^Iv>U5q<+M!N*u4c79HDtXgnaeF#%d7L~eS+f4fNy>D@eByIh&^T zvWW+x#uAV97uR;={brEr^TWDN6*+E0e~bIO=455nP2#;+K@NCL{=-k&5FJM!$e(5gHO{TI#(%q@6_;$*LR|mG-Go~N~tY;!t`;S zEwrRSez0uOT99sECyLk7auu`=+jhM4AFtP#46wtHlz*H< zQ|2!`m^M_bCY2l8#fayR{JiLzmR)#R?IH$}WRA-c0o5Lk;k>#)>W(Y(kFy@EO4kbF zu0C+?FxEr#)>&=TdWLI7$-@N;Ql`E!LLa1e{3+(^q|U2iaYq_mOe7+km(E|>eBHE* zGl9j~C@kAZ%w{Mi@|P}m^w%ES>Qu(4&3q{qpw&ruE0SygvpYOu(5Ri7(K~rlnI+Vh zS2puuSx^0*NTuH{b$ZQ;tJd(0eC6cMEH<1Y)S9>@$WDOOU|HK`@8+W3cUuN_>-di3 zdguH<>DaFoU=#R{cbb*XN{Ud{^dVwJL6KWP+W@v#s)D5KGecd&@_l~}n(4K~>KG*7 z5v;!*9f+Kj@dY1l8WwNP`cpP`*FCPB9@{3kZK??)ZLg8r7J==Kf7(vfuO$-3^rP%f zrsrvDYo3Z*LDs9b=SL!M6gA;5xHcys<-_g@{Lu+EfJOK{KXWuOkN~q!9HOPkR2dvs zxZ<^raLb+nKF!0$$*110JfGKNmrtR~vNCdYzi8#%tvr|V=Ydc^(N!MC74TQbH`)()^8~UPfo(f8s6(6az`)r7||)-gAvibE*wHE4U5C z{s)wj`_Xukf@E!84$gF0j=&tvHq<5ezM`p!Yq}FDDe_kD@(&3Nl)G?T2VutDazp$jtlM!A?(|C{ckPMx%U8eKABp<5$aA z2uZ^i3+_zETWx;h6U_S$3EmbW3;NVc9FLi4X1hf2OM5<5c5NyUBd39*HDKQhr<~S> z`(*!o=t;SNnA6+_^khNEBq>mCzd|luBa(XG_>70nVAphEDTHCN=IT`SaFv$J6?JBU zLGeBRz}SbsOi~9`Jo#Lyph@`FyXhDNoM*a5R4CVS4+y&T8a!shL8xE<&wzk_F4^a$=dB6~Y(PwQwT_0l(Q zdM@_oo?#~&LNKEJ$zp~U_qb1Fs--8h`G@adK2*A|r^ad}!CJ2dkC$Dvg6a5x)wsHP zQ=s`W^wj>Gc)tlh#|l?!Fhlv#eUm)v)3%rW)K&7v6B>k}9?ReIpF~ZdA5_zLfyJ@u z6ws^E5xp-xQJ8MeVc8>9hlI&hcEu;W)R4K^XvUveIKmK4Vw-Yk z=*B!I<8DdIZwO(x<@dqzxtC%LMC$TV#*IJ*I46VnD7(pIl_DgTQo3~uLK;_j2>J9t z_|JJj(+bd28z%p#y~F@Le7aJCVTT@m$#`*EjQ=#-ndGV1etNsL&uvi9{i12E%GU^A zD`dr!3X`{EQyPIy2vBLV0f!QP{bxoqWXE04w>rd3ncCCT(tK~VBR76qUGRDQ#`XYP z{SEf)Q_%wbwACgWqxy7r{Qeh2(P22*AVNBa zplZ6x(d(ld^>(oDu;`f%K4K5Sy=UWAR`o)n4Ys?cm|v|?uY|FXEieA5y_QSwzJr~s zk(#q{MWlA>rdDRWGIIn9UUkV1mCt6PUr@m-%hesqnUD25kO+ONF!cCnM|aF z^*koXJpX(Rp)CI#E507pp1GwLFrpaLQGFWjq$Z%%Di6g=_%l_mOg;kB(;&If5tOz@LGrr zkzJ#XXzA0M9ZZkmc#NN#?(k^LOH0kfBws=C1l1#+90?cM-i$coSicy^@8`^*3!D7Q zu*Z?_0DO!OkdM`cr6qP+Oz(Mf!5hmI?L2U0FL6-$!#-v1*a4o0KG+k*pa!;XB*K$< zP8YHsC;amwEw>|-sYt9b*Du(Qc{0;Ign=u12tq1ATCB;kK{nEAxlVugI7`gwsIlv2fcsNMehmE4Qnixpi`+7}VJz)Q*BL?Q8 z8xDFcNzoOeJK{1EQ-?F@A=Pjfhs1gEz1~w-l=gHRs&Nk+_wn>5;Z&G74$H{#)9U8S zm3zdBdujQG?YsWhc}df+eu$W`?YW2H$WAjFpJ%HT?W|SLOC=(k2xg{%`rGj^Ag2p4 zR3UEjW2aXoj%j)a1kM%#uunu0u&_R?g}>km%US9O-*tLQKa7j(-|DV#{8$YB(Fo=n zI5{bQLOxh#H_4gBA;vc%njAYk#>ufqr7A9dJ!EzDvA1JxK)TFmc`TEz4R`K?lRA^R zLkIpEx$By=u*F&v-u{%YB_Izgm#dzsuWH=&PnwK-Duc-EDZhydvvb`N$l!c zohm*@b4jJxTM&2n{VRn_txsK{r^y7tDaplc|MZ3VuJ82ns_y;?c+E(DSg}uXFqd<3 zlAxD-~FR`2(fP0s&+s`Y3mtpfx>lv!56s_K)6_0fSa- zHQPYS`yzvb)xlB&mqW`kG?qKs_d?Z%!HMGRmK?kWjWpg zZnIZbvsn<-J0X1gZ2b^L;Sx7O4^$+uGcf}x8dx)uPKPxz8N9LmO35%oJ}bBu0s;jrq3xw?h z&&DBs_S+x+I001#%z)wik$#ZXI)x~k=r%vp8T$Nb5@N;j!5o_nRM-iv_*UBg2CH)0f}M1JGO+c^I_q;aOH&Z(yZ79)Y%!@f5$=RdTowEntF%J zdyXZokv!aF9GjFVR2kQy*elktHI`hfYgci#B&FdiGl|Y9ttq@9dVGd|{)z!H zX{7_Y*BM&t&fEu<7fpB=7qKQ4(nCJ^j#&ArB{&eNX+Jjx^&L}Dn|=y^zR+}hS$Smi zCyid`>h!2N<>7v!Xs$wPQ_Jzu37a+}FK{Yvdy?u{Gqol!*Z%JE!BMsxETc2_)j?`9 z;g`7rl%M}tYHuvs%yf0!PG`T>FQqX^erlMlZx-=XUKwTwsxEqfED01_91rekC99lH z$P-{D@K@^wajyuqD(b&>h&_2!)$8YAV|~uvXYbqEPAm`eF3=}FeG=fi`BK~8(|2F4 zissv#uI<|G){>3z@H7{&i`oc$;&P!B9hbI{(r8MO3UcS@CK-9|6Lf3tkaI{73RAka z;OHLou_In%+C5yC3PzZP$Z)FhPVdD~9+sq@nBiwX$7zUjxl6JsZw7V0nt=0KiFHP< zCK4!yF(-Fabyr2;VyqK&%hhfClm9&nkkEN`_wM^((h}AF1!|IhFe6d1;E7}w^3wfm z(I_Mx*}huw*V=M-PSsja=ib-`LDcubJQ^@dc+fGndZ@L_MRku9!^L=9Sop6cst9NT({J67KrkSgPiw@jejaXqry1x4iPVDB&0Y_T46s+_U0IhQP8#Jz-SIFE&c~JHr_n>)>@TZ6}+X_a@SHLvmE>F6m_MmBkxFi z> z*b>Zp8&>ev@ei^Hn2G+%Y-s~Z03?uJs#E9TEb7rf*3dp>7rkYgZop9Om*QwW6aJF( z7P;VZZ0)Ziot+8oJU@1E^nuEoMi1DX@j8TrHpn#2*TMICs=SvJ-Eq76oqn53L%DrO z?iN

dSJTXs?#uw*4DU4_4C4jZil=1%^uIcR`p06lb3kYAmS?ZEWCR(o!fAdgOCnyvP%zRNYf%^Yy19P^daOU^MjTJ?AvD!IPy| znR0JgVI1vrdyR<#an*fURd89J#@(We)(jktq!sW+_a z72~p>erIo{zf%E)6}aS6!6*~z@Cm3#Oc8V{LvLkr5;@PetIy-&bwbxzd9?Ps>qu*7 zI`&_FV9ZXUR4Sirf{W*OFVWFDL;A(AeO~XL(4wR?%b0#SE_()+YFODkXXX(e%Mu+sV_KF?uW_2Cp>Jyz<4VUm)~xUe>;; zMBJ+ZJ7k`W_p}1)>iaLwkCjBW_i}@^%VkEt$za`t9Pdi0kck(6^80FWXciV0ntEoa zVPF8+1T|hb;sq#^FvYKZgF6hiPx6-CGkiU~#^HII6?=0hs^+`f?eId|bR5&qB|xbu zCcx+AuYVbn6t6%acS#HONd>pv@Efo}_a4TgW7{>$QdD1D)WQb0k7s3YZ;@hh9(q?% z`nF#KhKy%%pKk7DFJj0jNf;_Wr8>0wG@@{#n9?;0@=49&(u{?7l^x;bSRO5J(q|4U z2WihAlLqOv&}8r>^57+V_T3SdXm7blMr_AAX#?f(VlICbZz^ul2EUr-SHM#;J6ET0 z%JLY`w`c1b8yoQmZ}0pR@nqrXI!~hTqwPj$)i-nRs3LL6{`1RB=vw=EyZ15s^?nun z2j9me=qw-LH`0B6V!bWm1_9dUG@O3OPOC8;&1B-joC-yE z(o+wD_epP7o#d-KKr@!b>m1VeCQW&rbwA2Zj@7yMZ_duX@&-}<@LN|Sn-|BW?8_D7 z-fkXGF`=m}9>#eQp4;I}<^N!lMbXLK%@Dt)*{mLRyTsJ*K<*LmKebI7VtjTV`z}}l zXH(3?Z%{U?(kM}=Q&x_dh=au_#;BJ(RU=L5fe_Th$t<(`_j=fb66_s5-<%(J51zk( z$y`BquOAyk%(il_hl8VPRt`ewS5|L(<-d$$09%MjY;@?u(}y{G52`aMx`vp&QgSX{ zN%Hj%R_{X7covVoJr>O3B7%OPkm`f5lJGnP1>Ui5ArSSz9I&Pnwr}Q^5UAhL8D36%P1Xya&i;@+`!|xYYOIkZV!_29U+Li7IF`wdF{(WI+GhkfL=Yk*fNRM1H;Hxp zk`YNFpg+Eq5h=>kdc5DUgGDwWDU)E1`qJy;B_iA-BQt&FUQUaRXzdE#03rNP%~g_$ zyMY2n)AO4c9$XAsc7>PCY9uqNogal*vQ;LPsdf=FtLl~IpWuB|B*fjvjuaguqQdNI zvXxRPy{1%M%q;X-RZnl$%VxM9LjpH@&Ssz>EHHxEKZ-lp)Xr26KmFm{5{9pTk{}z~ zpYucpZ(Bmp_HxI}g$Tl7yt^zY!k6yDnRPm1hnk|~^pXC4mec8qeH&gkg4uQZbJLU^ zKlyso!q6Ixhw0Udy^<58-6*ZQacl+H4AaIOXN%mZ4afB3=wItUF>u=?ea^ww{26H2 z%E9BuMu>8kE$`I$V6B-DZCXYXr~N-)m3ff{_?&TK7)5aPoGh?OFXk^q24?-d=bl|S z!T~ASK&>H5_8WYuWcApJd|f~bacd!>NuVv0vU{w7jo)(2l^@qSl=PD1Rd zMhu#n#MAY=x^S64B`vXrCwoOkJw!v)Gg%Iuz(DT`H| z?Nd-I71E3A+ooU!j1_4dOMH9mbO z^z7>sY5rLA@jLb}yOFQ@Jclgrj%PWf8<4W!cu2|XIet)bU(tbc4#~gpodSfNmRScc zixqQOjL_ka7vHUP!F_WlawsdKqWVh>p7=`Er-jT2*vF@GCzaiA_j|x6A(|^S_6f&; z;^WDtOStzI|NdlFD-+?~G6Oh8frpv_G5xFO&!!ia7t$PD7s7{2%WMwUHi!D@8Hm)e zxoyOXaEQk4+G`*gzeY<^ZSy53wwY?gWsF}>| zDq&kOQXpzGae|M_kF+(xFOsGDURs`&?B=QIODsAmQfd^pQCOwc!&vkhPvj~lYYv!R z*gg_^3#Se18OkS9uC^inWxu+{I!;onl?SKhZkxrI&xTeSiFULJZM{@DVc1{afa7O| zsx>~ihFm0j{K9=9Uo+x|upRq^Jcpq>t^|{g#g7AIWpCEl)`9s{rJ5azA69*;FeSLx zqn{EmFQswc=}5Cag)O_CJ^!uCQGm?WXQX4|I^-^|vQqEn?HHc#&1_x^Q$^&-&de3% zsW6B7RQYL=9Ucng8@6_Kl;Es;nM`VMr14jWN zxBbNi2TorOPqDL27>%R0=QsvYRXlUig z(~57FA4A@1$1)LCemy?3&J2M`@Uh*Q^Rg+|RPI%Jo-{o7Z65Rc%3ed~Ckzs=F&Bqx zvnOIe*q*$rwgY{K++p$iEE1qM z{OIlEUyI<;3D(GCy0K~0r$5Q2?S3-ZA+5n`rIn_w-D1>eHVaW*?n@*g5i;1*v8M%0 zq7Mn8@0D^AR3T3JUR5d18scoBErr*2d-N{Ekj@{pu3gM``P%Dq|FHu)mMn^$c6v#^ z|8#$Rc6=jkVpexntf_78X0#roUlG7s9jkmL3Pb|jtNGC!d^%q_&y z_+s&QhF9@rKkkt%KO-mM>dA*@6yqhjLp2#y-~wEWaX;-!jP zs-==z+g~@n{Q3T_;~xWwx4Wlf9ZQF#X=iU26y0$mIGmVdJwUb;fEF8hcFjfo{fj~= zQr*0A(8ZmV`6HJ6-6#mZbAJPe*}%E=`lQ8$$eGyL=Yrrm~g>OmGoX>nfn)ywSX%wE2 zD9>Q^Jtrp@fMazVVS^SR14?};ozit$cEjIMI-RvWd zY$W1YUDZ?|bBTng2dV?V`IzHzTAHZo?1|by#6-@BnCSD$68&~W$<`x_5+u~)xMnAW za%p3O&EMZ+Qv3|p2*7jzS86799dN=$@32hQ^f5*ly7eX;_!X=19K#^Rgtb~CK9TPN zI9fiDlqh&U{WpHr3ChnoS~TqLr{*~)z6I{ z)g@!Zw4*SF!~;ZJ93x2vH%F`w+k!&G(+M#^17}N6mTQG|hJ{dxKI+O%zh^P8>dc{L zIn|zBRJ%cSaS?-rI(kX=)kErgD4bky(DvDj*jIbe3*aq%_+b{5C-PpDA*CT>-WrkR z)`(h9Qq1lt6fTFaJ)&A=u|l5;6@{RfNVSj;8*(l(Gw`K3f36iFEJni))0Ib)KXLHg zsgs*T2ekcHug5Y2Y*VL6?5RW zEJzeCFJ#y%NE|Y;^*R>3yN@62Q;mMVt+$uH{p*H!5}72Anh7>y3__AjdLyc^f~-`? zb}#;M&ukZ&`$v?qwfd!0gM8YQS%Z-E!|S#TB^W)#+O<8_+u*^q5@)L7i^?|#SS;Q0 zM|Ht{>hUlZ8+1R9dp`M&D?KF&$Lz0m3T6LVpN{N`mFt`ccYLwdkkV?y@N}b7!Tq|HFz1=$=?$DO zT9r~H;LiJ=b-I`bbNU54n1SVItottu)dnC%W)JZ7|s;A)Wc~~<2zFJocK%PO> z#frpyc17_z*mo-j2ZJ8F11QhX>!lp*`3sAv=|>0e(AQs1L)cqEvl=&*(%K(IQYkQY zin$&5LzE8(9CnMtx|=JuYZjprMo-?XA5)|@a5X?vW(gBu)P_eY=wk}u+O*|r+)c;t zBfYCzqJAA)DL-r&Ht((2e7AS&TRNaN^95AETs^bR z>#pp5b1dsIg&^q=(gxd6ffC=nO5v=QB=FbU(IO2r4INHjMC`FA`}GanUu^2YwAa9eaMJueP_i7v6cx|pY5enoL4nntI_NHI#Q_`*4gLl@i zONj)zX42y-8I$0~n- z)n;moHcMsd#p-kyQ69o9lWCGvO4loz&l4BOL;5-KcPVO?^H3|oUA3I`TCX)Lac)ab zTiz5CydnPqR;h1PFU$VS0}GhgqdAlBF5G6n7}&JQ+00gi38o5N(wSzj(A?{cxeCl9 z$+^g1S|77LI7(nx{gQDo$cZ@w591XnfPdeJ?1%?Wj!v7uULRh6zDoOaQEf;-@v&be zTh~T$_NCI&_HYv##t%;L>MGIX!??sGJA`ejLHj>pxpUN%uz?kqan2tiJI7h~Yu1nY zvGk><+fq`tKJV#-#-Shv50Z{B@6$C#2?0 z9F4b1wpTr<(Dc27r8;frS}*f#T)?S~t5fyjxae8sGvfO=1ngF114aBC%Ekt1HSOF2 zTz#Cb1jmQ4Tb|METKUuE^5wq%i_gkr#R5Y$QKm1yAUe0pRix6E#HhBr_tNtzP{VOw zwq_hm>U5?_6lB5*zAKKe6cZt5nRc?^8;qEql%F0}5wM_RTqHLIzsptXPL(I`XN?bV z!Q#R}D2gqL*M^%$4}@brP6qTLFygdqOqLz#_D;u75uNxLE*MQG2#mEoLo?UrSXAZsMs>IC%+rhE~pvmap8AJ zSsHqz*`Bd+S}K8Na@^wc^8cy9_J+Uja;5bG0MRj~c=r#rV38m5l zq2K4TOY*=uiTIn%hQJcX>$zxsuLg@#&|=_(rC>^c`GRKMc7uZo13ltQaxIi5pQeZH zjMsyIB=9q}%$%2dkRWGxqI`cK$Px`#W1;escM4r5KdZMc_3J zvfuZaS-iBE8f2_lE{%Cce|~2>q-2j1&*sa@+BkGOi0lsHn&qHSUX3rJBwG)s=)i9y z7guFW+8Gk`{8p=pnM;>A=X+>STuktSK^7Hd*@Efr%XeP6`G{Du+)V_uUNps%%qQyW z1Lk%|)bEK(kAO)jR%U*+|#)^UN^^t>@Ko)XwO-EEsI{*0uVqv z45D*19{ZE7NFuN(GQONy%Xljp3VWy!)@Nbj^xEcXvtF6I(^PyWGMzo1;^U0V;XQo5 zO9jTGO)S;#}{9gfoq;DIzmGDGMVIXH+6v#>{D9;b6&4^*@DD&j3_n^%!;=alJ(= zNo-f}hN&rqUF9GL5(p6#da8493~+>3HMVKC>K6`gRo6+EfifApMqEQ0V?{}cGv$uj zZQ6~}Y{^B^x;54n<#iumQfFna#zS{Zvwr;Wi^6_#zd74;n-?O$LA2#p$(W{fXqala z7hM=mek`A_xDfEQ;7Wdvt)8$a%vqIDdu@vDCCqhd+`5h2SFVZ!M{&n;>fo?2V9q~VUE$;(P-F;%QvB}h^y^JcoztUH5yNC zT!6!l%YB!^S6elx?Pk&KVQT80qE%b4kW7+tG{q5CNZPlu{PgK32U7=oR)j7J)kGIp z)vmMi@=BpJ?N=Xv1)pn_%se$JXZrHx%glEjEGC6a-%qJ|#Oq&3-#?Ih_zk#>ODf0o zL`^R66LGo|kq3dqV{2E_9d^X)a@b^|wu>k=5_Xov*XsO1Hr&6ulGsq6Bk7dnb z83-NAncabG=sw26!BLljW(1M-GnzN5^zy}w1q8qh&` zupZmRQP}X4#g#V=Af(xd?$25I$+@!<-bAis78);WVy9L3)>6hg-D{iUhwB{HD{>Yc zXVx_$%IgQc4C``E5?-7XN3pa#N>S@Wfi^Xc=+&KQP|{F^ij&+2uOCt5Wy<$%PgXlD z!}M#Sj=|Ch*sL&-MuGiMwBDqq`Fnz(+}EpthGP8!-v~|l)C;n`?7YHjBL+`>=ya=8 zTg9IfBhM{|eI6<=E@y|E3pAE)&rCV1OD4K{D4N0~7z#8alcdpK0T1c19SDd>MXR5k z2=|y?(^_!cFDm9WNE@$8@O(S9(T)CW*CB#Y+M%6rM6L`y^syD%Gu4@@_*srH-u5r~ z&^s>RzA+Y^I>x=y5ZOsiw!qk7xe_}}d_QqNAuZV}$7CZ4F8z9B&W$~K*DUF%aP4rb z!9xUYALYZA6gFTcjpe0E$1#6G zOz$gt3j_tOkMI*3Zw67)!JVYFD=0?fBACV0D?W6{ed?>f=B$h3&ur<*sV7P9tL;7u zk!BYXF2I@67;v_BZ-P@MR?m5e75r*RK3Wa&pUQ{mwXq08#M#4kl z#(7`qWMckA*I{GU&UOs`^#CqV9xv}-Q{3lhtgg90xT9hj}?xbud5T-n0#kGHxYwr?r7E-C}fy?WRkMB(sLC zmFg26e|RRu?R6=eg?#EBe_J0(yQ5lyPlJy$h}G_5bu}DHcn2E)x{$3LlD)vTJjd*P zPF1f+Rfu<H5W+h_het3157km=!oDu^fa4qAaP6bJ|k%d z^!_8R$)6LEEP)yKcDz`n+RhIN5bmSj*~S8}VFl2~+tJle4N@OlYt(R}cnQF%dz>a{ z=Fl0R%b~1?cnQ=oTu#$E<}DnI!*$I&j1!V$O3H1QULxleHO9JDSLyv)6SXyYk-0;r zGp{-|TDgnrDUCJt)#|yAC-8i$3p>!hDX>#%g7vMSI29uNZoa9){l)1%Ef89m0!&dks(WA$l0CmT-}zlH>Xu6lM6V z7B9@T>~!9`cs4$bt z`pI{ng9ZPM5E3S0ABIyjls`^;+#f9!;1>c?y7FELQAsZ2yn~0<p^+wwWjPXvG z?rT*YpIldnjfv+HUxnnBS4{nyk9|3+=@+W1v$;aH;d0$GB05qDIcmSd1w!qfoQA!- zfb5{6@GD4Bm;5>Y&9{1jRVlT+hY0+}UNWEQrmn5Ib(aGOfs9(^9mkXIEK6>qEB^e# z=CAfy{r;R@EWHhingfYoT?OSXrFG8Ll6bj9h@MGgWgusYjv0DvprKEBJ(zoxl)-+CpdK=;s`%(OmaMrZGdg(%+DZsMUP zgW#g|x)d<`F3@J8)%#QX>Bj|Sv@dPdjxMyU?fJv-$m_L-=3f*DLOB`+0WGZkM=u@; zBKaq#;;H3PQMu{tPjB_%ov{@0ecZL_pb_YKy?gQ5gFYZRstw$nH%r#?0iW&-DwHlJ zL56~{K&X_zA>wKEm$4k!vY359o!OHDA%0b^ciK+*CYrA^e9?*rGI%IeZjR*%v2{1B zcWN-xX~h+Zxh4x0_48GW>|U%^+J|E(sVaPE*b5=O#3g&zMH5VDry}CRe$wjb;{ux@ z9dk(W{Km>>8aP7BgW1nD;UN4+pHupvo%IDDT_1GVm!*oljzNUtd#LbbDM@{Dlx&nK z>=tejFF4yNM!NB2Xr)nBGdkRDBPutZo#Ds)y|ZzfHy?M|j3D}j%mky9wdb_vTiiy} zYI3Ry%0A2-w4NQ{A45OcmXg(Wp~gur2Vfw_gMId}%FWcZmbl9@k>NUC%$LOyH_Rjn z(r8C&n9I`;!64B;8;*F z+)xufm7)vvG|Awos5vDZa@um9Vmrr)XR|Ie-Auv@4gYYd{(3-LExrNJIK0p+mS$OY z=RC5}h(FIN#iT|xx7(H91d?Lg@e>i_Uf-o=UV(&M!%@rbWRy)?WuZGvsW2Q>Lt;IWRnwy~w`!bg!Xm$zP z5mq9N`c4~|{%z4nem_{-z!cbi~$j#$dOqe&a>K4&q40pJf`Y~H|i3i4or%qlP z{mE{17frFRgoa=0zUjLGS{q{I{LVi?IJwZ9sQOf1XFzvyuv$k+?nA4LX6CXf$3}lf zg>ymQCkHN1Nl@eRxr-8sOZd{alBL>zaH)}e-(AsX{zf6?)9Ew*5M}?!d&EutbK6?8_19VxYpHV-SVc2tt_8CV!qU#?y7&Z=!u71 zAeWOuoY%+t%O)sT_Gg|XT$+(#hlEJc{y6nEo(G$dA??r+ISWjPkWjwiz(?1}T%+bk zLz;0KnmB*JssPRDynm|;$zAP>Ubo*45vk_6V{4ytv0dLxF(tazm00~j>Q@;mt$9aO z6T#%e;!JfCvZU^0-{Ca{E9@qyj08b zR8W6ZbP^m#eP0we`lKYJq4CJH@7u9nh?GY5Btda}jb8E#e%!W^=|gb6rTVjg;X{dt zx);(^Nh#f1+;(sKMfS5dTY0wI{2I;&y)Im^kqJDkUH;?wrBAfEUg|(Rr>JP(AEtcE ziBZ*wz*57U_3Oa1_YPJrCjw<06A3(GS~c6R9^9`6U#4hw4kyLRu6DS=V(Qn~SDgdB zQ-=$BuR1)VLWSoi@wW3sRdwAYO{-sdw@u^kO=W~ejK{|ELa)vXqP&#{`G?GngT(3A z`m8(-7-0J7S2DUwHpJO|w8()=E1VtZuTCq^^F`WfZr47cDZ7?zh}2325jK8C|GEXG zHZ9VlnRVUh^RU24zD4w_Zmg`i6V70m~ITYd8FKZr||3pg+^$7`fF-II9k`fq$UZvqu+Gd9T z9Nbi2pIeIHdW!Kji)w@6WNym#&LH0>FtP6E$}pv0eP6M@p1*|v6Gfcntv^L)uIpjZ zI9NS)S=y8;O?NbfS_w7q5zgm2d$<1;y8f0c@gi@yNq0GR()|56*0^-iGpYTRm3#Wl zoyMgR_nJTI=1lDqok%5fk%h}ZJk@3=$~Z4hCS03Q?w2E)*w6+ODY>|m-6Bk1=f%(w z4~tD#NOOwr-tggWPKW8XIME|T+;AtW@k$IqjIrjRDMLTXE&LXe^#n)XIRM4Nj9(&r zeEv>G$I}E>Du?#vavDL!4{fQ{g%Uyt_xp<6vqgE#ogFUARroO9DnQ!L`Jp!3wByts z%Xs6i1YF8dU>HMxPJC6d(A8**A6)0V_xqZ~7irjjEgag;wO>SDP0M%|OJ<<`J2qsLgg7#wZCmSGgx(eNir^T* zmvSYpLsF@6DJ5>!)j_!6+Q-xvw!BWMYa27U+LjaCq;ImT_&6?q=Y;x&4aBdskC_|j z^)&&{>XQ&w8Z&E*^I6d>=M-;z9A?EQ-J))!$`x5!?&;Ow-1J#d%F)=cB(rmJxxWc2 zg&mM_A3vya)2nJW;h@{ltnwMmn8_Pc?6~0Zb+dGPgjs!tRE1VE>G@8DS4q3S@qX%l z*hQ?z=7~(P3Td`7f#rY+)nZ`8PqAp~9xi1udZfy^&T8yrAg&i&W-I+|yXqa>%GIIfG{qs~ zIDOc~GfKnh=tp;1&@BaL?q{;LtMP$s_#HbOAjP35ox}DV51lBOVO##dn{~!XxqZUn z+EZ-0on%}83Yl+%JVnFj@!}pfc6*UE?jnHC%2-*h6!qOaBKoeQ66YG8k5l-U1fiHp zI|XHqcO)7zGSxdl+{Ni@(=mzLD|!TjSjuMnE8mQQxi`fQW2&91Am+)rVajgKD@+m( zf5vc6pE~qK5}asPS!x5Zk1FG6jKJS$)0i|NE5$?0_iL}vXRCXgXFgkhV}*HLwx9L7 zF+nSz@W2E2RIj&=`hi|U2#^Y0-4c;dM8H!btX$X>*WVvexV@X%ezCJ5TOT#H zuB`bjB&gccK(}Gnq_JdUF6~Ww;TJO>4&*uF$Tq}Q9E6_x!4^(T8(7%X!abogxAlDM z1F&n!HI~m9@7Nc4qoV)onYy49e989?GJ=|@`9)&s!z;=&ksztKFt*CIp$YpTZnsI7 zAp|XlceDhw&TpEPx?-lN>oeOM`(F#gL#JkV1^ZVdPTXK^9_DxR(_dB!-=CZ>rHPb9 z6^wn0;>y*wS2lk^ISNwm+fP5O+7*+@51#loxaVzZtH*A%O^Yl$rT*ON4lvPzoj|u(L74Krkyh73*!S}=n3;yeO5A*CLS4IHg~JaL(@f-gpAdL;WJ-d%n}sT9 zQ7*0(yCeDc1uztF;Q>{yiPw;D{Z9x^%NRz5msl%eVe3aW?WNIxw~NKjH-Z^yGrbMB zx@u5T3gD(xR*UI!M?SK|gEH`Ce?f#ZbL$pWE{mhI=Ii*hKh)P28){C{M4P`fws5&e z`Fc$i{hBfF%baS~yl43`=p|Wp3?KBZrI6EPovM74N(bYv;|pS6n@$3zL55a-YlKVy zm5B{mK<{b;++nwTD5xQg_k@>ilPBhN)=DxpSH*X2p^bW#?%i>r1}!RAycku^XjH#| zs(;z22g8-sES**NHy=Sh@70Kz!hDUS`4c_Ise$i&Qa@8ak3*TH4dzbUQ6gG|^<2lVtDws@Rvj7l8A5>5VlR~)ZK3yECM*+jF%@}MpHwB&&WcIdUY%<}X@hH@c~|jsf(#EcTwI1ng4lPt zA7T33FU)7S0Y_qszTWdgve>bFD}Fw=m+s!K)jTTKcAPDlKT9(w``}?sP5HghkgZqt zV=KwvtJU-EoAnKAeWBgtkS!!HWGp8OZ%G!rMlEPDS(s?EUm8Y7Tg4`$b$Q}X)0ZdN zF$d}+rp@7O!V!%{JZp*3QhvdZlRIuSv_IlY&W(HIH%T^B#k!3gI`6yLPK_JnR<&B@ zI~grNgi2E9t6DacA^j1hXV-e14z9BpC)GoA```+F^%!j>?adFy+u@}%J^*2}7nzc+ z;hm!q+#ni6wc$G2zL!GjxQ_aLm1k94&maAA!gjrJ_B)t+@Hy}q-gqViY%4OBi7Dy> zlPVn8^vuE+d&5n*HjtNRk`bz}U?C5ZAatUFqnJf=ZliGPY*Ou54p_dAd1iVtilcV+ zxS3WLUf%HdWEc*ndehqa)J49(q0}O*LR>qU-L&`4(0C$o%}(6$z83PGk&^`Zb#)50n!x7rJa zOh@zUfvnzCmpkVZ#<)&shHuny892mYmW+KaM;2s?&cW0YJN>q4x*PoNjbY8EHq%Vc zd+HBQ!jnI)lc*S62rKzm9H)fe}-El)Vd_^XQU6<^prz@kCB3q!_K-^F90~^ro`I|Go%fk zqDrX1ZhtVpFUH9@!p6?@-n4o<>>V66c2;}g8h+|!-+s?l)pC5vo-A)CFmKP`p&oHH~1*jg24+ijuZcbzShJ{?R_ZF1Mra zx060J7DU5kI#=b3Tf9^R>bZKcIG}kDA)H2!cAyT+(KJWr-CK`QS=NcKH@EocBNVSx zQ8;@J1dTT7@*NnHpXl3jnM)Uk->2$lbWRYus*YuS+llcbJ=SE^x;W#@wZ~@LC|^?B zS=SW}8U4#qc$Mt-_?mo7_tk}G2kGy-&M4sgQ%4fTj4GwswFfo@_&@Kqn8rIxx-D+6 zD9-LQ7#)2Bxqh7RT*C~L#UPO|B|WnG#SWbQ`p2bNz~=lmJa-?@UCVO(-*l#xfKKeF0+7zbNuS}*C;$GP8~yW`9+v8_0>~zUwo{e<|4M z`~NCa%L;fEm62a$DYVt@{p;hvj@#S+Dr5X-q3*7=(YVlD$9lg5zTY3e7=f4l-=wG( z03ei~38+f1HA(*KYU}c#9Ax5ThO|e`* z`RB)jfxjx$O=xLA;(sJ&-3|KtTJtZj`SeKxAm=TZfJ|}F62gD0_TN5#`tO?3e-!HB zK&Zghf96P)1zz@l^_xeo^VmvBoMsIAMg8k<1C_z5_=`dXeX`loU;RTl;2-_r1-$IP zB-Z_76gDx2vK0V|FaO#fk5m4usPvzO!g4Ys;QK>$=^t(Tzp3$$rnnw(|C<{Bn;L&N zJO7&+|C<`X3iQ8K16Vb#l8Nr-a~nXu%b!EeLvZ;-dF#6#g_-|WZl_Zg(Qnc$=W+X`}7J88Jnzk=5)Kqk}GvhIdE!q?-vqMeY)5wQ+dxn z>fV?nRa-4%OF2DqaGnmvlMa_Hdh}Hc`FXOpI}c);xHFGoO}~ISUuk{tcE&jA=*S$O zHRy<3Z<&EOC_+Wy;RWf=?wodIt9fb-90{!!mC9NH%JM`Lh_}Fs?nv@BMG0U#HsS3~ z<=+M24!6&~Tbvj7ynYmVj%(==b#TZ`ssh^?``Uv`)(TN|48}??ZHX*$laM`WOkd{g z{o$fJjw_ZfKd@}9-QYkE`|#ka&-_?%Go`r4u`-2SJL+L%IBC_iK4sC14Z>~m;&7K= z$&{hyKjK(b7}773W%-02{f+O1&>j+1vV7UF8(&R$tIDtS#F&^$JKNzxXFDKl9UY9A zd+@IN?<{~n4Gr6km2!L1Owv{L$*^ViR4*CL&JEG z+hw74_3iW&c!j(0#r}Mn$fP7IwBSv|-eTm0XU#oD@cXWq!=ut}Tx|s^Fmk}VzWMls zPMm+-c6*P%@tdQSNp{zbcta_bvYA;3efEmMhR6#Xs zb&Ha11a>w#GY&Hj-wK9EHHcv}b&XImc*hTJTmgzAn9XkTuwULlH-+e~Mi&(}c`FJx zKh5@XTNoaEc%tyOtGs%jVaFIUaxi(}5x~l107v!+JW#Cnsz6j6+inHz;3A`kW?c~G z1sk^xt;q#muf@ZB2GtG`-!_8%-(I+EHh_!?WboixLdfez{JNenhGt%A61pHUFnXhg24fVf(gE$-S1APLNG*b2c@}%ZjMCM}1YQu~^3{*4pd8;_R zBZ#$bNAk5J67F?_0%X9{Ga7p?T0-Dbv{1RET;HYXd|n_FN83>s8v}}DY5!#kMpUW z%Q`!DS=C4g-(tT&NcKrc;C|6a#nd_^kYJhb0^X#{c$HkCi$sU!Zy1IbKzB3xa{ATA zGQXIn_G;@uD`KUs!e8<$WS?jzZ%baRipiwv6nDej_gca=1*JDMt{w`_>VMcN@imNd z)+pKjl{t+@Z#lNR^w3Q0+rt7t!W{2#mJ5F{C7?4FedR;>dJy{uo!!+32e#TDua3)^ zK&mnQx;b`VM7D;5GD+lXfM6E( zj`E`1Y?y0F+#Z)MQcAgGBz8kJ)xJ5;udRgpx3`{f^wOxBK_JBw!|8^Q9F0|O!I`qv zrR8{cQ9pO}*mWUL@(*G%7TTq>n(3&h?+m{8cyt@`3KQNqOhyZVj7f-RYNKM0kwXo| zN|lL%3+b<uVpaKs1@yDEDy2yzQM}oC#d<)Ugodu z&&#**FNRAE$Bc;YioF}y?4{(Uu<^pE)W04(rw41*)*acL?qnLaUwU*aDO;6FbRZ8< zAyu!H8)Vj#YS6V-KOzNGZM5paiyOVu!h03ZUu9nC2v%66pTRX(ght3#jEs?e)sdN~ z^OwBNK7)4b+ZVL96kpq#tkd&IPBK}J50@s= zo3V>{BMsTa9PwTy?un(&O^0#EOW;e|*RrtCYf4_3ptm> z%GZ!|A#wdHSL!<4V@im|K z^!36M8{FMa#AN*~Y4c+$mNFjM9$k59v~vU`*RX~!vAQ-3Um{_CuKiY$5_ty>p^Ryk zPw_P>RyQ(9ya`{Vwx&CKTqbH~twhp>Xk|D-I>h}6kRInlmuKlvOP1JRz5)fc_Mm*3 zWn3}3tB!;>Fzz?cd2#|>hKF#m(&vxoNfId;Bk=~Y#K$aoFS4bg$A~2)Pkt$$m5TEt z9gpt4a@#1zG^E*Hc!aACV2LY*qWHms^N2g|Ao`1+vaPJyaJsb}M%cPL;)a|7nAGu7 zjXlp~bYc!CO2wk#Z0oOSo-|NlnDg_B!zBV9^-r$TALmDC7RJKrmFM1wmlIB7HzcRx{&IGAd7n(pEAz4t10&YKj(T0&7)s#RY-Wg*%k zMlgAWdm4(+$9Mht0#xAInGOJE(Sy6)R{XI4P5QTk?s#X0VWQ`S$&&pB1YO!^>IG}R zq;Afi07iorSj10mAkTZ-vmWlkKXGOvc&Vtt&yyDGt(w*0BzJ`eXNNU4g%fLwqOA{g zG`{PN=&B8Lc4}5m8`*Xye(q+dq%#C}J-juY*?%tOu`B$f>*Q*oPUqu$MEgjT^DoJ< zEmVR7B!>J^d(nF3Qe0yWpH>+$L^5KTRLBz|^=5b)PZ_d;Lz()0hQ zp2iCSJwVq%@Fc|3j{Q`p{M2dncdZhWXdB}1uYk^S0_eA-wo{{V!`HA%&9g$YeWjly zQCBTSH$I=nSm$uqetFgaT@N+%JtiKdyDMFFnw7_MA>Np$m2Ly>dJM3vuIQzmAqUQdcO^y5p#_ zsXiNCM8^;lxAfeK^L-6w@f2qaS4u8$rP1U7|EC7UmDa$@4MZM)PI7RcLF+QAQT+uE z@3?5Q?!&il|JazrB9p^HKhcw3_hA#_V_dD;($z_Q<1`dKM4xU-!}gj2m!R+Kx9P}0 zPvul(fucvc{E4R|`{YZZVS(W8Eml6b7Av`mYe(@y&03R4`IBvr+bkS3jvuz{yRV!b z0+C^pHWAb4xnnl=w_ySmD|5-Xx9Logza-z$J(MMwWtz#Q^sA$74@p01hIzZm+tySy z)Mgfg%7#AL+xf^jnYRbf=c(EcH7&$2n=<2C3aJgw{9nM9NbKIf0UK+Dmzn=FfpdT`!&Sf^u150y=p|1Shi_N|L z7p(Pp@8!MbF zVhcMWJO8?@O})zM7*)UQJUSW?C)oW_TP>RmzETpD!z=ar5U?k0{?RyXalCx$(=*0* zx=O`IbrMp!H^PIEZ(j9|YYoo|qBrj)+L@a6p9ap=$j=hrEjy*SbQtG^%yJ1Fv#gcL zVlI(QvGkkcVMj0f+#Q+KQ6+fX(G6^t)OU+sgH2NhpBq7D+WB|l0`{X}`j~Zwu%ni$ zWSSyH9jU}oT0|VHP)(QKO68fjV2#1>7!j#=)kQcQWV%eecDqq7QdjP2)yNutzxDEj z&&q}xfDS^Gdfc_@9*|yG1VepyI9=~jMl(M0 zL+?PJ*QUnUj#QYty2gHX+>*sd(#briK1j@N)|C(}f?YJ9j?pHM-J9IRRtA?Wi$gZ> zxViDZ!L8ZOTV2vky_{b*zqU`1A26l9^l(vxtq&xoxa&+lWhtG}*Hs@8jb`&9YTtgD zd8q6y&4g5R??#qb|1GdQ@z5zT0;%Fw>KxS=JielN)&a<+IPEywXK^>m*&R&pRa9VL zCzr>IpW%HWwtHjQpvbRq)){P5!4~c+VD9dScWgLyxRql(Nc$zX*U)62B3zdNmD(fMLLPqgl(i|uE(L-_qX14{j(dpJQhwS63! zGdmG9N@t{*QSE>4H}f!8#!YUmYRlU{*cQ>(-KFgd+cfROALD#8CUWxIQ=Zb)#G9Ov zK40=Xo$ScVGNm?W%rrC^mU!8d& zOAS(?m5ubSXG}Jkt`kXPyrQnnI?-ACxMlhGpS>$77$Dmx;7b1CqDqwvwp#q+!3pTF zH*JJY=o(3`TT^QeXi>}iJu@T-Nt{$2JNEd{&>s!fFr4ozU17Z1X)JF6BC*TV)1TGf z>W?@t61EDsn3-KCv9+VWbNZ58PQc4JfL8g`0a)lCGQU#g>6jSTym@&O+bAC zfhU6yky(;ieb48`Yc>!mWyxS+n3z`(0{bh7OV(0O~MJs?A_1}*>>=!w49NXBOr-_Z6T(O z$<^6^3Od?&!d9UyuB5YH^+poUYvR7P?o&C-pYy|>*m>;PS31iUIZF=5?elH{4I8j> ze9rWv8r*dRLVBKWQlxcssfe(>sEB7*PM|H7vwDf(+#tVjeNaQSNVL$XUI0X#$*n~p zzHp#*DS+0sctK*U>#)Uh69}hOWZwoJSIcJuqyms z^z7ENXrbEQzSlyP*XLv6S!%lP|1=D@sMwEK7gZPTJN_;kazliY*IxJYqtUPa zo12m=9X9!tkFwfC4#)8dM|+%Hty8|>;u^dT%aK5%C{ZPx7t z3kdMIYy%@!5Y!N_-O+st-WZUP54tC->|VR_DV8PNWF5DkZ4+d!r=W%+6pJx7>edr` z2XSt%`+RS7fhH{P;jr_59+CS3!`jM8z2(IC6*hvEk6wpr2X$3)aj=k&v{a!z@9gWD zovmz8l+&=*ve72WIMv90Q^+HPmkCosmoF4*3Z>1RGkpiF3vN@aN%u%u_7M z%1`1<0`G~ahFwm>a927Q*A8s7YF*fM>%zHk{K#iRi;cQF=M%GN1(V(9(@u9R!hRBC zc^`8QLv(6>es8Gw&f3qS`}+OC+ikk!q?gWk!J8~EURqC@5j)5h>}VmTM7Mei{nKDQ zf8#k0+~3)Hm>wl}IQ+DG&ZjJNRw#!^(W7xD2&BPxhqeIImVg;&rIQ(0U7m&}Ikz98 z1c2?-T2C>}GpUi*^2asj8OVjD8G~7?m0%l}a2C(QsKrL=s(lScL1hHQIQrfG`7c6Q zoy^R231^Rrov9xyypXf1+`IQ(ZGLW`YY$I&$p{jTg=Y$_C!y(ZsD)&OKRTYQ@6!2v zq1Vgz@zPc8e28w#lLLbm*oPCjbbDQ$l97jwjg+^Mlf~mUB-rU>+p%)fnmGf*&4%Hj zo~xUS25eOqLVz4@lDsuhaQnz}HdkX~qh3AeA|IsIAnv>D1FUYFM-G<>uB+8hGykYj4C0+b9B@!RH8QjfUSiFTqe8Bd7ZOSmCI`;L$L&gsQhy zr}p65duwGQx$4vs`BHallPoKCCW21ofg|3-LvAoN5*o4P7BwmhxZ2{^enIrM<6a{( z+iOAKxc{mMI2-RK0(N76HAk|6Ljo9Dj*~H+ea(!;%S-D{XOl5k=D#l5&&=Z|$s=eOg^nrKPlXI-|a)YPvNeOB(%X9MXm^ya-Ez$7<$qui=&zC0riC zmL(E5-^k8Qg|S}}E@nSEbq!|%Zwxs)hNDWN#&~5FpxB#AUQWvqRjYg|uBC0W8iR^l zQQqIO_i>Krzw=_+imsMBS`iECv5rT@-kMni=4VEk)zyLQ5uUL_tu;SSr&5ez_&ObZ zEX*~r?sn3W#Sg66hd(|zCko;1Fv(DKa0w)P&~Kq#3#|_TA*xOeM+?wtK78E$G{|zR zzHc>ZXOY@n3UYFRV(R4Tzz8kUxpx#NgV@FBlG!YgECE7Rj7Jz3yrml-6*!Cup>_3V zbFl>gJR`KZA0(j5wt*4%DH<4K3Xb#=F`bpy z5pdsei@vQi=lc$XAk-u_r;U2W2E%&b(opnxb4VAVB5kQKj3$-nOl2xc#_2bZ{q2(s z&P(BkE(4lRmjHxb`{-I}=B^r6ml7@Xxa`dM7c!CY?Bc|E*^W^=3FgGfzP0>QNvcJXZ!%H(fv~=ed5T@BVcyjk&}8yL><1 z8XX9BN1x>B@@v;_?hsrCztsc$+uDWS^~})*z@KA6oF31|O8-H1)B*g9XS$ff@2gb* zU_AglnD(zQ7xdtrX5RmJ(@m+rVsG>+Q6<&?%FzIIzI^asvv2>&-h^{K8Uuo=fBnt_ zwZAIV&3xy8`rnHG|E$Muz+Yf4_aGIGC4jc_KOYBf6a4}nvo~ zqvy{LfOr2Z_9h+A-}yffFsy&Tr~mezKY*a1UlvGx+y7`=G~HjZH?-C-3x1RM|3s%A zm;6yxyyEOCFPyBn0|NP=-;DYS`D-iUgL<688|GjN*K>iX- z6Q{ht`TLs4Kl|hEi@z$==TT_$%zw1)smNc9!Y@KodTNaS=(*qZc&i84ga4bL{qO8e z!5H;1>A!PL|C<{B)*f>In;QS$O^s7BtS;rkO!9A$KNBL}SaV%X<37zcyYnPiYy9SmLm6Ar|txZVJ&$7g2Ve8Qy(sCR!D!8q070tIJJ6s z-KCEo14d(JHum=W8|6Q)C%fBc@-Kh;8v^GOFk*ySW76|mHNYK{L`q`kv+EX@CMyZ9Cz}1a9z+8Cjcd_hqJRF zIepWwwYMM0J$XB#l(ytV{{QP2q;OcYRgB6cCcex-ilkbc&IGwFjmqEaRBYO4{TcqM zMy!8gDRM%l(pTiN9;qmK0zySZ5So(z(cWl)GQK*o5l3rB7hGSneLFWxCP%^9%j7-4 zLXh*sF;3yUVloQ53M^;EnR9BCoEtR!VSSqLk0mSx2Y`{8gXd@Ag+?L2*9pOgyYD0k zijSSf^-0?MbNKazo#1`4EoRbuS>8E)mL&dP!{hl`^cOPLF10UJ2lp@9VKS0GqqS0< zyT4`J+fy`Y38gx;8qJxL+)mHxlX*0e={5eal*ptdoZ{GETatk`g&~tshWg0M>%ClS z)l_GBh$6JgJq*yQE#Sn|Yq^Cnu?o|v5| z4ckoZG2Jt~;D4wygDeKLBUPxXFD4$shW$g#L8f3+t4>jira2t6TI5;@X&d_;_ zw=-t9FjkVCWPjPd;}=2JV5DzBX5RRfvn+x7$Xq@zrKm@vqAZ`MxSwbV!=87|FQ zC*KdmW@Z2mJJrsI#GPIf~ir zW-Ko)4M5AVY$Vn(@i7nC3y(|LhzKJX{YD~L>1%Jj%sx!*Z)u=9w~=i6ITJ3p%qHXb)qN)6JyoKlcm7>cg+0i6)=zwG_k8s zNMHQnzs%gIiWFq1sCw}k2(8ke&{_|ID%3~k?4%??|j3kh31 z!%8SXUk?=}t7&Q&GRN68A#c4LB&}RG15ap(h$6E6N5iX*=MmY55y!fng%STz;iEgt zLMpqGsARQ2B8$RLLpkO$>xTY*P97MBZg`Qb^4J}}Hla~hhlPsRQrlzC+{I0Ok!P*p zYiP6E(y>rX3;E)V`@z+eD=szvEBz^}tHVr9I94H(K#g$dYC!LYk4Y5BY|{_P@_U`- ztmTvHVs*dEGFupr-TdIx=a2AXP6*J=sh&wex8vw^Vu-qb+m;%V-RGHn-k1E(>oyb< zBMfE|lU^EYWX}8QmaLFjH;Q!D1oVERC%rvO6qm;WsV;6++eXfXg3AAqYSu86Kufyr6b&c z&XbzJX2u==3M~N{sfjb@JbJl20>uUfT7duyN6`CA;YI}xv|E@!`S3S7U0c_l;sV$$f zI?DT@dj#nIA<)^CQ=pcFxIRn(TjC|85x#X=nnO@hk=LUwH~$ptPnfeva)OJC{z|Kl zpp#31Z3#rX1JN;r?pe5y1iE+%QsY5;fbcj+NWj+UM)e>JfUxlNEFHTA(M-nI)y*&j z9r%W9Jf2<;i>@20o0;%+!xkLnKsA{GsW?Jd3Ei%=1u~F=6eNgvLiCXrKsJdqi76ut z7!7RTR;B@89KFu~1fH&bF6*2UngBPSUkm^M diff --git a/htdocs/install/doctemplates/websites/website_template-style01.zip b/htdocs/install/doctemplates/websites/website_template-style01.zip deleted file mode 100644 index 100e66ad6b2a9be304f5a0adbac7a22a04d37d7d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16436 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%0D0%#(6iSoIgJ5ldy?g#>7L{attf{+)Ov0XP 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'kAIl^wUJCI?T*y=jxR-;0!Ml80_GmftyM3(f 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 literal 0 HcmV?d00001 diff --git a/htdocs/install/doctemplates/websites/website_template-style02.zip b/htdocs/install/doctemplates/websites/website_template-style02.zip new file mode 100644 index 0000000000000000000000000000000000000000..11116bcfc648ebc7a11d308b528dffd227668ced GIT binary patch literal 15973 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 Date: Fri, 22 Jul 2022 10:35:54 +0200 Subject: [PATCH 255/826] fix php 8 warning (and error) --- htdocs/core/lib/fourn.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/fourn.lib.php b/htdocs/core/lib/fourn.lib.php index 2fd4ce3799a..59a16164f97 100644 --- a/htdocs/core/lib/fourn.lib.php +++ b/htdocs/core/lib/fourn.lib.php @@ -222,7 +222,7 @@ function ordersupplier_prepare_head(CommandeFournisseur $object) $h++; $head[$h][0] = DOL_URL_ROOT.'/fourn/commande/info.php?id='.$object->id; - $head[$h][1] .= $langs->trans("Events"); + $head[$h][1] = $langs->trans("Events"); if (isModEnabled('agenda') && (!empty($user->rights->agenda->myactions->read) || !empty($user->rights->agenda->allactions->read))) { $head[$h][1] .= '/'; $head[$h][1] .= $langs->trans("Agenda"); From 0ee6e92dc0286ed9427cb446cadf63a45052d6e0 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Fri, 22 Jul 2022 10:51:28 +0200 Subject: [PATCH 256/826] fix: display message only if change --- htdocs/fourn/class/fournisseur.commande.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index ce1fffba01e..74ef2ff7ce2 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -1830,7 +1830,7 @@ class CommandeFournisseur extends CommonOrder // Predefine quantity according to packaging if (!empty($conf->global->PRODUCT_USE_SUPPLIER_PACKAGING)) { - $prod = new Product($this->db, $fk_product); + $prod = new Product($this->db); $prod->get_buyprice($fk_prod_fourn_price, $qty, $fk_product, 'none', ($this->fk_soc ? $this->fk_soc : $this->socid)); if ($qty < $prod->packaging) { @@ -1839,9 +1839,9 @@ class CommandeFournisseur extends CommonOrder if (!empty($prod->packaging) && ($qty % $prod->packaging) > 0) { $coeff = intval($qty / $prod->packaging) + 1; $qty = $prod->packaging * $coeff; + setEventMessage($langs->trans('QtyRecalculatedWithPackaging'), 'mesgs'); } } - setEventMessage($langs->trans('QtyRecalculatedWithPackaging'), 'mesgs'); } } From 762cea241612ed007c90b4412786495cbfb8d300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?This=20Charl=C3=A8ne?= <1179011+defrance@users.noreply.github.com> Date: Fri, 22 Jul 2022 10:51:45 +0200 Subject: [PATCH 257/826] php V8 fix warning --- htdocs/fourn/commande/card.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index 67b8eb75fb4..8da9241d6c7 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -555,13 +555,15 @@ if (empty($reshook)) { $ref_supplier = $productsupplier->ref_supplier; // Get vat rate + $tva_npr = 0; if (!GETPOSTISSET('tva_tx')) { // If vat rate not provided from the form (the form has the priority) $tva_tx = get_default_tva($object->thirdparty, $mysoc, $productsupplier->id, GETPOST('idprodfournprice', 'alpha')); $tva_npr = get_default_npr($object->thirdparty, $mysoc, $productsupplier->id, GETPOST('idprodfournprice', 'alpha')); + if (empty($tva_tx)) { + $tva_npr = 0; + } } - if (empty($tva_tx)) { - $tva_npr = 0; - } + $localtax1_tx = get_localtax($tva_tx, 1, $mysoc, $object->thirdparty, $tva_npr); $localtax2_tx = get_localtax($tva_tx, 2, $mysoc, $object->thirdparty, $tva_npr); @@ -667,10 +669,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { From bd0b28d30a4fbced2a0bcca6096e80c8bf453b00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?This=20Charl=C3=A8ne?= <1179011+defrance@users.noreply.github.com> Date: Fri, 22 Jul 2022 11:00:06 +0200 Subject: [PATCH 258/826] fix special_code PHP V8 by adding on addline fct --- htdocs/fourn/class/fournisseur.commande.class.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index 3212766a573..5c5ed88aa43 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -1432,7 +1432,7 @@ class CommandeFournisseur extends CommonOrder } - $this->special_code = $line->special_code; // TODO : remove this in 9.0 and add special_code param to addline() + //$this->special_code = $line->special_code; // TODO : remove this in 9.0 and add special_code param to addline() // This include test on qty if option SUPPLIER_ORDER_WITH_NOPRICEDEFINED is not set $result = $this->addline( @@ -1454,7 +1454,8 @@ class CommandeFournisseur extends CommonOrder $line->date_start, $line->date_end, $line->array_options, - $line->fk_unit + $line->fk_unit, + $line->special_code ); if ($result < 0) { dol_syslog(get_class($this)."::create ".$this->error, LOG_WARNING); // do not use dol_print_error here as it may be a functionnal error @@ -1745,9 +1746,10 @@ class CommandeFournisseur extends CommonOrder * @param string $origin 'order', ... * @param int $origin_id Id of origin object * @param int $rang Rank + * @param int $special_code Special code * @return int <=0 if KO, >0 if OK */ - public function addline($desc, $pu_ht, $qty, $txtva, $txlocaltax1 = 0.0, $txlocaltax2 = 0.0, $fk_product = 0, $fk_prod_fourn_price = 0, $ref_supplier = '', $remise_percent = 0.0, $price_base_type = 'HT', $pu_ttc = 0.0, $type = 0, $info_bits = 0, $notrigger = false, $date_start = null, $date_end = null, $array_options = 0, $fk_unit = null, $pu_ht_devise = 0, $origin = '', $origin_id = 0, $rang = -1) + public function addline($desc, $pu_ht, $qty, $txtva, $txlocaltax1 = 0.0, $txlocaltax2 = 0.0, $fk_product = 0, $fk_prod_fourn_price = 0, $ref_supplier = '', $remise_percent = 0.0, $price_base_type = 'HT', $pu_ttc = 0.0, $type = 0, $info_bits = 0, $notrigger = false, $date_start = null, $date_end = null, $array_options = 0, $fk_unit = null, $pu_ht_devise = 0, $origin = '', $origin_id = 0, $rang = -1, $special_code=0) { global $langs, $mysoc, $conf; @@ -1957,7 +1959,7 @@ class CommandeFournisseur extends CommonOrder $this->line->total_localtax2 = $total_localtax2; $this->line->total_ttc = $total_ttc; $this->line->product_type = $type; - $this->line->special_code = $this->special_code; + $this->line->special_code = $special_code; $this->line->origin = $origin; $this->line->origin_id = $origin_id; $this->line->fk_unit = $fk_unit; From 42809c62d2e97b75986fa431afa283854ce2bfee Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Fri, 22 Jul 2022 09:05:51 +0000 Subject: [PATCH 259/826] Fixing style errors. --- htdocs/fourn/class/fournisseur.commande.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index 5c5ed88aa43..97eb63d1c69 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -1454,7 +1454,7 @@ class CommandeFournisseur extends CommonOrder $line->date_start, $line->date_end, $line->array_options, - $line->fk_unit, + $line->fk_unit, $line->special_code ); if ($result < 0) { @@ -1749,7 +1749,7 @@ class CommandeFournisseur extends CommonOrder * @param int $special_code Special code * @return int <=0 if KO, >0 if OK */ - public function addline($desc, $pu_ht, $qty, $txtva, $txlocaltax1 = 0.0, $txlocaltax2 = 0.0, $fk_product = 0, $fk_prod_fourn_price = 0, $ref_supplier = '', $remise_percent = 0.0, $price_base_type = 'HT', $pu_ttc = 0.0, $type = 0, $info_bits = 0, $notrigger = false, $date_start = null, $date_end = null, $array_options = 0, $fk_unit = null, $pu_ht_devise = 0, $origin = '', $origin_id = 0, $rang = -1, $special_code=0) + public function addline($desc, $pu_ht, $qty, $txtva, $txlocaltax1 = 0.0, $txlocaltax2 = 0.0, $fk_product = 0, $fk_prod_fourn_price = 0, $ref_supplier = '', $remise_percent = 0.0, $price_base_type = 'HT', $pu_ttc = 0.0, $type = 0, $info_bits = 0, $notrigger = false, $date_start = null, $date_end = null, $array_options = 0, $fk_unit = null, $pu_ht_devise = 0, $origin = '', $origin_id = 0, $rang = -1, $special_code = 0) { global $langs, $mysoc, $conf; From 50e1597ef1d89a5dfa1604b780050c1a96a69563 Mon Sep 17 00:00:00 2001 From: Chl Date: Fri, 22 Jul 2022 19:46:05 +0200 Subject: [PATCH 260/826] FIX #20476 migration postgresql 13.0.x to 14.0.x packaging type --- htdocs/install/mysql/migration/13.0.0-14.0.0.sql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/install/mysql/migration/13.0.0-14.0.0.sql b/htdocs/install/mysql/migration/13.0.0-14.0.0.sql index 2ec43548bb6..44b1a6b5185 100644 --- a/htdocs/install/mysql/migration/13.0.0-14.0.0.sql +++ b/htdocs/install/mysql/migration/13.0.0-14.0.0.sql @@ -85,7 +85,8 @@ UPDATE llx_const set value = __ENCRYPT('eldy')__ WHERE __DECRYPT('value')__ = 'c DELETE FROM llx_user_param where param = 'MAIN_THEME' and value in ('auguria', 'amarok', 'cameleo'); ALTER TABLE llx_product_fournisseur_price ADD COLUMN packaging real DEFAULT NULL; -ALTER TABLE llx_product_fournisseur_price MODIFY COLUMN packaging real DEFAULT NULL; +-- VMYSQL4.3 ALTER TABLE llx_product_fournisseur_price MODIFY COLUMN packaging real DEFAULT NULL; +-- VPGSQL8.2 ALTER TABLE llx_product_fournisseur_price MODIFY COLUMN packaging real DEFAULT NULL USING packaging::real; -- For v14 From b4d4c42cfb13643714904be9ad074972194bc384 Mon Sep 17 00:00:00 2001 From: Chl Date: Fri, 22 Jul 2022 21:10:23 +0200 Subject: [PATCH 261/826] FIX #20476 discrepancy between MySQL & PostgreSQL default value --- htdocs/install/mysql/migration/12.0.0-13.0.0.sql | 1 + htdocs/install/mysql/migration/13.0.0-14.0.0.sql | 1 + htdocs/install/mysql/migration/14.0.0-15.0.0.sql | 1 + 3 files changed, 3 insertions(+) diff --git a/htdocs/install/mysql/migration/12.0.0-13.0.0.sql b/htdocs/install/mysql/migration/12.0.0-13.0.0.sql index a632a32271b..4a48e8b97fd 100644 --- a/htdocs/install/mysql/migration/12.0.0-13.0.0.sql +++ b/htdocs/install/mysql/migration/12.0.0-13.0.0.sql @@ -568,6 +568,7 @@ INSERT INTO llx_c_socialnetworks (entity, code, label, url, icon, active) VALUES ALTER TABLE llx_product_fournisseur_price ADD COLUMN packaging varchar(64) DEFAULT NULL; ALTER TABLE llx_product_fournisseur_price MODIFY COLUMN packaging varchar(64) DEFAULT NULL; +-- VPGSQL8.2 ALTER TABLE llx_product_fournisseur_price ALTER COLUMN packaging DROP DEFAULT; ALTER TABLE llx_projet ADD COLUMN fk_opp_status_end integer DEFAULT NULL; diff --git a/htdocs/install/mysql/migration/13.0.0-14.0.0.sql b/htdocs/install/mysql/migration/13.0.0-14.0.0.sql index 44b1a6b5185..b335cf7f3f6 100644 --- a/htdocs/install/mysql/migration/13.0.0-14.0.0.sql +++ b/htdocs/install/mysql/migration/13.0.0-14.0.0.sql @@ -87,6 +87,7 @@ DELETE FROM llx_user_param where param = 'MAIN_THEME' and value in ('auguria', ' ALTER TABLE llx_product_fournisseur_price ADD COLUMN packaging real DEFAULT NULL; -- VMYSQL4.3 ALTER TABLE llx_product_fournisseur_price MODIFY COLUMN packaging real DEFAULT NULL; -- VPGSQL8.2 ALTER TABLE llx_product_fournisseur_price MODIFY COLUMN packaging real DEFAULT NULL USING packaging::real; +-- VPGSQL8.2 ALTER TABLE llx_product_fournisseur_price ALTER COLUMN packaging DROP DEFAULT; -- For v14 diff --git a/htdocs/install/mysql/migration/14.0.0-15.0.0.sql b/htdocs/install/mysql/migration/14.0.0-15.0.0.sql index a945f078bbb..7eb3403e3ed 100644 --- a/htdocs/install/mysql/migration/14.0.0-15.0.0.sql +++ b/htdocs/install/mysql/migration/14.0.0-15.0.0.sql @@ -38,6 +38,7 @@ ALTER TABLE llx_product_fournisseur_price ADD COLUMN packaging real DEFAULT NULL; -- VMYSQL4.3 ALTER TABLE llx_product_fournisseur_price MODIFY COLUMN packaging real DEFAULT NULL; -- VPGSQL8.2 ALTER TABLE llx_product_fournisseur_price MODIFY COLUMN packaging real DEFAULT NULL USING packaging::real; +-- VPGSQL8.2 ALTER TABLE llx_product_fournisseur_price ALTER COLUMN packaging DROP DEFAULT; ALTER TABLE llx_accounting_bookkeeping ADD COLUMN date_export datetime DEFAULT NULL; From 8c5554a6e6c853411acf1f9f9076aaebea82fcb0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Jul 2022 11:09:59 +0200 Subject: [PATCH 262/826] Add option ACCOUNTANCY_DISABLE_CLOSURE_LINE_BY_LINE --- htdocs/accountancy/bookkeeping/list.php | 22 ++++----- .../accountancy/bookkeeping/listbyaccount.php | 2 +- htdocs/accountancy/closure/index.php | 45 ++++++++++++++----- 3 files changed, 46 insertions(+), 23 deletions(-) diff --git a/htdocs/accountancy/bookkeeping/list.php b/htdocs/accountancy/bookkeeping/list.php index 90adc84dfd5..bc229dd69f7 100644 --- a/htdocs/accountancy/bookkeeping/list.php +++ b/htdocs/accountancy/bookkeeping/list.php @@ -197,7 +197,7 @@ $arrayfields = array( 't.date_creation'=>array('label'=>$langs->trans("DateCreation"), 'checked'=>0), 't.tms'=>array('label'=>$langs->trans("DateModification"), 'checked'=>0), 't.date_export'=>array('label'=>$langs->trans("DateExport"), 'checked'=>1), - 't.date_validated'=>array('label'=>$langs->trans("DateValidationAndLock"), 'checked'=>1), + 't.date_validated'=>array('label'=>$langs->trans("DateValidationAndLock"), 'checked'=>1, 'enabled'=>!getDolGlobalString("ACCOUNTANCY_DISABLE_CLOSURE_LINE_BY_LINE")), 't.import_key'=>array('label'=>$langs->trans("ImportId"), 'checked'=>0, 'position'=>1100), ); @@ -769,16 +769,18 @@ if ($action == 'export_file') { $form_question['separator'] = array('name'=>'separator', 'type'=>'separator'); - // If 0 or not set, we NOT check by default. - $checked = (isset($conf->global->ACCOUNTING_DEFAULT_NOT_NOTIFIED_VALIDATION_DATE) || !empty($conf->global->ACCOUNTING_DEFAULT_NOT_NOTIFIED_VALIDATION_DATE)); - $form_question['notifiedvalidationdate'] = array( - 'name' => 'notifiedvalidationdate', - 'type' => 'checkbox', - 'label' => $langs->trans('NotifiedValidationDate', $langs->transnoentitiesnoconv("MenuAccountancyClosure")), - 'value' => $checked, - ); + if (!getDolGlobalString("ACCOUNTANCY_DISABLE_CLOSURE_LINE_BY_LINE")) { + // If 0 or not set, we NOT check by default. + $checked = (isset($conf->global->ACCOUNTING_DEFAULT_NOT_NOTIFIED_VALIDATION_DATE) || !empty($conf->global->ACCOUNTING_DEFAULT_NOT_NOTIFIED_VALIDATION_DATE)); + $form_question['notifiedvalidationdate'] = array( + 'name' => 'notifiedvalidationdate', + 'type' => 'checkbox', + 'label' => $langs->trans('NotifiedValidationDate', $langs->transnoentitiesnoconv("MenuAccountancyClosure")), + 'value' => $checked, + ); - $form_question['separator2'] = array('name'=>'separator2', 'type'=>'separator'); + $form_question['separator2'] = array('name'=>'separator2', 'type'=>'separator'); + } $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?'.$param, $langs->trans("ExportFilteredList").' ('.$listofformat[$formatexportset].')', $langs->trans('ConfirmExportFile'), 'export_fileconfirm', $form_question, '', 1, 300, 600); } diff --git a/htdocs/accountancy/bookkeeping/listbyaccount.php b/htdocs/accountancy/bookkeeping/listbyaccount.php index d638a7c0c84..bb864fc39e3 100644 --- a/htdocs/accountancy/bookkeeping/listbyaccount.php +++ b/htdocs/accountancy/bookkeeping/listbyaccount.php @@ -166,7 +166,7 @@ $arrayfields = array( 't.credit'=>array('label'=>$langs->trans("Credit"), 'checked'=>1), 't.lettering_code'=>array('label'=>$langs->trans("LetteringCode"), 'checked'=>1), 't.date_export'=>array('label'=>$langs->trans("DateExport"), 'checked'=>1), - 't.date_validated'=>array('label'=>$langs->trans("DateValidation"), 'checked'=>1), + 't.date_validated'=>array('label'=>$langs->trans("DateValidation"), 'checked'=>1, 'enabled'=>!getDolGlobalString("ACCOUNTANCY_DISABLE_CLOSURE_LINE_BY_LINE")), 't.import_key'=>array('label'=>$langs->trans("ImportId"), 'checked'=>0, 'position'=>1100), ); diff --git a/htdocs/accountancy/closure/index.php b/htdocs/accountancy/closure/index.php index f02eda61bf6..a1d75440b56 100644 --- a/htdocs/accountancy/closure/index.php +++ b/htdocs/accountancy/closure/index.php @@ -112,6 +112,7 @@ if ($action == 'validate_movements_confirm' && !empty($user->rights->accounting- } } + /* * View */ @@ -178,20 +179,40 @@ for ($i = 1; $i <= 12; $i++) { } print '

'; -$sql = "SELECT COUNT(b.rowid) as detail,"; -for ($i = 1; $i <= 12; $i++) { - $j = $i + ($conf->global->SOCIETE_FISCAL_MONTH_START ? $conf->global->SOCIETE_FISCAL_MONTH_START : 1) - 1; - if ($j > 12) { - $j -= 12; +if (getDolGlobalString("ACCOUNTANCY_DISABLE_CLOSURE_LINE_BY_LINE")) { + // TODO Analyse is done by finding record not into a closed period + $sql = "SELECT COUNT(b.rowid) as detail,"; + for ($i = 1; $i <= 12; $i++) { + $j = $i + ($conf->global->SOCIETE_FISCAL_MONTH_START ? $conf->global->SOCIETE_FISCAL_MONTH_START : 1) - 1; + if ($j > 12) { + $j -= 12; + } + $sql .= " SUM(".$db->ifsql("MONTH(b.doc_date)=".$j, "1", "0").") AS month".str_pad($j, 2, "0", STR_PAD_LEFT).","; } - $sql .= " SUM(".$db->ifsql("MONTH(b.doc_date)=".$j, "1", "0").") AS month".str_pad($j, 2, "0", STR_PAD_LEFT).","; + $sql .= " COUNT(b.rowid) as total"; + $sql .= " FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as b"; + $sql .= " WHERE b.doc_date >= '".$db->idate($search_date_start)."'"; + $sql .= " AND b.doc_date <= '".$db->idate($search_date_end)."'"; + $sql .= " AND b.entity IN (".getEntity('bookkeeping', 0).")"; // We don't share object for accountancy + // Loop on each closed period + $sql .= " AND b.doc_date BETWEEN 0 AND 0"; +} else { + // Analyse closed record using the unitary flag/date on each record + $sql = "SELECT COUNT(b.rowid) as detail,"; + for ($i = 1; $i <= 12; $i++) { + $j = $i + ($conf->global->SOCIETE_FISCAL_MONTH_START ? $conf->global->SOCIETE_FISCAL_MONTH_START : 1) - 1; + if ($j > 12) { + $j -= 12; + } + $sql .= " SUM(".$db->ifsql("MONTH(b.doc_date)=".$j, "1", "0").") AS month".str_pad($j, 2, "0", STR_PAD_LEFT).","; + } + $sql .= " COUNT(b.rowid) as total"; + $sql .= " FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as b"; + $sql .= " WHERE b.doc_date >= '".$db->idate($search_date_start)."'"; + $sql .= " AND b.doc_date <= '".$db->idate($search_date_end)."'"; + $sql .= " AND b.entity IN (".getEntity('bookkeeping', 0).")"; // We don't share object for accountancy + $sql .= " AND date_validated IS NULL"; } -$sql .= " COUNT(b.rowid) as total"; -$sql .= " FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as b"; -$sql .= " WHERE b.doc_date >= '".$db->idate($search_date_start)."'"; -$sql .= " AND b.doc_date <= '".$db->idate($search_date_end)."'"; -$sql .= " AND b.entity IN (".getEntity('bookkeeping', 0).")"; // We don't share object for accountancy -$sql .= " AND date_validated IS NULL"; dol_syslog('htdocs/accountancy/closure/index.php', LOG_DEBUG); $resql = $db->query($sql); From 3ebf64de63fa0257f54c1372d6157f2efa5a4daa Mon Sep 17 00:00:00 2001 From: marc Date: Sun, 24 Jul 2022 11:57:42 +0200 Subject: [PATCH 263/826] Fix #21536 API Invoice Delete doesn't raise exception in some case --- htdocs/compta/facture/class/api_invoices.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/facture/class/api_invoices.class.php b/htdocs/compta/facture/class/api_invoices.class.php index a864168d161..6948ae850c7 100644 --- a/htdocs/compta/facture/class/api_invoices.class.php +++ b/htdocs/compta/facture/class/api_invoices.class.php @@ -666,7 +666,7 @@ class Invoices extends DolibarrApi } $result = $this->invoice->delete(DolibarrApiAccess::$user); - if ($result < 0) { + if ($result <= 0) { throw new RestException(500, 'Error when deleting invoice'); } From c3016c6175cdc7cf8d0535cf89ec22623e76511b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Jul 2022 13:44:47 +0200 Subject: [PATCH 264/826] Fix php8 --- htdocs/core/class/commondocgenerator.class.php | 13 +++++++++++-- htdocs/core/class/translate.class.php | 10 +++++----- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/htdocs/core/class/commondocgenerator.class.php b/htdocs/core/class/commondocgenerator.class.php index bee63613bca..d0b64fdca77 100644 --- a/htdocs/core/class/commondocgenerator.class.php +++ b/htdocs/core/class/commondocgenerator.class.php @@ -895,7 +895,12 @@ abstract class CommonDocGenerator //Add value to store price with currency $array_to_fill = array_merge($array_to_fill, array($array_key.'_options_'.$key.'_currency' => $object->array_options['options_'.$key.'_currency'])); } elseif ($extrafields->attributes[$object->table_element]['type'][$key] == 'select') { - $object->array_options['options_'.$key] = $extrafields->attributes[$object->table_element]['param'][$key]['options'][$object->array_options['options_'.$key]]; + $valueofselectkey = $object->array_options['options_'.$key]; + if (array_key_exists($valueofselectkey, $extrafields->attributes[$object->table_element]['param'][$key]['options'])) { + $object->array_options['options_'.$key] = $extrafields->attributes[$object->table_element]['param'][$key]['options'][$valueofselectkey]; + } else { + $object->array_options['options_'.$key] = ''; + } } elseif ($extrafields->attributes[$object->table_element]['type'][$key] == 'checkbox') { $valArray = explode(',', $object->array_options['options_'.$key]); $output = array(); @@ -945,7 +950,11 @@ abstract class CommonDocGenerator } } - $array_to_fill = array_merge($array_to_fill, array($array_key.'_options_'.$key => $object->array_options['options_'.$key])); + if (array_key_exists('option_'.$key, $object->array_options)) { + $array_to_fill = array_merge($array_to_fill, array($array_key.'_options_'.$key => $object->array_options['options_'.$key])); + } else { + $array_to_fill = array_merge($array_to_fill, array($array_key.'_options_'.$key => '')); + } } } diff --git a/htdocs/core/class/translate.class.php b/htdocs/core/class/translate.class.php index 94bd36799fc..c11f94fa047 100644 --- a/htdocs/core/class/translate.class.php +++ b/htdocs/core/class/translate.class.php @@ -904,11 +904,11 @@ class Translate * This function need module "numberwords" to be installed. If not it will return * same number (this module is not provided by default as it use non GPL source code). * - * @param int $number Number to encode in full text - * @param string $isamount ''=it's just a number, '1'=It's an amount (default currency), 'currencycode'=It's an amount (foreign currency) - * @return string Label translated in UTF8 (but without entities) - * 10 if setDefaultLang was en_US => ten - * 123 if setDefaultLang was fr_FR => cent vingt trois + * @param int|string $number Number to encode in full text + * @param string $isamount ''=it's just a number, '1'=It's an amount (default currency), 'currencycode'=It's an amount (foreign currency) + * @return string Label translated in UTF8 (but without entities) + * 10 if setDefaultLang was en_US => ten + * 123 if setDefaultLang was fr_FR => cent vingt trois */ public function getLabelFromNumber($number, $isamount = '') { From e7161edffe95e55744012c2620464b7690266121 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Jul 2022 15:11:00 +0200 Subject: [PATCH 265/826] Fix missing @ in dolEval --- htdocs/core/lib/functions.lib.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index bfb1e170078..dee765d174a 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -8611,7 +8611,7 @@ function dol_eval($s, $returnvalue = 0, $hideerrors = 1, $onlysimplestring = '1' } } elseif ($onlysimplestring == '2') { // We must accept: (($reloadedobj = new Task($db)) && ($reloadedobj->fetchNoCompute($object->id) > 0) && ($secondloadedobj = new Project($db)) && ($secondloadedobj->fetchNoCompute($reloadedobj->fk_project) > 0)) ? $secondloadedobj->ref : "Parent project not found" - if (preg_match('/[^a-z0-9\s'.preg_quote('^$_+-.*>&|=!?():"\',/;[]', '/').']/i', $s)) { + if (preg_match('/[^a-z0-9\s'.preg_quote('^$_+-.*>&|=!?():"\',/@;[]', '/').']/i', $s)) { if ($returnvalue) { return 'Bad string syntax to evaluate (found chars that are not chars for simplestring): '.$s; } else { @@ -9020,7 +9020,7 @@ function complete_head_from_modules($conf, $langs, $object, &$head, &$h, $type, if ($values[0] != $type) { continue; } - //var_dump(verifCond($values[4])); + var_dump($value.' '.verifCond($values[4])); if (verifCond($values[4])) { if ($values[3]) { From 481bd93ab821ba9fba9558242e4b6bde95c1677e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Jul 2022 15:12:08 +0200 Subject: [PATCH 266/826] Fix var_dump --- htdocs/core/lib/functions.lib.php | 1 - 1 file changed, 1 deletion(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index dee765d174a..38b60b9f17b 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -9020,7 +9020,6 @@ function complete_head_from_modules($conf, $langs, $object, &$head, &$h, $type, if ($values[0] != $type) { continue; } - var_dump($value.' '.verifCond($values[4])); if (verifCond($values[4])) { if ($values[3]) { From 99f632b3fff0004c77e06813ef18775467f39012 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Jul 2022 15:40:55 +0200 Subject: [PATCH 267/826] Add transaction db missing --- htdocs/core/actions_addupdatedelete.inc.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/htdocs/core/actions_addupdatedelete.inc.php b/htdocs/core/actions_addupdatedelete.inc.php index 506a1465fdc..4452c9a7eb8 100644 --- a/htdocs/core/actions_addupdatedelete.inc.php +++ b/htdocs/core/actions_addupdatedelete.inc.php @@ -134,6 +134,8 @@ if ($action == 'add' && !empty($permissiontoadd)) { } if (!$error) { + $db->begin(); + $result = $object->create($user); if ($result > 0) { // Creation OK @@ -141,14 +143,19 @@ if ($action == 'add' && !empty($permissiontoadd)) { $categories = GETPOST('categories', 'array:int'); $object->setCategories($categories); } + $urltogo = $backtopage ? str_replace('__ID__', $result, $backtopage) : $backurlforlist; $urltogo = preg_replace('/--IDFORBACKTOPAGE--/', $object->id, $urltogo); // New method to autoselect project after a New on another form object creation + $db->commit(); + if (empty($noback)) { header("Location: " . $urltogo); exit; } } else { + $db->rollback(); + $error++; // Creation KO if (!empty($object->errors)) { From c31a924812fa490b17696c97fd28a13bbee14ecf Mon Sep 17 00:00:00 2001 From: marc Date: Sun, 24 Jul 2022 16:50:08 +0200 Subject: [PATCH 268/826] The return code 0 is not an error but the serveur refuse to execute the request --- htdocs/compta/facture/class/api_invoices.class.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/compta/facture/class/api_invoices.class.php b/htdocs/compta/facture/class/api_invoices.class.php index 6948ae850c7..285d9d366f7 100644 --- a/htdocs/compta/facture/class/api_invoices.class.php +++ b/htdocs/compta/facture/class/api_invoices.class.php @@ -666,8 +666,10 @@ class Invoices extends DolibarrApi } $result = $this->invoice->delete(DolibarrApiAccess::$user); - if ($result <= 0) { + if ($result < 0) { throw new RestException(500, 'Error when deleting invoice'); + } elseif ($result == 0) { + throw new RestException(403, 'Invoice not erasable'); } return array( From 083b785ec873afa4877764e1c74a39b673606f9b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Jul 2022 20:13:48 +0200 Subject: [PATCH 269/826] Update combinations.php --- htdocs/variants/combinations.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/variants/combinations.php b/htdocs/variants/combinations.php index fd4f116f51b..f01e674c44a 100644 --- a/htdocs/variants/combinations.php +++ b/htdocs/variants/combinations.php @@ -69,7 +69,7 @@ if ($id > 0 || $ref) { $object->fetch($id, $ref); } -$selectedvariant = !empty($_SESSION['addvariant_'.$object->id]) ? $_SESSION['addvariant_'.$object->id] : Array(); +$selectedvariant = !empty($_SESSION['addvariant_'.$object->id]) ? $_SESSION['addvariant_'.$object->id] : array(); // Security check if (empty($conf->variants->enabled)) { From d622bfd7743e2c8decbc2e844f84617d1d9deb94 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Jul 2022 20:32:06 +0200 Subject: [PATCH 270/826] Update modulehelp.php --- htdocs/admin/modulehelp.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/admin/modulehelp.php b/htdocs/admin/modulehelp.php index e9e6333f54f..16500c62d59 100644 --- a/htdocs/admin/modulehelp.php +++ b/htdocs/admin/modulehelp.php @@ -506,7 +506,7 @@ if ($mode == 'feature') { $text .= '
'; $text .= '
'.$langs->trans("AddHooks").': '; - if (isset($objMod->module_parts['hooks']) && is_array($objMod->module_parts['hooks']) && count($objMod->module_parts['hooks'])) { + if (isset($objMod->module_parts) && isset($objMod->module_parts['hooks']) && is_array($objMod->module_parts['hooks']) && count($objMod->module_parts['hooks'])) { $i = 0; foreach ($objMod->module_parts['hooks'] as $key => $val) { if ($key === 'entity') { From 747c10f2ac60e4038057c3cafd81a45595b8415f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Jul 2022 22:14:11 +0200 Subject: [PATCH 271/826] Css --- htdocs/core/class/html.formwebsite.class.php | 5 +++-- htdocs/core/lib/cron.lib.php | 10 ++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/htdocs/core/class/html.formwebsite.class.php b/htdocs/core/class/html.formwebsite.class.php index 083e571cf35..720c447ce95 100644 --- a/htdocs/core/class/html.formwebsite.class.php +++ b/htdocs/core/class/html.formwebsite.class.php @@ -165,9 +165,10 @@ class FormWebsite * @param int $useempty 1=Add an empty value in list * @param string $moreattrib More attributes on HTML select tag * @param int $addjscombo Add js combo + * @param string $morecss More css * @return string HTML select component with list of type of containers */ - public function selectSampleOfContainer($htmlname, $selected = '', $useempty = 0, $moreattrib = '', $addjscombo = 0) + public function selectSampleOfContainer($htmlname, $selected = '', $useempty = 0, $moreattrib = '', $addjscombo = 0, $morecss = 'minwidth200') { global $langs, $conf, $user; @@ -190,7 +191,7 @@ class FormWebsite } $out = ''; - $out .= ''; if ($useempty == 1 || $useempty == 2) { $out .= ''; diff --git a/htdocs/core/lib/cron.lib.php b/htdocs/core/lib/cron.lib.php index b4c728fd611..c12109f3123 100644 --- a/htdocs/core/lib/cron.lib.php +++ b/htdocs/core/lib/cron.lib.php @@ -100,8 +100,14 @@ function dol_print_cron_urls() print '
'; + print "
\n"; + print ' '.$langs->trans("OrToLaunchASpecificJob"); + print '
'; $url = $urlwithroot.'/public/cron/cron_run_jobs_by_url.php?'.(empty($conf->global->CRON_KEY) ? '' : 'securitykey='.$conf->global->CRON_KEY.'&').'userlogin='.$user->login.'&id=cronjobid'; print img_picto('', 'globe').' '.$url."
\n"; print ''; From 6d3059d2a8156f2779040fd47ef3371aac6afe19 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 24 Jul 2022 22:20:41 +0200 Subject: [PATCH 272/826] Add type ip --- htdocs/core/class/commonobject.class.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index ba6007235f3..ad31e42a625 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -6868,7 +6868,7 @@ abstract class CommonObject $out = ''; } elseif (preg_match('/varchar/', $type)) { $out = ' 0 ? ' maxlength="'.$size.'"' : '').' value="'.dol_escape_htmltag($value).'"'.($moreparam ? $moreparam : '').($autofocusoncreate ? ' autofocus' : '').'>'; - } elseif (in_array($type, array('mail', 'phone', 'url'))) { + } elseif (in_array($type, array('mail', 'phone', 'url', 'ip'))) { $out = ''; } elseif (preg_match('/^text/', $type)) { if (!preg_match('/search_/', $keyprefix)) { // If keyprefix is search_ or search_options_, we must just use a simple text field @@ -7498,6 +7498,8 @@ abstract class CommonObject $value = dol_print_url($value, '_blank', 32, 1); } elseif ($type == 'phone') { $value = dol_print_phone($value, '', 0, 0, '', ' ', 'phone'); + } elseif ($type == 'ip') { + $value = dol_print_ip($value, 0); } elseif ($type == 'price') { if (!is_null($value) && $value !== '') { $value = price($value, 0, $langs, 0, 0, -1, $conf->currency); From 3262426b84c96ab22a9cf8a98fa9aac761b6525e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 25 Jul 2022 08:59:01 +0200 Subject: [PATCH 273/826] Trans --- htdocs/langs/en_US/install.lang | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/langs/en_US/install.lang b/htdocs/langs/en_US/install.lang index 6aee82bacec..135cb51a01b 100644 --- a/htdocs/langs/en_US/install.lang +++ b/htdocs/langs/en_US/install.lang @@ -213,3 +213,5 @@ ClickHereToGoToApp=Click here to go to your application ClickOnLinkOrRemoveManualy=If an upgrade is in progress, please wait. If not, click on the following link. If you always see this same page, you must remove/rename the file install.lock in the documents directory. Loaded=Loaded FunctionTest=Function test +NodoUpgradeAfterDB=No action requested by external modules after upgrade of database +NodoUpgradeAfterFiles=No action requested by external modules after upgrade of files or directories \ No newline at end of file From 1e282aaded86daa2f706712557e4e34ab0824bdd Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Mon, 25 Jul 2022 10:49:19 +0200 Subject: [PATCH 274/826] FIX : js injection in stockmovement.php --- htdocs/product/stock/massstockmove.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/htdocs/product/stock/massstockmove.php b/htdocs/product/stock/massstockmove.php index 85848942fbe..b2276befd63 100644 --- a/htdocs/product/stock/massstockmove.php +++ b/htdocs/product/stock/massstockmove.php @@ -336,11 +336,11 @@ if ($action == 'importCSV' && !empty($user->rights->stock->mouvement->creer)) { continue; } //var_dump($data); - $tmp_id_sw = $data[$i][0]['val']; - $tmp_id_tw = $data[$i][1]['val']; - $tmp_id_product = $data[$i][2]['val']; - $tmp_qty = $data[$i][3]['val']; - $tmp_batch = $data[$i][4]['val']; + $tmp_id_sw = dol_escape_htmltag($data[$i][0]['val']); + $tmp_id_tw = dol_escape_htmltag($data[$i][1]['val']); + $tmp_id_product = dol_escape_htmltag($data[$i][2]['val']); + $tmp_qty = dol_escape_htmltag($data[$i][3]['val']); + $tmp_batch = dol_escape_htmltag($data[$i][4]['val']); if (!is_numeric($tmp_id_product)) { $result = fetchref($productstatic, $tmp_id_product); From 2c1833fedfa7aa09d585c591319a674dc1afc10d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 25 Jul 2022 11:46:46 +0200 Subject: [PATCH 275/826] Doc --- htdocs/contrat/card.php | 4 ++-- htdocs/core/class/html.form.class.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php index 317aebecfd1..eb3a29bb3e9 100644 --- a/htdocs/contrat/card.php +++ b/htdocs/contrat/card.php @@ -1263,9 +1263,9 @@ if ($action == 'create') { $formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=".$object->id, $langs->trans("CloseAContract"), $langs->trans("ConfirmCloseContract"), "confirm_close", '', 0, 1); } elseif ($action == 'activate') { $formquestion = array( - array('type' => 'date', 'name' => 'd_start', 'label' => $langs->trans("DateServiceActivate"), /*'value' => $form->selectDate('', '', $usehm, $usehm, '', "active", 1, 0),*/ /*'socid', '(s.client=1 OR s.client=2 OR s.client=3)'*/), + array('type' => 'date', 'name' => 'd_start', 'label' => $langs->trans("DateServiceActivate"), 'value' => dol_now()), array('type' => 'date', 'name' => 'd_end', 'label' => $langs->trans("DateEndPlanned"), /*'value' => $form->selectDate('', "end", $usehm, $usehm, '', "active", 1, 0),*/ '', ''), - array('type' => 'text', 'name' => 'comment', 'label' => $langs->trans("Comment"), 'value' => '', '', '', 'class' => 'minwidth300') + array('type' => 'text', 'name' => 'comment', 'label' => $langs->trans("Comment"), 'value' => '', '', '', 'class' => 'minwidth300', 'moreattr'=>'autofocus') ); $formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=".$object->id, $langs->trans("ActivateAllOnContract"), $langs->trans("ConfirmActivateAllOnContract"), "confirm_activate", $formquestion, 'yes', 1, 280); } elseif ($action == 'clone') { diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 625791ea0d0..dda61ae72d4 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -4913,8 +4913,8 @@ class Form * @param string $title Title * @param string $question Question * @param string $action Action - * @param array|string $formquestion An array with complementary inputs to add into forms: array(array('label'=> ,'type'=> , 'size'=>, 'morecss'=>, 'moreattr'=>)) - * type can be 'hidden', 'text', 'password', 'checkbox', 'radio', 'date', 'select', 'multiselect', 'morecss', 'other' or 'onecolumn'... + * @param array|string $formquestion An array with complementary inputs to add into forms: array(array('label'=> ,'type'=> , 'size'=>, 'morecss'=>, 'moreattr'=>'autofocus' or 'style=...')) + * 'type' can be 'hidden', 'text', 'password', 'checkbox', 'radio', 'date', 'select', 'multiselect', 'morecss', 'other' or 'onecolumn'... * @param string $selectedchoice '' or 'no', or 'yes' or '1' or '0' * @param int|string $useajax 0=No, 1=Yes, 2=Yes but submit page with &confirm=no if choice is No, 'xxx'=Yes and preoutput confirm box with div id=dialog-confirm-xxx * @param int|string $height Force height of box (0 = auto) From eb463341b47c201881e353352aaa997ef2a4e2b4 Mon Sep 17 00:00:00 2001 From: Berton Anthony Date: Mon, 25 Jul 2022 12:17:02 +0200 Subject: [PATCH 276/826] ok --- htdocs/commande/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index ee25ea86eff..5d921c89e22 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -1217,7 +1217,7 @@ if ($resql) { if ($permissiontocancel) { $arrayofmassactions['cancelorders'] = img_picto('', 'close_title', 'class="pictofixedwidth"').$langs->trans("Cancel"); } - if ($user->rights->facture->creer) { + if (!empty($user->invoices->enabled) && $user->rights->facture->creer) { $arrayofmassactions['createbills'] = img_picto('', 'bill', 'class="pictofixedwidth"').$langs->trans("CreateInvoiceForThisCustomer"); } if ($permissiontoclose) { From e77c51eabbfbc90d67bddc4a573324653f4a38f8 Mon Sep 17 00:00:00 2001 From: Berton Anthony Date: Mon, 25 Jul 2022 12:18:07 +0200 Subject: [PATCH 277/826] conf --- htdocs/commande/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index 5d921c89e22..dbb99d0f993 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -1217,7 +1217,7 @@ if ($resql) { if ($permissiontocancel) { $arrayofmassactions['cancelorders'] = img_picto('', 'close_title', 'class="pictofixedwidth"').$langs->trans("Cancel"); } - if (!empty($user->invoices->enabled) && $user->rights->facture->creer) { + if (!empty($conf->invoice->enabled) && $user->rights->facture->creer) { $arrayofmassactions['createbills'] = img_picto('', 'bill', 'class="pictofixedwidth"').$langs->trans("CreateInvoiceForThisCustomer"); } if ($permissiontoclose) { From c4eccd262dac825df85fa7721e25c891b05111a1 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 25 Jul 2022 13:15:22 +0200 Subject: [PATCH 278/826] Add ip into ticket table --- htdocs/install/mysql/migration/16.0.0-17.0.0.sql | 4 ++++ htdocs/install/mysql/tables/llx_ticket-ticket.sql | 1 + 2 files changed, 5 insertions(+) diff --git a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql index d5bb7cd6728..2362036c93a 100644 --- a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql +++ b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql @@ -57,3 +57,7 @@ ALTER TABLE llx_facture_fourn ADD COLUMN close_missing_amount double(24, 8) afte ALTER TABLE llx_adherent_type ADD COLUMN caneditamount integer DEFAULT 0 AFTER amount; ALTER TABLE llx_inventory ADD COLUMN categories_product VARCHAR(255) DEFAULT NULL AFTER fk_product; + +ALTER TABLE llx_ticket ADD COLUMN ip varchar(250); + + diff --git a/htdocs/install/mysql/tables/llx_ticket-ticket.sql b/htdocs/install/mysql/tables/llx_ticket-ticket.sql index d079fdf3964..1f60cb3e6f8 100644 --- a/htdocs/install/mysql/tables/llx_ticket-ticket.sql +++ b/htdocs/install/mysql/tables/llx_ticket-ticket.sql @@ -40,6 +40,7 @@ CREATE TABLE llx_ticket date_close datetime, notify_tiers_at_create tinyint, email_msgid varchar(255), -- if ticket is created by email collector, we store here MSG ID + ip varchar(250), tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, import_key varchar(14) )ENGINE=innodb; From f30c95ad2233c04b9776973cae57869ef360cd58 Mon Sep 17 00:00:00 2001 From: Yoan Mollard Date: Fri, 8 Jul 2022 14:53:46 +0200 Subject: [PATCH 279/826] Create a 3rd party from the self-subscription membership form Only when ADHERENT_DEFAULT_CREATE_THIRDPARTY = 1 --- htdocs/adherents/card.php | 28 ++++---------------------- htdocs/public/members/new.php | 12 ++++++++++- htdocs/societe/class/societe.class.php | 17 ++++++++++++---- 3 files changed, 28 insertions(+), 29 deletions(-) diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php index ee195da77be..4ac0d020458 100644 --- a/htdocs/adherents/card.php +++ b/htdocs/adherents/card.php @@ -564,36 +564,16 @@ if (empty($reshook)) { $id = $object->id; } else { $db->rollback(); + setEventMessages($object->error, $object->errors, 'errors'); - if ($object->error) { - setEventMessages($object->error, $object->errors, 'errors'); - } else { - setEventMessages($object->error, $object->errors, 'errors'); - } } + // Auto-create thirdparty on member creation if (!empty($conf->global->ADHERENT_DEFAULT_CREATE_THIRDPARTY)) { if ($result > 0) { - // User creation + // Create third party out of a member $company = new Societe($db); - - $companyalias = ''; - $fullname = $object->getFullName($langs); - - if ($object->morphy == 'mor') { - $companyname = $object->company; - if (!empty($fullname)) { - $companyalias = $fullname; - } - } else { - $companyname = $fullname; - if (!empty($object->company)) { - $companyalias = $object->company; - } - } - - $result = $company->create_from_member($object, $companyname, $companyalias); - + $result = $company->create_from_member($object); if ($result < 0) { $langs->load("errors"); setEventMessages($langs->trans($company->error), null, 'errors'); diff --git a/htdocs/public/members/new.php b/htdocs/public/members/new.php index d29d80cf5d4..ac06a95a2b6 100644 --- a/htdocs/public/members/new.php +++ b/htdocs/public/members/new.php @@ -254,7 +254,7 @@ if (empty($reshook) && $action == 'add') { $public = GETPOSTISSET('public') ? 1 : 0; if (!$error) { - // email a peu pres correct et le login n'existe pas + // E-mail looks OK and login does not exist $adh = new Adherent($db); $adh->statut = -1; $adh->public = $public; @@ -375,6 +375,16 @@ if (empty($reshook) && $action == 'add') { } } + // Auto-create thirdparty on member creation + if (!empty($conf->global->ADHERENT_DEFAULT_CREATE_THIRDPARTY)) { + $company = new Societe($db); + $result = $company->create_from_member($adh); + if ($result < 0) { + $error++; + $errmsg .= join('
', $company->errors); + } + } + if (!empty($backtopage)) { $urlback = $backtopage; } elseif (!empty($conf->global->MEMBER_URL_REDIRECT_SUBSCRIPTION)) { diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 7c5773363c4..9d7a666d87d 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -3904,12 +3904,21 @@ class Societe extends CommonObject global $conf, $user, $langs; dol_syslog(get_class($this)."::create_from_member", LOG_DEBUG); - - $name = $socname ? $socname : $member->societe; - if (empty($name)) { - $name = $member->getFullName($langs); + $fullname = $member->getFullName($langs); + + if ($member->morphy == 'mor') { + $socname = $member->company? $member->company : $member->societe; + if (!empty($fullname) && empty($socalias)) { + $socalias = $fullname; + } + } else if(empty($socname) && $member->morphy == 'phy') { + $socname = $fullname; + if (!empty($member->company) && empty($socalias)) { + $socalias = $member->company; + } } + $name = $socname; $alias = $socalias ? $socalias : ''; // Positionne parametres From b0c9f5c3123084b3ac3767d2e27647e414b75108 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Mon, 25 Jul 2022 14:14:28 +0000 Subject: [PATCH 280/826] Fixing style errors. --- htdocs/societe/class/societe.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 9d7a666d87d..68942d5f9ba 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -3905,13 +3905,13 @@ class Societe extends CommonObject dol_syslog(get_class($this)."::create_from_member", LOG_DEBUG); $fullname = $member->getFullName($langs); - + if ($member->morphy == 'mor') { $socname = $member->company? $member->company : $member->societe; if (!empty($fullname) && empty($socalias)) { $socalias = $fullname; } - } else if(empty($socname) && $member->morphy == 'phy') { + } elseif (empty($socname) && $member->morphy == 'phy') { $socname = $fullname; if (!empty($member->company) && empty($socalias)) { $socalias = $member->company; From 873745a178ab3bdca28cff576ea4e998d25f53be Mon Sep 17 00:00:00 2001 From: Quatadah Nasdami Date: Mon, 25 Jul 2022 20:13:54 +0200 Subject: [PATCH 281/826] I included the boolean in the `$params` and resolved the margin issue. --- htdocs/core/lib/functions.lib.php | 8 ++++---- htdocs/projet/card.php | 22 +++++++++++----------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index e7c0244387f..3df96d4e057 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -10343,7 +10343,6 @@ function dolGetStatus($statusLabel = '', $statusLabelShort = '', $html = '', $st * @param string $actionType default, delete, danger * @param string $url the url for link * @param string $id attribute id of button - * @param bboolean $isDropdown is dropdown button * @param int $userRight user action right * // phpcs:disable * @param array $params = [ // Various params for future : recommended rather than adding more function arguments @@ -10359,17 +10358,18 @@ function dolGetStatus($statusLabel = '', $statusLabelShort = '', $html = '', $st * 'cancel-btn-label' => '', // Overide label of cancel button, if empty default label use "CloseDialog" lang key * 'content' => '', // Overide text of content, if empty default content use "ConfirmBtnCommonContent" lang key * 'modal' => true, // true|false to display dialog as a modal (with dark background) + * 'isDropDrown' => false, // true|false to display dialog as a dropdown (with dark background) * ], * ] * // phpcs:enable * @return string html button */ -function dolGetButtonAction($label, $html = '', $actionType = 'default', $url = '', $id = '', $isDropdown = false, $userRight = 1, $params = array()) +function dolGetButtonAction($label, $html = '', $actionType = 'default', $url = '', $id = '', $userRight = 1, $params = array()) { global $hookmanager, $action, $object, $langs; - //var_dump($isDropdown); - if ($isDropdown) + //var_dump($params); + if ($params['isDropdown']) $class = "dropdown-item"; else { $class = 'butAction'; diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index 0864a5b53f6..7353323b60d 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -1319,48 +1319,48 @@ if ($action == 'create' && $user->rights->projet->creer) { if (!empty($conf->global->PROJECT_SHOW_CREATE_OBJECT_BUTTON)) { print'
'; print $langs->trans("Usage"); print ''.$langs->trans("Total").'
'; $tooltip = $langs->trans("GenericMaskCodes", $langs->transnoentities("RecruitmentJobPosition"), $langs->transnoentities("RecruitmentJobPosition")); @@ -79,7 +79,7 @@ class mod_recruitmentjobposition_advanced extends ModeleNumRefRecruitmentJobPosi // Parametrage du prefix $texte .= ''; - $texte .= ''; + $texte .= ''; $texte .= ''; @@ -98,20 +98,15 @@ class mod_recruitmentjobposition_advanced extends ModeleNumRefRecruitmentJobPosi */ public function getExample() { - global $conf, $db, $langs, $mysoc; + global $conf, $langs, $mysoc; - $object = new RecruitmentJobPosition($db); - $object->initAsSpecimen(); - - /*$old_code_client = $mysoc->code_client; + $old_code_client = $mysoc->code_client; $old_code_type = $mysoc->typent_code; $mysoc->code_client = 'CCCCCCCCCC'; - $mysoc->typent_code = 'TTTTTTTTTT';*/ - - $numExample = $this->getNextValue($object); - - /*$mysoc->code_client = $old_code_client; - $mysoc->typent_code = $old_code_type;*/ + $mysoc->typent_code = 'TTTTTTTTTT'; + $numExample = $this->getNextValue($mysoc, ''); + $mysoc->code_client = $old_code_client; + $mysoc->typent_code = $old_code_type; if (!$numExample) { $numExample = $langs->trans('NotConfigured'); From e73cefa47a27370a118a20ea274d982bbcf4b2e5 Mon Sep 17 00:00:00 2001 From: Christian Foellmann Date: Tue, 19 Jul 2022 22:37:38 +0200 Subject: [PATCH 283/826] fix creating job, field type 'email' does not exist --- htdocs/recruitment/class/recruitmentcandidature.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/recruitment/class/recruitmentcandidature.class.php b/htdocs/recruitment/class/recruitmentcandidature.class.php index b0a8e9e52a0..bbe5b5e3ab5 100644 --- a/htdocs/recruitment/class/recruitmentcandidature.class.php +++ b/htdocs/recruitment/class/recruitmentcandidature.class.php @@ -120,7 +120,7 @@ class RecruitmentCandidature extends CommonObject 'fk_user_modif' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserModif', 'enabled'=>'1', 'position'=>511, 'notnull'=>-1, 'visible'=>-2,), 'lastname' => array('type'=>'varchar(128)', 'label'=>'Lastname', 'enabled'=>'1', 'position'=>20, 'notnull'=>0, 'visible'=>1,), 'firstname' => array('type'=>'varchar(128)', 'label'=>'Firstname', 'enabled'=>'1', 'position'=>21, 'notnull'=>0, 'visible'=>1,), - 'email' => array('type'=>'email', 'label'=>'EMail', 'enabled'=>'1', 'position'=>30, 'notnull'=>1, 'visible'=>1, 'picto'=>'email', 'csslist'=>'tdoverflowmax200'), + 'email' => array('type'=>'varchar(255)', 'label'=>'EMail', 'enabled'=>'1', 'position'=>30, 'notnull'=>1, 'visible'=>1, 'picto'=>'email', 'csslist'=>'tdoverflowmax200'), 'phone' => array('type'=>'phone', 'label'=>'Phone', 'enabled'=>'1', 'position'=>31, 'notnull'=>0, 'visible'=>1, 'picto'=>'phone', 'csslist'=>'tdoverflowmax150'), 'date_birth' => array('type'=>'date', 'label'=>'DateOfBirth', 'enabled'=>'1', 'position'=>70, 'visible'=>-1,), 'email_msgid' => array('type'=>'varchar(255)', 'label'=>'EmailMsgID', 'visible'=>-2, 'enabled'=>1, 'position'=>540, 'notnull'=>-1, 'help'=>'EmailMsgIDDesc'), From 8a807257931131a4758e62008659975ba6c5b98a Mon Sep 17 00:00:00 2001 From: Christian Foellmann Date: Fri, 22 Jul 2022 22:57:05 +0200 Subject: [PATCH 284/826] fix config of numbering for applications --- .../recruitment/admin/setup_candidatures.php | 8 +- .../mod_recruitmentcandidature_advanced.php | 143 ++++++++++++++++++ 2 files changed, 147 insertions(+), 4 deletions(-) create mode 100644 htdocs/recruitment/core/modules/recruitment/mod_recruitmentcandidature_advanced.php diff --git a/htdocs/recruitment/admin/setup_candidatures.php b/htdocs/recruitment/admin/setup_candidatures.php index 1ab24288401..adc12a656f4 100644 --- a/htdocs/recruitment/admin/setup_candidatures.php +++ b/htdocs/recruitment/admin/setup_candidatures.php @@ -93,11 +93,11 @@ if ((float) DOL_VERSION >= 6) { } if ($action == 'updateMask') { - $maskconstorder = GETPOST('maskconstorder', 'alpha'); - $maskorder = GETPOST('maskorder', 'alpha'); + $maskconstcand = GETPOST('maskconstcand', 'alpha'); + $maskcand = GETPOST('maskcand', 'alpha'); - if ($maskconstorder) { - $res = dolibarr_set_const($db, $maskconstorder, $maskorder, 'chaine', 0, '', $conf->entity); + if ($maskconstcand) { + $res = dolibarr_set_const($db, $maskconstcand, $maskcand, 'chaine', 0, '', $conf->entity); } if (!($res > 0)) { diff --git a/htdocs/recruitment/core/modules/recruitment/mod_recruitmentcandidature_advanced.php b/htdocs/recruitment/core/modules/recruitment/mod_recruitmentcandidature_advanced.php new file mode 100644 index 00000000000..000c045a03f --- /dev/null +++ b/htdocs/recruitment/core/modules/recruitment/mod_recruitmentcandidature_advanced.php @@ -0,0 +1,143 @@ + + * Copyright (C) 2004-2007 Laurent Destailleur + * Copyright (C) 2005-2009 Regis Houssin + * Copyright (C) 2008 Raphael Bertrand (Resultic) + * Copyright (C) 2019 Frédéric France + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * or see https://www.gnu.org/ + */ + +/** + * \file htdocs/core/modules/recruitment/mod_recruitmentcandidaturen_advanced.php + * \ingroup recruitment + * \brief File containing class for advanced numbering model of RecruitmentCandidature + */ + +dol_include_once('/recruitment/core/modules/recruitment/modules_recruitmentcandidature.php'); + + +/** + * Class to manage customer Bom numbering rules advanced + */ +class mod_recruitmentcandidature_advanced extends ModeleNumRefRecruitmentCandidature +{ + /** + * Dolibarr version of the loaded document + * @var string + */ + public $version = 'dolibarr'; // 'development', 'experimental', 'dolibarr' + + /** + * @var string Error message + */ + public $error = ''; + + /** + * @var string name + */ + public $name = 'advanced'; + + + /** + * Returns the description of the numbering model + * + * @return string Texte descripif + */ + public function info() + { + global $conf, $langs, $db; + + $langs->load("bills"); + + $form = new Form($db); + + $texte = $langs->trans('GenericNumRefModelDesc')."
\n"; + $texte .= ''; + $texte .= ''; + $texte .= ''; + $texte .= ''; + $texte .= '
'.$langs->trans("Mask").':'.$form->textwithpicto('', $tooltip, 1, 1).''.$form->textwithpicto('', $tooltip, 1, 1).' 
'; + + $tooltip = $langs->trans("GenericMaskCodes", $langs->transnoentities("RecruitmentCandidature"), $langs->transnoentities("RecruitmentCandidature")); + $tooltip .= $langs->trans("GenericMaskCodes2"); + $tooltip .= $langs->trans("GenericMaskCodes3"); + $tooltip .= $langs->trans("GenericMaskCodes4a", $langs->transnoentities("RecruitmentCandidature"), $langs->transnoentities("RecruitmentCandidature")); + $tooltip .= $langs->trans("GenericMaskCodes5"); + + // Parametrage du prefix + $texte .= ''; + $texte .= ''; + + $texte .= ''; + + $texte .= ''; + + $texte .= '
'.$langs->trans("Mask").':'.$form->textwithpicto('', $tooltip, 1, 1).' 
'; + $texte .= ''; + + return $texte; + } + + /** + * Return an example of numbering + * + * @return string Example + */ + public function getExample() + { + global $conf, $langs, $mysoc; + + $old_code_client = $mysoc->code_client; + $old_code_type = $mysoc->typent_code; + $mysoc->code_client = 'CCCCCCCCCC'; + $mysoc->typent_code = 'TTTTTTTTTT'; + $numExample = $this->getNextValue($mysoc, ''); + $mysoc->code_client = $old_code_client; + $mysoc->typent_code = $old_code_type; + + if (!$numExample) { + $numExample = $langs->trans('NotConfigured'); + } + return $numExample; + } + + /** + * Return next free value + * + * @param Object $object Object we need next value for + * @return string Value if KO, <0 if KO + */ + public function getNextValue($object) + { + global $db, $conf; + + require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; + + // We get cursor rule + $mask = getDolGlobalString('RECRUITMENT_RECRUITMENTCANDIDATURE_ADVANCED_MASK'); + + if (!$mask) { + $this->error = 'NotConfigured'; + return 0; + } + + $date = $object->date; + + $numFinal = get_next_value($db, $mask, 'recruitment_recruitmentcandidature', 'ref', '', null, $date); + + return $numFinal; + } +} From f651bf9c0d3551f8aa4b275b670580bad119f73a Mon Sep 17 00:00:00 2001 From: Christian Foellmann Date: Fri, 22 Jul 2022 23:23:37 +0200 Subject: [PATCH 285/826] fix behaviour without action --- htdocs/recruitment/recruitmentcandidature_card.php | 2 +- htdocs/recruitment/recruitmentjobposition_card.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/recruitment/recruitmentcandidature_card.php b/htdocs/recruitment/recruitmentcandidature_card.php index 0da5badd7bc..c1a4ca94045 100644 --- a/htdocs/recruitment/recruitmentcandidature_card.php +++ b/htdocs/recruitment/recruitmentcandidature_card.php @@ -86,7 +86,7 @@ foreach ($object->fields as $key => $val) { } if (empty($action) && empty($id) && empty($ref)) { - $action = 'view'; + $action = 'create'; } // Load object diff --git a/htdocs/recruitment/recruitmentjobposition_card.php b/htdocs/recruitment/recruitmentjobposition_card.php index b2172aca80d..ed1b1b54711 100644 --- a/htdocs/recruitment/recruitmentjobposition_card.php +++ b/htdocs/recruitment/recruitmentjobposition_card.php @@ -85,7 +85,7 @@ foreach ($object->fields as $key => $val) { } if (empty($action) && empty($id) && empty($ref)) { - $action = 'view'; + $action = 'create'; } // Load object From 984c125720a23761469ba3cb9573454150c7c5cb Mon Sep 17 00:00:00 2001 From: "OPEN\\s.takeuchi" Date: Tue, 26 Jul 2022 11:30:23 +0900 Subject: [PATCH 286/826] Rev+Add: Japan departments, accountings --- .../install/mysql/data/llx_10_c_regions.sql | 2 + .../mysql/data/llx_20_c_departements.sql | 49 +++ .../install/mysql/data/llx_accounting_abc.sql | 3 + .../mysql/data/llx_accounting_account_jp.sql | 365 ++++++++++++++++++ .../mysql/data/llx_c_forme_juridique.sql | 33 ++ 5 files changed, 452 insertions(+) create mode 100644 htdocs/install/mysql/data/llx_accounting_account_jp.sql diff --git a/htdocs/install/mysql/data/llx_10_c_regions.sql b/htdocs/install/mysql/data/llx_10_c_regions.sql index 752bc7de395..ffd02aa9cf9 100644 --- a/htdocs/install/mysql/data/llx_10_c_regions.sql +++ b/htdocs/install/mysql/data/llx_10_c_regions.sql @@ -533,3 +533,5 @@ INSERT INTO llx_c_regions (fk_pays, code_region, cheflieu, tncc, nom) values ( 2 INSERT INTO llx_c_regions (fk_pays, code_region, cheflieu, tncc, nom) values ( 232, 23208, '', 0, 'Nor-Oriental'); INSERT INTO llx_c_regions (fk_pays, code_region, cheflieu, tncc, nom) values ( 232, 23209, '', 0, 'Zuliana'); +-- Japan Region (id country=123) +INSERT INTO llx_c_regions (fk_pays, code_region, cheflieu, tncc, nom) values ( 123, 12301, '', 0,'日本'); diff --git a/htdocs/install/mysql/data/llx_20_c_departements.sql b/htdocs/install/mysql/data/llx_20_c_departements.sql index 642bd69960b..6b7ade68de9 100644 --- a/htdocs/install/mysql/data/llx_20_c_departements.sql +++ b/htdocs/install/mysql/data/llx_20_c_departements.sql @@ -1899,3 +1899,52 @@ INSERT INTO llx_c_departements (code_departement, fk_region, cheflieu, tncc, ncc INSERT INTO llx_c_departements (code_departement, fk_region, cheflieu, tncc, ncc, nom) VALUES ('AE-5', 22701, '', 0, '', 'Ras al-Khaimah'); INSERT INTO llx_c_departements (code_departement, fk_region, cheflieu, tncc, ncc, nom) VALUES ('AE-6', 22701, '', 0, '', 'Sharjah'); INSERT INTO llx_c_departements (code_departement, fk_region, cheflieu, tncc, ncc, nom) VALUES ('AE-7', 22701, '', 0, '', 'Umm al-Quwain'); + +-- Japan 都道府県 (id country=123) +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '01', '', '北海', '北海道', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '02', '', '青森', '青森県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '03', '', '岩手', '岩手県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '04', '', '宮城', '宮城県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '05', '', '秋田', '秋田県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '06', '', '山形', '山形県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '07', '', '福島', '福島県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '08', '', '茨城', '茨城県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '09', '', '栃木', '栃木県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '10', '', '群馬', '群馬県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '11', '', '埼玉', '埼玉県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '12', '', '千葉', '千葉県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '13', '', '東京', '東京都', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '14', '', '神奈川', '神奈川県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '15', '', '新潟', '新潟県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '16', '', '富山', '富山県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '17', '', '石川', '石川県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '18', '', '福井', '福井県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '19', '', '山梨', '山梨県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '20', '', '長野', '長野県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '21', '', '岐阜', '岐阜県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '22', '', '静岡', '静岡県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '23', '', '愛知', '愛知県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '24', '', '三重', '三重県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '25', '', '滋賀', '滋賀県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '26', '', '京都', '京都府', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '27', '', '大阪', '大阪府', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '28', '', '兵庫', '兵庫県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '29', '', '奈良', '奈良県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '30', '', '和歌山', '和歌山県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '31', '', '鳥取', '鳥取県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '32', '', '島根', '島根県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '33', '', '岡山', '岡山県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '34', '', '広島', '広島県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '35', '', '山口', '山口県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '36', '', '徳島', '徳島県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '37', '', '香川', '香川県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '38', '', '愛媛', '愛媛県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '39', '', '高知', '高知県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '40', '', '福岡', '福岡県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '41', '', '佐賀', '佐賀県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '42', '', '長崎', '長崎県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '43', '', '熊本', '熊本県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '44', '', '大分', '大分県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '45', '', '宮崎', '宮崎県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '46', '', '鹿児島', '鹿児島県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '47', '', '沖縄', '沖縄県', 1); diff --git a/htdocs/install/mysql/data/llx_accounting_abc.sql b/htdocs/install/mysql/data/llx_accounting_abc.sql index 7c8deec073c..8874fad0784 100644 --- a/htdocs/install/mysql/data/llx_accounting_abc.sql +++ b/htdocs/install/mysql/data/llx_accounting_abc.sql @@ -183,3 +183,6 @@ INSERT INTO llx_accounting_system (fk_country, pcg_version, label, active) VALUE -- Description of chart of account Mexico SAT/24-2019 INSERT INTO llx_accounting_system (fk_country, pcg_version, label, active) VALUES ( 154, 'SAT/24-2019', 'Catalogo y codigo agrupador fiscal del 2019', 1); + +-- Description of chart of account Japan JPN-BASE +INSERT INTO llx_accounting_system (fk_country, pcg_version, label, active) VALUES ( 123, 'JPN-BASE', '日本 勘定科目表 基本版', 1); diff --git a/htdocs/install/mysql/data/llx_accounting_account_jp.sql b/htdocs/install/mysql/data/llx_accounting_account_jp.sql new file mode 100644 index 00000000000..2b852ae273f --- /dev/null +++ b/htdocs/install/mysql/data/llx_accounting_account_jp.sql @@ -0,0 +1,365 @@ +-- Copyright (C) 2001-2004 Rodolphe Quiedeville +-- Copyright (C) 2003 Jean-Louis Bergamo +-- Copyright (C) 2004-2009 Laurent Destailleur +-- Copyright (C) 2004 Benoit Mortier +-- Copyright (C) 2004 Guillaume Delecourt +-- Copyright (C) 2005-2009 Regis Houssin +-- Copyright (C) 2007 Patrick Raguin +-- Copyright (C) 2011-2017 Alexandre Spangaro +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . +-- +-- Note (JPN-BASE): INCOME = REVENUE +-- Note (JPN-BASE): EXPENSE = EXPENSES +-- Note (JPN-BASE): CAPITAL = EQUITY +-- +-- Ne pas placer de commentaire en fin de ligne, ce fichier est parsé lors +-- de l''install et tous les sigles '--' sont supprimés. +-- Note: To replace a string thas is '__, 0' into an increasing number, you can use vi with comment +-- :let @a=1 | %s/__, 0/\='__, '.(@a+setreg('a',@a+1))/g + +-- Descriptif des plans comptables Japan JPN-BASE +-- ID 10000 - 99999 +-- ADD 12300000 to rowid # Do no remove this comment -- + +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 10000, 'JPN-BASE', 'ASSETS', '10000000', '0', '資産合計', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11000, 'JPN-BASE', 'ASSETS', '11000000', '10000000', '流動資産', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11100, 'JPN-BASE', 'ASSETS', '11100000', '11000000', '当座資産', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11101, 'JPN-BASE', 'ASSETS', '11110000', '11100000', '現金及び預金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11102, 'JPN-BASE', 'ASSETS', '11111000', '11110000', '現金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11103, 'JPN-BASE', 'ASSETS', '11111100', '11111000', '現金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11104, 'JPN-BASE', 'ASSETS', '11111200', '11111000', '小口現金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11105, 'JPN-BASE', 'ASSETS', '11111300', '11111000', '小切手', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11106, 'JPN-BASE', 'ASSETS', '11111400', '11111000', '転送中現金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11107, 'JPN-BASE', 'ASSETS', '11112000', '11110000', '流動性預金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11108, 'JPN-BASE', 'ASSETS', '11112100', '11112000', '当座預金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11109, 'JPN-BASE', 'ASSETS', '11112200', '11112000', '普通預金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11110, 'JPN-BASE', 'ASSETS', '11112300', '11112000', '通知預金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11111, 'JPN-BASE', 'ASSETS', '11112400', '11112000', 'その他流動性預金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11112, 'JPN-BASE', 'ASSETS', '11112500', '11112000', '銀行通過中預金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11113, 'JPN-BASE', 'ASSETS', '11112600', '11112000', '銀行未確認受領', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11114, 'JPN-BASE', 'ASSETS', '11112700', '11112000', '未配分受取預金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11115, 'JPN-BASE', 'ASSETS', '11113000', '11110000', '固定性預金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11116, 'JPN-BASE', 'ASSETS', '11113100', '11113000', '定期預金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11117, 'JPN-BASE', 'ASSETS', '11113200', '11113000', '定期積金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11118, 'JPN-BASE', 'ASSETS', '11113300', '11113000', 'その他固定性預金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11119, 'JPN-BASE', 'ASSETS', '11120000', '11100000', 'その他当座資産', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11120, 'JPN-BASE', 'ASSETS', '11121000', '11120000', '受取手形', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11121, 'JPN-BASE', 'ASSETS', '11122000', '11120000', '売掛金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11122, 'JPN-BASE', 'ASSETS', '11123000', '11120000', 'サービス売掛金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11123, 'JPN-BASE', 'ASSETS', '11124000', '11120000', '有価証券', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11124, 'JPN-BASE', 'ASSETS', '11125000', '11120000', 'その他当座資産', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11125, 'JPN-BASE', 'ASSETS', '11126000', '11120000', '未請求売掛金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11200, 'JPN-BASE', 'ASSETS', '11200000', '11000000', '棚卸資産', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11201, 'JPN-BASE', 'ASSETS', '11201000', '11200000', '商品', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11202, 'JPN-BASE', 'ASSETS', '11202000', '11200000', '製品', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11203, 'JPN-BASE', 'ASSETS', '11203000', '11200000', '製品資産', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11204, 'JPN-BASE', 'ASSETS', '11204000', '11200000', '倉庫資産', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11205, 'JPN-BASE', 'ASSETS', '11205000', '11200000', '原材料', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11206, 'JPN-BASE', 'ASSETS', '11206000', '11200000', '半製品・仕掛品', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11207, 'JPN-BASE', 'ASSETS', '11207000', '11200000', '貯蔵品', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11208, 'JPN-BASE', 'ASSETS', '11208000', '11200000', '補助材料', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11209, 'JPN-BASE', 'ASSETS', '11209000', '11200000', 'その他棚卸資産', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11210, 'JPN-BASE', 'ASSETS', '11210000', '11200000', '仕掛品在庫', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11211, 'JPN-BASE', 'ASSETS', '11211000', '11200000', '検品中在庫', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11300, 'JPN-BASE', 'ASSETS', '11300000', '11000000', 'その他流動資産', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11301, 'JPN-BASE', 'ASSETS', '11301000', '11300000', '前渡金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11302, 'JPN-BASE', 'ASSETS', '11302000', '11300000', '短期貸付金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11303, 'JPN-BASE', 'ASSETS', '11303000', '11300000', '立替金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11304, 'JPN-BASE', 'ASSETS', '11304000', '11300000', '従業員立替', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11305, 'JPN-BASE', 'ASSETS', '11305000', '11300000', '未収入金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11306, 'JPN-BASE', 'ASSETS', '11306000', '11300000', '仮払金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11307, 'JPN-BASE', 'ASSETS', '11307000', '11300000', '前払金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11308, 'JPN-BASE', 'ASSETS', '11308000', '11300000', '仮払消費税等', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11309, 'JPN-BASE', 'ASSETS', '11309000', '11300000', '未収法人税等', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11310, 'JPN-BASE', 'ASSETS', '11310000', '11300000', '繰延税金資産', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11311, 'JPN-BASE', 'ASSETS', '11311000', '11300000', 'その他流動資産', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11312, 'JPN-BASE', 'ASSETS', '11312000', '11300000', '不渡手形', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11313, 'JPN-BASE', 'ASSETS', '11313000', '11300000', '債権償却特別勘定', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 11314, 'JPN-BASE', 'ASSETS', '11314000', '11300000', '貸倒引当金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 12000, 'JPN-BASE', 'ASSETS', '12000000', '10000000', '固定資産', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 12100, 'JPN-BASE', 'ASSETS', '12100000', '12000000', '有形固定資産', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 12101, 'JPN-BASE', 'ASSETS', '12101000', '12100000', '建物', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 12102, 'JPN-BASE', 'ASSETS', '12102000', '12100000', '建物付属設備', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 12103, 'JPN-BASE', 'ASSETS', '12103000', '12100000', '構築物', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 12104, 'JPN-BASE', 'ASSETS', '12104000', '12100000', '機械装置', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 12105, 'JPN-BASE', 'ASSETS', '12105000', '12100000', '車両運搬具', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 12106, 'JPN-BASE', 'ASSETS', '12106000', '12100000', '工具器具備品', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 12107, 'JPN-BASE', 'ASSETS', '12107000', '12100000', '土地', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 12108, 'JPN-BASE', 'ASSETS', '12108000', '12100000', '建設仮勘定', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 12109, 'JPN-BASE', 'ASSETS', '12109000', '12100000', 'その他有形固定資産', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 12110, 'JPN-BASE', 'ASSETS', '12110000', '12100000', '減価償却累計額', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 12200, 'JPN-BASE', 'ASSETS', '12200000', '12000000', '無形固定資産', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 12201, 'JPN-BASE', 'ASSETS', '12201000', '12200000', '電話加入権', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 12202, 'JPN-BASE', 'ASSETS', '12202000', '12200000', 'その他無形固定資産', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 12203, 'JPN-BASE', 'ASSETS', '12203000', '12200000', 'ソフトウェア資産', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 12300, 'JPN-BASE', 'ASSETS', '12300000', '12000000', '投資その他の資産', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 12301, 'JPN-BASE', 'ASSETS', '12301000', '12300000', '投資有価証券', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 12302, 'JPN-BASE', 'ASSETS', '12302000', '12300000', '出資金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 12303, 'JPN-BASE', 'ASSETS', '12303000', '12300000', '長期貸付金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 12304, 'JPN-BASE', 'ASSETS', '12304000', '12300000', '長期前払費用', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 12305, 'JPN-BASE', 'ASSETS', '12305000', '12300000', '保証金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 12306, 'JPN-BASE', 'ASSETS', '12306000', '12300000', '事業保険積立金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 12307, 'JPN-BASE', 'ASSETS', '12307000', '12300000', '長期繰延税金資産', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 12308, 'JPN-BASE', 'ASSETS', '12308000', '12300000', 'その他投資', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 12309, 'JPN-BASE', 'ASSETS', '12410000', '12000000', 'プロジェクト資産', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 12310, 'JPN-BASE', 'ASSETS', '12420000', '12000000', 'プロジェクト仕掛', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 13000, 'JPN-BASE', 'ASSETS', '13000000', '10000000', '繰延資産', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 13001, 'JPN-BASE', 'ASSETS', '13100000', '13000000', '創立費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 13002, 'JPN-BASE', 'ASSETS', '13200000', '13000000', '開発費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 13003, 'JPN-BASE', 'ASSETS', '13300000', '13000000', '試験研究費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 13004, 'JPN-BASE', 'ASSETS', '13400000', '13000000', 'その他繰延資産', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 14000, 'JPN-BASE', 'ASSETS', '14000000', '10000000', '関係会社取引元勘定', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 20000, 'JPN-BASE', 'LIABILITIES_EQUITY', '20000000', '0', '負債・純資産合計', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21000, 'JPN-BASE', 'LIABILITIES', '21000000', '20000000', '負債合計', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21001, 'JPN-BASE', 'LIABILITIES', '21100000', '21000000', '流動負債', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21002, 'JPN-BASE', 'LIABILITIES', '21101000', '21100000', '支払手形', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21003, 'JPN-BASE', 'LIABILITIES', '21102000', '21100000', '買掛金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21004, 'JPN-BASE', 'LIABILITIES', '21103000', '21100000', 'サービス買掛金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21005, 'JPN-BASE', 'LIABILITIES', '21104000', '21100000', '短期借入金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21006, 'JPN-BASE', 'LIABILITIES', '21105000', '21100000', '1年内返済長期借入金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21007, 'JPN-BASE', 'LIABILITIES', '21106000', '21100000', '未払金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21008, 'JPN-BASE', 'LIABILITIES', '21107000', '21100000', '未払費用', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21009, 'JPN-BASE', 'LIABILITIES', '21108000', '21100000', '前受金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21010, 'JPN-BASE', 'LIABILITIES', '21109000', '21100000', '仮受金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21011, 'JPN-BASE', 'LIABILITIES', '21110000', '21100000', '預り金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21012, 'JPN-BASE', 'LIABILITIES', '21111000', '21100000', '従業員預り金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21013, 'JPN-BASE', 'LIABILITIES', '21112000', '21100000', '割引手形', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21014, 'JPN-BASE', 'LIABILITIES', '21113000', '21100000', '裏書手形', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21015, 'JPN-BASE', 'LIABILITIES', '21114000', '21100000', '未払法人税等', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21016, 'JPN-BASE', 'LIABILITIES', '21115000', '21100000', '賞与引当金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21017, 'JPN-BASE', 'LIABILITIES', '21116000', '21100000', '仮受消費税等', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21018, 'JPN-BASE', 'LIABILITIES', '21117000', '21100000', '繰延税金負債', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21019, 'JPN-BASE', 'LIABILITIES', '21118000', '21100000', 'その他流動負債', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21020, 'JPN-BASE', 'LIABILITIES', '21119000', '21100000', '未請求受領書', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21021, 'JPN-BASE', 'LIABILITIES', '21200000', '21000000', '固定負債', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21022, 'JPN-BASE', 'LIABILITIES', '21201000', '21200000', '長期借入金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21023, 'JPN-BASE', 'LIABILITIES', '21202000', '21200000', '預り保証金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21024, 'JPN-BASE', 'LIABILITIES', '21203000', '21200000', '退職給与引当金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21025, 'JPN-BASE', 'LIABILITIES', '21204000', '21200000', '長期繰延税金負債', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21026, 'JPN-BASE', 'LIABILITIES', '21205000', '21200000', 'その他固定負債', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21027, 'JPN-BASE', 'LIABILITIES', '21300000', '21000000', '引当金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21028, 'JPN-BASE', 'LIABILITIES', '21301000', '21300000', '引当金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21029, 'JPN-BASE', 'LIABILITIES', '21410000', '21000000', '関係会社取引先勘定', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21030, 'JPN-BASE', 'LIABILITIES', '21420000', '21000000', '源泉所得税', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 21031, 'JPN-BASE', 'LIABILITIES', '21430000', '21000000', '支払中買掛金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22000, 'JPN-BASE', 'EQUITY', '22000000', '20000000', '純資産合計', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22001, 'JPN-BASE', 'EQUITY', '22100000', '22000000', '株主資本', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22002, 'JPN-BASE', 'EQUITY', '22110000', '22100000', '資本金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22003, 'JPN-BASE', 'EQUITY', '22111000', '22110000', '資本金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22004, 'JPN-BASE', 'EQUITY', '22120000', '22100000', '新株式申込証拠金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22005, 'JPN-BASE', 'EQUITY', '22121000', '22120000', '新株式申込証拠金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22006, 'JPN-BASE', 'EQUITY', '22130000', '22100000', '資本剰余金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22007, 'JPN-BASE', 'EQUITY', '22131000', '22130000', '資本準備金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22008, 'JPN-BASE', 'EQUITY', '22131100', '22131000', 'その他資本剰余金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22009, 'JPN-BASE', 'EQUITY', '22131110', '22131100', '資本・資本準備金減少差益', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22010, 'JPN-BASE', 'EQUITY', '22131120', '22131100', '自己株式処分差益', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22011, 'JPN-BASE', 'EQUITY', '22140000', '22100000', '利益剰余金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22012, 'JPN-BASE', 'EQUITY', '22141000', '22140000', '利益準備金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22013, 'JPN-BASE', 'EQUITY', '22142000', '22140000', 'その他利益剰余金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22014, 'JPN-BASE', 'EQUITY', '22142100', '22142000', '退職給与積立金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22015, 'JPN-BASE', 'EQUITY', '22142200', '22142000', '別途積立金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22016, 'JPN-BASE', 'EQUITY', '22142300', '22142000', 'その他任意積立金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22017, 'JPN-BASE', 'EQUITY', '22142400', '22142000', '繰越利益剰余金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22018, 'JPN-BASE', 'EQUITY', '22142410', '22142400', '繰越利益剰余金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22019, 'JPN-BASE', 'EQUITY', '22150000', '22100000', '自己株式', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22020, 'JPN-BASE', 'EQUITY', '22151000', '22150000', '自己株式', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22021, 'JPN-BASE', 'EQUITY', '22160000', '22100000', '自己株式申込証拠金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22022, 'JPN-BASE', 'EQUITY', '22161000', '22160000', '自己株式申込証拠金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22023, 'JPN-BASE', 'EQUITY', '22200000', '22000000', '評価・換算差額等', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22024, 'JPN-BASE', 'EQUITY', '22210000', '22200000', '他有価証券評価差額金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22025, 'JPN-BASE', 'EQUITY', '22211000', '22210000', '他有価証券評価差額金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22026, 'JPN-BASE', 'EQUITY', '22220000', '22200000', '繰越ヘッジ損益', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22027, 'JPN-BASE', 'EQUITY', '22221000', '22220000', '繰越ヘッジ損益', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22028, 'JPN-BASE', 'EQUITY', '22300000', '22000000', '新株予約権', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22029, 'JPN-BASE', 'EQUITY', '22310000', '22300000', '新株予約権', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 22030, 'JPN-BASE', 'EQUITY', '22320000', '22300000', '自己新株予約権', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 30000, 'JPN-BASE', 'INCOME', '30000000', '0', '純売上高', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 30001, 'JPN-BASE', 'INCOME', '30001000', '30000000', '商品売上高', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 30002, 'JPN-BASE', 'INCOME', '30002000', '30000000', '製品売上高', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 30003, 'JPN-BASE', 'INCOME', '30003000', '30000000', 'サービス売上高', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 30004, 'JPN-BASE', 'INCOME', '30004000', '30000000', '売上値引高', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 30005, 'JPN-BASE', 'INCOME', '30005000', '30000000', '売上戻り高', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 30006, 'JPN-BASE', 'INCOME', '30006000', '30000000', '売上割戻し高', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 30007, 'JPN-BASE', 'INCOME', '30007000', '30000000', '前受収益', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 30008, 'JPN-BASE', 'INCOME', '30008000', '30000000', '未請求売上', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31000, 'JPN-BASE', 'COGS', '31000000', '0', '売上原価', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31001, 'JPN-BASE', 'COGS', '31100000', '31000000', '商品売上原価', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31002, 'JPN-BASE', 'COGS', '31200000', '31000000', '製品売上原価', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31003, 'JPN-BASE', 'COGS', '31201000', '31000000', '製品経費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31004, 'JPN-BASE', 'COGS', '31202000', '31000000', '製品原価調整', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31005, 'JPN-BASE', 'COGS', '31203000', '31000000', '入庫請求仮勘定', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31006, 'JPN-BASE', 'COGS', '31204000', '31000000', '請求価格差異', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31007, 'JPN-BASE', 'COGS', '31205000', '31000000', '標準価格差異', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31008, 'JPN-BASE', 'COGS', '31206000', '31000000', '平均原価差異', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31009, 'JPN-BASE', 'COGS', '31207000', '31000000', '倉庫差異', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31010, 'JPN-BASE', 'COGS', '31208000', '31000000', '在庫調整', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31011, 'JPN-BASE', 'COGS', '31209000', '31000000', '棚卸再評価', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31012, 'JPN-BASE', 'COGS', '31300000', '31000000', '期首棚卸高', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31400, 'JPN-BASE', 'COGS', '31400000', '31000000', '仕入高', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31401, 'JPN-BASE', 'COGS', '31410000', '31400000', '商品仕入高', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31402, 'JPN-BASE', 'COGS', '31420000', '31400000', 'サービス仕入高', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31403, 'JPN-BASE', 'COGS', '31430000', '31400000', '仕入値引高', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31404, 'JPN-BASE', 'COGS', '31440000', '31400000', '仕入戻り高', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31405, 'JPN-BASE', 'COGS', '31450000', '31400000', '仕入割戻し高', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31406, 'JPN-BASE', 'COGS', '31460000', '31400000', '仕入等配賦額', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31500, 'JPN-BASE', 'COGS', '31500000', '31000000', '当期製品製造原価', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31501, 'JPN-BASE', 'COGS', '31510000', '31500000', '当期総製造費用', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31502, 'JPN-BASE', 'COGS', '31511000', '31510000', '材料費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31503, 'JPN-BASE', 'COGS', '31511100', '31511000', '期首材料棚卸高', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31504, 'JPN-BASE', 'COGS', '31511200', '31511000', '材料仕入高', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31505, 'JPN-BASE', 'COGS', '31511300', '31511000', '期末材料棚卸高', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31506, 'JPN-BASE', 'COGS', '31512000', '31510000', '労務費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31507, 'JPN-BASE', 'COGS', '31512100', '31512000', '賃金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31508, 'JPN-BASE', 'COGS', '31512200', '31512000', '賞与', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31509, 'JPN-BASE', 'COGS', '31512300', '31512000', '退職金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31510, 'JPN-BASE', 'COGS', '31512400', '31512000', '法定福利費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31511, 'JPN-BASE', 'COGS', '31512500', '31512000', '福利厚生費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31512, 'JPN-BASE', 'COGS', '31512600', '31512000', '賞与引当金繰入', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31513, 'JPN-BASE', 'COGS', '31512700', '31512000', '退職給与引当金繰入', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31514, 'JPN-BASE', 'COGS', '31512800', '31512000', 'その他労務費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31515, 'JPN-BASE', 'COGS', '31512900', '31512000', '雑給', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31516, 'JPN-BASE', 'COGS', '31513000', '31510000', '外注加工費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31517, 'JPN-BASE', 'COGS', '31513100', '31513000', '外注加工費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31518, 'JPN-BASE', 'COGS', '31514000', '31510000', '製造経費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31519, 'JPN-BASE', 'COGS', '31514010', '31514000', '電力費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31520, 'JPN-BASE', 'COGS', '31514020', '31514000', '燃料費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31521, 'JPN-BASE', 'COGS', '31514030', '31514000', '水道光熱費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31522, 'JPN-BASE', 'COGS', '31514040', '31514000', '車両関連費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31523, 'JPN-BASE', 'COGS', '31514050', '31514000', '運賃', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31524, 'JPN-BASE', 'COGS', '31514060', '31514000', '工場消耗品費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31525, 'JPN-BASE', 'COGS', '31514070', '31514000', '賃借料', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31526, 'JPN-BASE', 'COGS', '31514080', '31514000', '支払保険料', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31527, 'JPN-BASE', 'COGS', '31514090', '31514000', '修繕費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31528, 'JPN-BASE', 'COGS', '31514100', '31514000', '租税公課', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31529, 'JPN-BASE', 'COGS', '31514110', '31514000', '減価償却費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31530, 'JPN-BASE', 'COGS', '31514120', '31514000', '旅費交通費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31531, 'JPN-BASE', 'COGS', '31514130', '31514000', '通信費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31532, 'JPN-BASE', 'COGS', '31514140', '31514000', '支払手数料', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31533, 'JPN-BASE', 'COGS', '31514150', '31514000', '会議費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31534, 'JPN-BASE', 'COGS', '31514160', '31514000', '諸会費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31535, 'JPN-BASE', 'COGS', '31514170', '31514000', '図書教育費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31536, 'JPN-BASE', 'COGS', '31514180', '31514000', '試験研究費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31537, 'JPN-BASE', 'COGS', '31514190', '31514000', 'その他製造経費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31538, 'JPN-BASE', 'COGS', '31514200', '31514000', '雑費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31539, 'JPN-BASE', 'COGS', '31515010', '31514000', '製造原価', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31540, 'JPN-BASE', 'COGS', '31515020', '31514000', 'スクラップ', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31541, 'JPN-BASE', 'COGS', '31515030', '31514000', '外注加工費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31542, 'JPN-BASE', 'COGS', '31515040', '31514000', '数量差異', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31543, 'JPN-BASE', 'COGS', '31515050', '31514000', '仕様変更差異', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31544, 'JPN-BASE', 'COGS', '31515060', '31514000', '賃率差異', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31545, 'JPN-BASE', 'COGS', '31515070', '31514000', '準変動費差異', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31546, 'JPN-BASE', 'COGS', '31515080', '31514000', '労務費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31547, 'JPN-BASE', 'COGS', '31515090', '31514000', '負担', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31548, 'JPN-BASE', 'COGS', '31515100', '31514000', '間接諸経費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31549, 'JPN-BASE', 'COGS', '31520000', '31500000', '仕掛品棚卸高', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31550, 'JPN-BASE', 'COGS', '31521000', '31520000', '製造原価配賦額', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31551, 'JPN-BASE', 'COGS', '31522000', '31520000', '期首仕掛品棚卸高', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31552, 'JPN-BASE', 'COGS', '31523000', '31520000', '期末仕掛品棚卸高', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31553, 'JPN-BASE', 'COGS', '31524000', '31520000', '他勘定振替高', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 31600, 'JPN-BASE', 'COGS', '31600000', '31000000', '期末棚卸高', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41000, 'JPN-BASE', 'EXPENSE', '41000000', '0', '販売費及び一般管理費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41100, 'JPN-BASE', 'EXPENSE', '41100000', '41000000', '人件費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41101, 'JPN-BASE', 'EXPENSE', '41101000', '41100000', '役員報酬', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41102, 'JPN-BASE', 'EXPENSE', '41102000', '41100000', '役員賞与', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41103, 'JPN-BASE', 'EXPENSE', '41103000', '41100000', '給料手当', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41104, 'JPN-BASE', 'EXPENSE', '41104000', '41100000', '賞与', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41105, 'JPN-BASE', 'EXPENSE', '41105000', '41100000', '退職金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41106, 'JPN-BASE', 'EXPENSE', '41106000', '41100000', '法定福利費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41107, 'JPN-BASE', 'EXPENSE', '41107000', '41100000', '福利厚生費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41108, 'JPN-BASE', 'EXPENSE', '41108000', '41100000', '賞与引当金繰入', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41109, 'JPN-BASE', 'EXPENSE', '41109000', '41100000', '退職給与引当金繰入', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41110, 'JPN-BASE', 'EXPENSE', '41110000', '41100000', 'その他人件費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41111, 'JPN-BASE', 'EXPENSE', '41111000', '41100000', '雑給', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41112, 'JPN-BASE', 'EXPENSE', '41112000', '41100000', '従業員経費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41200, 'JPN-BASE', 'EXPENSE', '41200000', '41000000', '販売直接費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41201, 'JPN-BASE', 'EXPENSE', '41201000', '41200000', '広告宣伝費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41202, 'JPN-BASE', 'EXPENSE', '41202000', '41200000', '運賃', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41203, 'JPN-BASE', 'EXPENSE', '41203000', '41200000', '販売手数料', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41204, 'JPN-BASE', 'EXPENSE', '41204000', '41200000', '容器包装費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41205, 'JPN-BASE', 'EXPENSE', '41205000', '41200000', 'その他販売直接費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41300, 'JPN-BASE', 'EXPENSE', '41300000', '41000000', '一般管理費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41301, 'JPN-BASE', 'EXPENSE', '41301000', '41300000', '水道光熱費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41302, 'JPN-BASE', 'EXPENSE', '41302000', '41300000', '車両関連費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41303, 'JPN-BASE', 'EXPENSE', '41303000', '41300000', '事務用消耗品費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41304, 'JPN-BASE', 'EXPENSE', '41304000', '41300000', '消耗品費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41305, 'JPN-BASE', 'EXPENSE', '41305000', '41300000', '賃借料', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41306, 'JPN-BASE', 'EXPENSE', '41306000', '41300000', '支払保険料', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41307, 'JPN-BASE', 'EXPENSE', '41307000', '41300000', '修繕費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41308, 'JPN-BASE', 'EXPENSE', '41308000', '41300000', '租税公課', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41309, 'JPN-BASE', 'EXPENSE', '41309000', '41300000', '減価償却費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41310, 'JPN-BASE', 'EXPENSE', '41310000', '41300000', '接待交際費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41311, 'JPN-BASE', 'EXPENSE', '41311000', '41300000', '旅費交通費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41312, 'JPN-BASE', 'EXPENSE', '41312000', '41300000', '通信費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41313, 'JPN-BASE', 'EXPENSE', '41313000', '41300000', '支払手数料', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41314, 'JPN-BASE', 'EXPENSE', '41314000', '41300000', '会議費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41315, 'JPN-BASE', 'EXPENSE', '41315000', '41300000', '諸会費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41316, 'JPN-BASE', 'EXPENSE', '41316000', '41300000', '寄付金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41317, 'JPN-BASE', 'EXPENSE', '41317000', '41300000', '図書教育費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41318, 'JPN-BASE', 'EXPENSE', '41318000', '41300000', '試験研究費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41319, 'JPN-BASE', 'EXPENSE', '41319000', '41300000', 'その他管理費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41320, 'JPN-BASE', 'EXPENSE', '41320000', '41300000', '貸倒引当金繰入', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41321, 'JPN-BASE', 'EXPENSE', '41321000', '41300000', '銀行手数料', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41322, 'JPN-BASE', 'EXPENSE', '41322000', '41300000', '現金差異', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41323, 'JPN-BASE', 'EXPENSE', '41323000', '41300000', '雑費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 41400, 'JPN-BASE', 'EXPENSE', '41400000', '41000000', '販管費配賦額', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 51000, 'JPN-BASE', 'OTHER_REVENUE', '51000000', '0', '営業外収益', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 51001, 'JPN-BASE', 'OTHER_REVENUE', '51010000', '51000000', '受取利息', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 51002, 'JPN-BASE', 'OTHER_REVENUE', '51020000', '51000000', '受取配当金', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 51003, 'JPN-BASE', 'OTHER_REVENUE', '51030000', '51000000', '銀行再評価益', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 51004, 'JPN-BASE', 'OTHER_REVENUE', '51040000', '51000000', '銀行決済利益', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 51005, 'JPN-BASE', 'OTHER_REVENUE', '51050000', '51000000', '手数料収益', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 51006, 'JPN-BASE', 'OTHER_REVENUE', '51060000', '51000000', 'その他営業外収益', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 51007, 'JPN-BASE', 'OTHER_REVENUE', '51070000', '51000000', '支払割引費科目', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 51008, 'JPN-BASE', 'OTHER_REVENUE', '51080000', '51000000', '許可割引料', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 51009, 'JPN-BASE', 'OTHER_REVENUE', '51090000', '51000000', '現金出納帳受取', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 51010, 'JPN-BASE', 'OTHER_REVENUE', '51100000', '51000000', '未実現利益', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 51011, 'JPN-BASE', 'OTHER_REVENUE', '51110000', '51000000', '実現利益', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 51012, 'JPN-BASE', 'OTHER_REVENUE', '51120000', '51000000', '雑収入', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 52000, 'JPN-BASE', 'OTHER_EXPENSES', '52000000', '0', '営業外費用', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 52001, 'JPN-BASE', 'OTHER_EXPENSES', '52010000', '52000000', '支払利息', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 52002, 'JPN-BASE', 'OTHER_EXPENSES', '52020000', '52000000', '銀行再評価損', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 52003, 'JPN-BASE', 'OTHER_EXPENSES', '52030000', '52000000', '銀行決済損失', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 52004, 'JPN-BASE', 'OTHER_EXPENSES', '52040000', '52000000', '手数料経費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 52005, 'JPN-BASE', 'OTHER_EXPENSES', '52050000', '52000000', '手形売却損', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 52006, 'JPN-BASE', 'OTHER_EXPENSES', '52060000', '52000000', 'その他営業外費用', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 52007, 'JPN-BASE', 'OTHER_EXPENSES', '52070000', '52000000', '支払割引売上科目', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 52008, 'JPN-BASE', 'OTHER_EXPENSES', '52080000', '52000000', '受取割引料', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 52009, 'JPN-BASE', 'OTHER_EXPENSES', '52090000', '52000000', '貸倒損失', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 52010, 'JPN-BASE', 'OTHER_EXPENSES', '52100000', '52000000', '現金出納帳経費', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 52011, 'JPN-BASE', 'OTHER_EXPENSES', '52110000', '52000000', '未実現損失', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 52012, 'JPN-BASE', 'OTHER_EXPENSES', '52120000', '52000000', '実現損失', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 52013, 'JPN-BASE', 'OTHER_EXPENSES', '52130000', '52000000', '雑損失', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 52014, 'JPN-BASE', 'OTHER_EXPENSES', '52140000', '52000000', '営業外配賦額', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 61000, 'JPN-BASE', 'EXTRAORDINALY_REVENUE', '61000000', '0', '特別利益', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 61001, 'JPN-BASE', 'EXTRAORDINALY_REVENUE', '61100000', '61000000', '固定資産売却益', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 61002, 'JPN-BASE', 'EXTRAORDINALY_REVENUE', '61200000', '61000000', '貸倒引当金戻入', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 61003, 'JPN-BASE', 'EXTRAORDINALY_REVENUE', '61300000', '61000000', 'その他特別利益', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 61004, 'JPN-BASE', 'EXTRAORDINALY_REVENUE', '61400000', '61000000', '前期損益修正益', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 62000, 'JPN-BASE', 'EXTRAORDINALY_EXPENSES', '62000000', '0', '特別損失', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 62001, 'JPN-BASE', 'EXTRAORDINALY_EXPENSES', '62100000', '62000000', '固定資産売却除却損', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 62002, 'JPN-BASE', 'EXTRAORDINALY_EXPENSES', '62200000', '62000000', 'その他特別損失', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 62003, 'JPN-BASE', 'EXTRAORDINALY_EXPENSES', '62300000', '62000000', '前期損益修正損', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 71100, 'JPN-BASE', 'INCOME_TAXES', '71100000', '0', '法人税等', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 71101, 'JPN-BASE', 'INCOME_TAXES', '71110000', '71100000', '法人税等', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 71102, 'JPN-BASE', 'INCOME_TAXES', '71120000', '71100000', '法人税等調整額', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 81101, 'JPN-BASE', 'OTHER_INCOME_EXPENSES', '81101000', '0', 'デフォルト勘定科目', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 81102, 'JPN-BASE', 'OTHER_INCOME_EXPENSES', '81102000', '0', '貸借不一致仮勘定', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 81103, 'JPN-BASE', 'OTHER_INCOME_EXPENSES', '81103000', '0', 'エラー仮勘定', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 81104, 'JPN-BASE', 'OTHER_INCOME_EXPENSES', '81104000', '0', '通貨貸借不一致仮勘定', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 81105, 'JPN-BASE', 'OTHER_INCOME_EXPENSES', '81105000', '0', '損益勘定', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 81106, 'JPN-BASE', 'OTHER_INCOME_EXPENSES', '81106000', '0', '購入価格差異相殺', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 82101, 'JPN-BASE', 'MEMO', '82100000', '0', 'コミッション相殺', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 82102, 'JPN-BASE', 'MEMO', '82200000', '0', '販売コミッション相殺', 1); +INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 82103, 'JPN-BASE', 'MEMO', '99999999', '0', '諸口', 1); diff --git a/htdocs/install/mysql/data/llx_c_forme_juridique.sql b/htdocs/install/mysql/data/llx_c_forme_juridique.sql index bb8dd4c4efb..7ba761ce8f9 100644 --- a/htdocs/install/mysql/data/llx_c_forme_juridique.sql +++ b/htdocs/install/mysql/data/llx_c_forme_juridique.sql @@ -403,3 +403,36 @@ INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (76, '7608', ' INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (76, '7609', 'Državno tijelo'); INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (76, '7610', 'Kućna radinost'); INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (76, '7611', 'Sporedno zanimanje'); + +-- Japan (id country=123) +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12301', '株式会社'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12302', '有限会社'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12303', '合資会社'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12304', '合名会社'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12305', '相互会社'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12306', '医療法人'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12307', '財団法人'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12308', '社団法人'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12309', '社会福祉法人'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12310', '学校法人'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12311', '特定非営利活動法人'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12312', 'NPO法人'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12313', '商工組合'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12314', '林業組合'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12315', '同業組合'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12316', '農業協同組合'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12317', '漁業協同組合'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12318', '農事組合法人'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12319', '生活互助会'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12320', '協業組合'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12321', '協同組合'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12322', '生活協同組合'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12323', '連合会'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12324', '組合連合会'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12325', '協同組合連合会'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12329', '一般社団法人'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12330', '公益社団法人'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12331', '一般財団法人'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12332', '公益財団法人'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12333', '合同会社'); +INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (123, '12399', '個人又はその他の法人'); From 63c821c12d7c127d4d555d74840a32a4f07fb85f Mon Sep 17 00:00:00 2001 From: Christian Foellmann Date: Tue, 26 Jul 2022 09:45:22 +0200 Subject: [PATCH 287/826] fix document prefixes CLOSE #18279 --- htdocs/recruitment/recruitmentcandidature_document.php | 1 + htdocs/recruitment/recruitmentjobposition_document.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/recruitment/recruitmentcandidature_document.php b/htdocs/recruitment/recruitmentcandidature_document.php index 38715f412f2..25cdb80aa3e 100644 --- a/htdocs/recruitment/recruitmentcandidature_document.php +++ b/htdocs/recruitment/recruitmentcandidature_document.php @@ -188,6 +188,7 @@ if ($object->id) { $param = '&id='.$object->id; $relativepathwithnofile = 'recruitmentcandidature/'.dol_sanitizeFileName($object->ref).'/'; + $savingdocmask = dol_sanitizeFileName($object->ref).'-__file__'; include DOL_DOCUMENT_ROOT.'/core/tpl/document_actions_post_headers.tpl.php'; } else { diff --git a/htdocs/recruitment/recruitmentjobposition_document.php b/htdocs/recruitment/recruitmentjobposition_document.php index 43f90ca1fdd..3845a53a4e3 100644 --- a/htdocs/recruitment/recruitmentjobposition_document.php +++ b/htdocs/recruitment/recruitmentjobposition_document.php @@ -186,8 +186,8 @@ if ($object->id) { $permtoedit = $user->rights->recruitment->recruitmentjobposition->write; $param = '&id='.$object->id; - //$relativepathwithnofile='recruitmentjobposition/' . dol_sanitizeFileName($object->id).'/'; $relativepathwithnofile = 'recruitmentjobposition/'.dol_sanitizeFileName($object->ref).'/'; + $savingdocmask = dol_sanitizeFileName($object->ref).'-__file__'; include DOL_DOCUMENT_ROOT.'/core/tpl/document_actions_post_headers.tpl.php'; } else { From d964aabcea3894db14904e5dc40d6ce5400679c7 Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Tue, 26 Jul 2022 11:01:53 +0200 Subject: [PATCH 288/826] fix with advices --- htdocs/product/stock/massstockmove.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/product/stock/massstockmove.php b/htdocs/product/stock/massstockmove.php index b2276befd63..09bc19b9beb 100644 --- a/htdocs/product/stock/massstockmove.php +++ b/htdocs/product/stock/massstockmove.php @@ -336,10 +336,10 @@ if ($action == 'importCSV' && !empty($user->rights->stock->mouvement->creer)) { continue; } //var_dump($data); - $tmp_id_sw = dol_escape_htmltag($data[$i][0]['val']); - $tmp_id_tw = dol_escape_htmltag($data[$i][1]['val']); - $tmp_id_product = dol_escape_htmltag($data[$i][2]['val']); - $tmp_qty = dol_escape_htmltag($data[$i][3]['val']); + $tmp_id_sw = (int) $data[$i][0]['val']; + $tmp_id_tw = (int) dol_escape_htmltag($data[$i][1]['val']); + $tmp_id_product = (int) dol_escape_htmltag($data[$i][2]['val']); + $tmp_qty = price2num((float) $data[$i][3]['val'], 'MS'); $tmp_batch = dol_escape_htmltag($data[$i][4]['val']); if (!is_numeric($tmp_id_product)) { From e4d2e538c4dedc045951d0f863757f61e40f4945 Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Tue, 26 Jul 2022 11:03:27 +0200 Subject: [PATCH 289/826] remove escape --- htdocs/product/stock/massstockmove.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/product/stock/massstockmove.php b/htdocs/product/stock/massstockmove.php index 09bc19b9beb..31b2aa8e187 100644 --- a/htdocs/product/stock/massstockmove.php +++ b/htdocs/product/stock/massstockmove.php @@ -337,8 +337,8 @@ if ($action == 'importCSV' && !empty($user->rights->stock->mouvement->creer)) { } //var_dump($data); $tmp_id_sw = (int) $data[$i][0]['val']; - $tmp_id_tw = (int) dol_escape_htmltag($data[$i][1]['val']); - $tmp_id_product = (int) dol_escape_htmltag($data[$i][2]['val']); + $tmp_id_tw = (int) $data[$i][1]['val']; + $tmp_id_product = (int) $data[$i][2]['val']; $tmp_qty = price2num((float) $data[$i][3]['val'], 'MS'); $tmp_batch = dol_escape_htmltag($data[$i][4]['val']); From de0e24b7d3b03fdb9f1e65819ed38ab083dc07c6 Mon Sep 17 00:00:00 2001 From: Christian Foellmann Date: Tue, 26 Jul 2022 10:00:47 +0200 Subject: [PATCH 290/826] remove inactive users from user selectors --- htdocs/recruitment/class/recruitmentjobposition.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/recruitment/class/recruitmentjobposition.class.php b/htdocs/recruitment/class/recruitmentjobposition.class.php index cc56b1c9cd7..e0a59b0e3a6 100644 --- a/htdocs/recruitment/class/recruitmentjobposition.class.php +++ b/htdocs/recruitment/class/recruitmentjobposition.class.php @@ -105,9 +105,9 @@ class RecruitmentJobPosition extends CommonObject 'label' => array('type'=>'varchar(255)', 'label'=>'JobLabel', 'enabled'=>'1', 'position'=>30, 'notnull'=>1, 'visible'=>1, 'searchall'=>1, 'css'=>'minwidth500', 'csslist'=>'tdoverflowmax300', 'showoncombobox'=>'2', 'autofocusoncreate'=>1), 'qty' => array('type'=>'integer', 'label'=>'NbOfEmployeesExpected', 'enabled'=>'1', 'position'=>45, 'notnull'=>1, 'visible'=>1, 'default'=>'1', 'isameasure'=>'1', 'css'=>'maxwidth75imp'), 'fk_project' => array('type'=>'integer:Project:projet/class/project.class.php:1', 'label'=>'Project', 'enabled'=>'$conf->project->enabled', 'position'=>52, 'notnull'=>-1, 'visible'=>-1, 'index'=>1, 'css'=>'maxwidth500', 'picto'=>'project'), - 'fk_user_recruiter' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'ResponsibleOfRecruitement', 'enabled'=>'1', 'position'=>54, 'notnull'=>1, 'visible'=>1, 'foreignkey'=>'user.rowid', 'css'=>'maxwidth500', 'csslist'=>'tdoverflowmax150', 'picto'=>'user'), + 'fk_user_recruiter' => array('type'=>'integer:User:user/class/user.class.php:status=1', 'label'=>'ResponsibleOfRecruitement', 'enabled'=>'1', 'position'=>54, 'notnull'=>1, 'visible'=>1, 'foreignkey'=>'user.rowid', 'css'=>'maxwidth500', 'csslist'=>'tdoverflowmax150', 'picto'=>'user'), 'email_recruiter' => array('type'=>'varchar(255)', 'label'=>'EmailRecruiter', 'enabled'=>'1', 'position'=>54, 'notnull'=>0, 'visible'=>-1, 'help'=>'ToUseAGenericEmail', 'picto'=>'email'), - 'fk_user_supervisor' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'FutureManager', 'enabled'=>'1', 'position'=>55, 'notnull'=>0, 'visible'=>-1, 'foreignkey'=>'user.rowid', 'css'=>'maxwidth500', 'csslist'=>'tdoverflowmax150', 'picto'=>'user'), + 'fk_user_supervisor' => array('type'=>'integer:User:user/class/user.class.php::t.statut = 1', 'label'=>'FutureManager', 'enabled'=>'1', 'position'=>55, 'notnull'=>0, 'visible'=>-1, 'foreignkey'=>'user.rowid', 'css'=>'maxwidth500', 'csslist'=>'tdoverflowmax150', 'picto'=>'user'), 'fk_establishment' => array('type'=>'integer:Establishment:hrm/class/establishment.class.php', 'label'=>'Establishment', 'enabled'=>'$conf->hrm->enabled', 'position'=>56, 'notnull'=>0, 'visible'=>-1, 'foreignkey'=>'establishment.rowid',), 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1:status=1 AND entity IN (__SHARED_ENTITIES__)', 'label'=>'WorkPlace', 'enabled'=>'$conf->societe->enabled', 'position'=>57, 'notnull'=>-1, 'visible'=>-1, 'css'=>'maxwidth500', 'index'=>1, 'help'=>"IfJobIsLocatedAtAPartner", 'picto'=>'company'), 'date_planned' => array('type'=>'date', 'label'=>'DateExpected', 'enabled'=>'1', 'position'=>60, 'notnull'=>0, 'visible'=>1,), From 46d36478773870dab945dc326cb77bde2668282d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 26 Jul 2022 12:18:56 +0200 Subject: [PATCH 291/826] Merge --- htdocs/compta/bank/class/account.class.php | 2 +- htdocs/core/class/commonobject.class.php | 4 ++++ htdocs/core/class/html.form.class.php | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/htdocs/compta/bank/class/account.class.php b/htdocs/compta/bank/class/account.class.php index 7a7097ecb71..21a082e9491 100644 --- a/htdocs/compta/bank/class/account.class.php +++ b/htdocs/compta/bank/class/account.class.php @@ -2390,7 +2390,7 @@ class AccountLine extends CommonObject $result = ''; - $label = img_picto('', $this->picto).' '.$langs->trans("Transaction").':
'; + $label = img_picto('', $this->picto).' '.$langs->trans("BankTransactionLine").':
'; $label .= ''.$langs->trans("Ref").': '.$this->ref; $linkstart = ''; diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index ad31e42a625..a0b225b952b 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -588,6 +588,10 @@ abstract class CommonObject public $alreadypaid; + private $labelStatus; + private $labelStatusShort; + + /** * @var array List of child tables. To test if we can delete object. */ diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index dda61ae72d4..9c3aaa87cb0 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -9387,7 +9387,7 @@ class Form $ret .= ''; // gravatar need md5 hash } else { if ($nophoto == 'company') { - $ret .= '
'.img_picto('', 'company').'
'; + $ret .= '
'.img_picto('', 'company').'
'; } else { $ret .= ''; } From 6ff83be2df321dab9b7f5597a10074482cdb8014 Mon Sep 17 00:00:00 2001 From: "OPEN\\s.takeuchi" Date: Tue, 26 Jul 2022 19:24:52 +0900 Subject: [PATCH 292/826] Rev: add 'tncc' value --- .../mysql/data/llx_20_c_departements.sql | 94 +++++++++---------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/htdocs/install/mysql/data/llx_20_c_departements.sql b/htdocs/install/mysql/data/llx_20_c_departements.sql index 6b7ade68de9..04522605d4a 100644 --- a/htdocs/install/mysql/data/llx_20_c_departements.sql +++ b/htdocs/install/mysql/data/llx_20_c_departements.sql @@ -1901,50 +1901,50 @@ INSERT INTO llx_c_departements (code_departement, fk_region, cheflieu, tncc, ncc INSERT INTO llx_c_departements (code_departement, fk_region, cheflieu, tncc, ncc, nom) VALUES ('AE-7', 22701, '', 0, '', 'Umm al-Quwain'); -- Japan 都道府県 (id country=123) -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '01', '', '北海', '北海道', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '02', '', '青森', '青森県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '03', '', '岩手', '岩手県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '04', '', '宮城', '宮城県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '05', '', '秋田', '秋田県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '06', '', '山形', '山形県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '07', '', '福島', '福島県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '08', '', '茨城', '茨城県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '09', '', '栃木', '栃木県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '10', '', '群馬', '群馬県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '11', '', '埼玉', '埼玉県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '12', '', '千葉', '千葉県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '13', '', '東京', '東京都', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '14', '', '神奈川', '神奈川県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '15', '', '新潟', '新潟県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '16', '', '富山', '富山県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '17', '', '石川', '石川県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '18', '', '福井', '福井県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '19', '', '山梨', '山梨県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '20', '', '長野', '長野県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '21', '', '岐阜', '岐阜県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '22', '', '静岡', '静岡県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '23', '', '愛知', '愛知県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '24', '', '三重', '三重県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '25', '', '滋賀', '滋賀県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '26', '', '京都', '京都府', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '27', '', '大阪', '大阪府', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '28', '', '兵庫', '兵庫県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '29', '', '奈良', '奈良県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '30', '', '和歌山', '和歌山県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '31', '', '鳥取', '鳥取県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '32', '', '島根', '島根県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '33', '', '岡山', '岡山県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '34', '', '広島', '広島県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '35', '', '山口', '山口県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '36', '', '徳島', '徳島県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '37', '', '香川', '香川県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '38', '', '愛媛', '愛媛県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '39', '', '高知', '高知県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '40', '', '福岡', '福岡県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '41', '', '佐賀', '佐賀県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '42', '', '長崎', '長崎県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '43', '', '熊本', '熊本県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '44', '', '大分', '大分県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '45', '', '宮崎', '宮崎県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '46', '', '鹿児島', '鹿児島県', 1); -insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '47', '', '沖縄', '沖縄県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '01', '', 0, '北海', '北海道', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '02', '', 0, '青森', '青森県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '03', '', 0, '岩手', '岩手県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '04', '', 0, '宮城', '宮城県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '05', '', 0, '秋田', '秋田県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '06', '', 0, '山形', '山形県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '07', '', 0, '福島', '福島県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '08', '', 0, '茨城', '茨城県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '09', '', 0, '栃木', '栃木県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '10', '', 0, '群馬', '群馬県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '11', '', 0, '埼玉', '埼玉県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '12', '', 0, '千葉', '千葉県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '13', '', 0, '東京', '東京都', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '14', '', 0, '神奈川', '神奈川県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '15', '', 0, '新潟', '新潟県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '16', '', 0, '富山', '富山県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '17', '', 0, '石川', '石川県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '18', '', 0, '福井', '福井県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '19', '', 0, '山梨', '山梨県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '20', '', 0, '長野', '長野県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '21', '', 0, '岐阜', '岐阜県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '22', '', 0, '静岡', '静岡県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '23', '', 0, '愛知', '愛知県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '24', '', 0, '三重', '三重県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '25', '', 0, '滋賀', '滋賀県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '26', '', 0, '京都', '京都府', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '27', '', 0, '大阪', '大阪府', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '28', '', 0, '兵庫', '兵庫県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '29', '', 0, '奈良', '奈良県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '30', '', 0, '和歌山', '和歌山県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '31', '', 0, '鳥取', '鳥取県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '32', '', 0, '島根', '島根県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '33', '', 0, '岡山', '岡山県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '34', '', 0, '広島', '広島県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '35', '', 0, '山口', '山口県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '36', '', 0, '徳島', '徳島県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '37', '', 0, '香川', '香川県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '38', '', 0, '愛媛', '愛媛県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '39', '', 0, '高知', '高知県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '40', '', 0, '福岡', '福岡県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '41', '', 0, '佐賀', '佐賀県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '42', '', 0, '長崎', '長崎県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '43', '', 0, '熊本', '熊本県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '44', '', 0, '大分', '大分県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '45', '', 0, '宮崎', '宮崎県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '46', '', 0, '鹿児島', '鹿児島県', 1); +insert into llx_c_departements (fk_region, code_departement, cheflieu, tncc, ncc, nom, active) values (12301, '47', '', 0, '沖縄', '沖縄県', 1); From ac21343227a4969a43673cd00633eea680ca9e00 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 26 Jul 2022 12:26:11 +0200 Subject: [PATCH 293/826] Update recruitmentcandidature.class.php --- htdocs/recruitment/class/recruitmentcandidature.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/recruitment/class/recruitmentcandidature.class.php b/htdocs/recruitment/class/recruitmentcandidature.class.php index bbe5b5e3ab5..b0a8e9e52a0 100644 --- a/htdocs/recruitment/class/recruitmentcandidature.class.php +++ b/htdocs/recruitment/class/recruitmentcandidature.class.php @@ -120,7 +120,7 @@ class RecruitmentCandidature extends CommonObject 'fk_user_modif' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserModif', 'enabled'=>'1', 'position'=>511, 'notnull'=>-1, 'visible'=>-2,), 'lastname' => array('type'=>'varchar(128)', 'label'=>'Lastname', 'enabled'=>'1', 'position'=>20, 'notnull'=>0, 'visible'=>1,), 'firstname' => array('type'=>'varchar(128)', 'label'=>'Firstname', 'enabled'=>'1', 'position'=>21, 'notnull'=>0, 'visible'=>1,), - 'email' => array('type'=>'varchar(255)', 'label'=>'EMail', 'enabled'=>'1', 'position'=>30, 'notnull'=>1, 'visible'=>1, 'picto'=>'email', 'csslist'=>'tdoverflowmax200'), + 'email' => array('type'=>'email', 'label'=>'EMail', 'enabled'=>'1', 'position'=>30, 'notnull'=>1, 'visible'=>1, 'picto'=>'email', 'csslist'=>'tdoverflowmax200'), 'phone' => array('type'=>'phone', 'label'=>'Phone', 'enabled'=>'1', 'position'=>31, 'notnull'=>0, 'visible'=>1, 'picto'=>'phone', 'csslist'=>'tdoverflowmax150'), 'date_birth' => array('type'=>'date', 'label'=>'DateOfBirth', 'enabled'=>'1', 'position'=>70, 'visible'=>-1,), 'email_msgid' => array('type'=>'varchar(255)', 'label'=>'EmailMsgID', 'visible'=>-2, 'enabled'=>1, 'position'=>540, 'notnull'=>-1, 'help'=>'EmailMsgIDDesc'), From c42eaaf16cd0cadc823e12c8a5609c4b7df47b39 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 26 Jul 2022 13:14:12 +0200 Subject: [PATCH 294/826] Clean code --- htdocs/holiday/card.php | 2 +- htdocs/holiday/card_group.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/holiday/card.php b/htdocs/holiday/card.php index 566864c765a..05fca97348a 100644 --- a/htdocs/holiday/card.php +++ b/htdocs/holiday/card.php @@ -1153,7 +1153,7 @@ if ((empty($id) && empty($ref)) || $action == 'create' || $action == 'add') { $errors[] = $langs->transnoentitiesnoconv('ErrorEndDateCP'); break; case 'SQL_Create': - $errors[] = $langs->transnoentitiesnoconv('ErrorSQLCreateCP').' '.$_GET['msg']; + $errors[] = $langs->transnoentitiesnoconv('ErrorSQLCreateCP'); break; case 'CantCreate': $errors[] = $langs->transnoentitiesnoconv('CantCreateCP'); diff --git a/htdocs/holiday/card_group.php b/htdocs/holiday/card_group.php index 5e571f077c8..950e2342de8 100644 --- a/htdocs/holiday/card_group.php +++ b/htdocs/holiday/card_group.php @@ -385,7 +385,7 @@ if ((empty($id) && empty($ref)) || $action == 'create' || $action == 'add') { $errors[] = $langs->trans('ErrorEndDateCP'); break; case 'SQL_Create': - $errors[] = $langs->trans('ErrorSQLCreateCP').' '.htmlentities($_GET['msg']).''; + $errors[] = $langs->trans('ErrorSQLCreateCP'); break; case 'CantCreate': $errors[] = $langs->trans('CantCreateCP'); From 0c416a1e38d7f04d6d3a4657e484e95a3dda50dd Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Tue, 26 Jul 2022 15:38:50 +0200 Subject: [PATCH 295/826] better hook management --- htdocs/takepos/invoice.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/htdocs/takepos/invoice.php b/htdocs/takepos/invoice.php index e3f4a106c67..a37752863a0 100644 --- a/htdocs/takepos/invoice.php +++ b/htdocs/takepos/invoice.php @@ -562,14 +562,16 @@ if (empty($reshook)) { $invoice->fetch_thirdparty(); $array_options = array(); + $line = array('description' => $prod->description, 'price' => $price, 'tva_tx' => $tva_tx, 'locatax1_tx' => $localtax1_tx, 'locatax2_tx' => $localtax2_tx, 'remise_percent' => $customer->remise_percent, 'price_ttc' => $price_ttc, 'array_options' => $array_options); + // complete line by hook - $parameters = array('prod' => $prod); - $reshook=$hookmanager->executeHooks('completeTakePosAddLine', $parameters, $invoice, $action); + $parameters = array('prod' => $prod, 'line' => $line); + $reshook=$hookmanager->executeHooks('completeTakePosAddLine', $parameters, $invoice, $action); // Note that $action and $line may have been modified by some hooks if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); - if (empty($reshook)) { - $idoflineadded = $invoice->addline($prod->description, $price, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idproduct, $customer->remise_percent, '', 0, 0, 0, '', $price_base_type, $price_ttc, $prod->type, -1, 0, '', 0, (!empty($parent_line)) ? $parent_line : '', null, '', '', $array_options, 100, '', null, 0); - } + if (!empty($hookmanager->resArray)) $line = $hookmanager->resArray; + + $idoflineadded = $invoice->addline($line['description'], $line['price'], $qty, $line['tva_tx'], $line['localtax1_tx'], $line['localtax2_tx'], $idproduct, $line['remise_percent'], '', 0, 0, 0, '', $price_base_type, $line['price_ttc'], $prod->type, -1, 0, '', 0, (!empty($parent_line)) ? $parent_line : '', null, '', '', $line['array_options'], 100, '', null, 0); if (!empty($conf->global->TAKEPOS_CUSTOMER_DISPLAY)) { $CUSTOMER_DISPLAY_line1 = $prod->label; From 3e930f92b8dd4d1a406decfc5c192885b2ecfce9 Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Tue, 26 Jul 2022 15:47:03 +0200 Subject: [PATCH 296/826] add reshook test --- htdocs/takepos/invoice.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/htdocs/takepos/invoice.php b/htdocs/takepos/invoice.php index a37752863a0..3657ca7f4b6 100644 --- a/htdocs/takepos/invoice.php +++ b/htdocs/takepos/invoice.php @@ -569,9 +569,14 @@ if (empty($reshook)) { $reshook=$hookmanager->executeHooks('completeTakePosAddLine', $parameters, $invoice, $action); // Note that $action and $line may have been modified by some hooks if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); - if (!empty($hookmanager->resArray)) $line = $hookmanager->resArray; - $idoflineadded = $invoice->addline($line['description'], $line['price'], $qty, $line['tva_tx'], $line['localtax1_tx'], $line['localtax2_tx'], $idproduct, $line['remise_percent'], '', 0, 0, 0, '', $price_base_type, $line['price_ttc'], $prod->type, -1, 0, '', 0, (!empty($parent_line)) ? $parent_line : '', null, '', '', $line['array_options'], 100, '', null, 0); + if (empty($reshook)) { + if (!empty($hookmanager->resArray)) { + $line = $hookmanager->resArray; + } + + $idoflineadded = $invoice->addline($line['description'], $line['price'], $qty, $line['tva_tx'], $line['localtax1_tx'], $line['localtax2_tx'], $idproduct, $line['remise_percent'], '', 0, 0, 0, '', $price_base_type, $line['price_ttc'], $prod->type, -1, 0, '', 0, (!empty($parent_line)) ? $parent_line : '', null, '', '', $line['array_options'], 100, '', null, 0); + } if (!empty($conf->global->TAKEPOS_CUSTOMER_DISPLAY)) { $CUSTOMER_DISPLAY_line1 = $prod->label; From 4776c9fdaaf29caa7b228e491acb96dc7372dad2 Mon Sep 17 00:00:00 2001 From: bagtaib Date: Tue, 26 Jul 2022 16:30:21 +0200 Subject: [PATCH 297/826] change button position --- htdocs/admin/tools/dolibarr_export.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/htdocs/admin/tools/dolibarr_export.php b/htdocs/admin/tools/dolibarr_export.php index fae91d3ecb4..83ae97bafa3 100644 --- a/htdocs/admin/tools/dolibarr_export.php +++ b/htdocs/admin/tools/dolibarr_export.php @@ -171,8 +171,7 @@ print ''; print ''; print ''; -print ''; -print ''; print '
'; print '
'.$langs->trans("ExportMethod").''; @@ -194,8 +193,9 @@ if (in_array($type, array('mysql', 'mysqli'))) { print '
'; print '
'; -print ''; -print ''; +print '
'; +print ''; print ''; @@ -216,6 +216,7 @@ function hideoptions(){ '; print ''; -print ''; +print ''; print ''; print '
'; +print '
'; +print '
'; From 3f81d21c7cea2245989e5ce873b9f4d80b99ef28 Mon Sep 17 00:00:00 2001 From: bagtaib Date: Tue, 26 Jul 2022 18:32:48 +0200 Subject: [PATCH 298/826] make a button look like a link --- htdocs/admin/tools/dolibarr_export.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/admin/tools/dolibarr_export.php b/htdocs/admin/tools/dolibarr_export.php index 83ae97bafa3..78c0d9690c1 100644 --- a/htdocs/admin/tools/dolibarr_export.php +++ b/htdocs/admin/tools/dolibarr_export.php @@ -197,7 +197,8 @@ print ''; print '
'; print ''; -print ''; +print ''; print ''; @@ -432,7 +432,7 @@ if (in_array($type, array('pgsql'))) { } print ''; -print ''; +print ''; print ''; print ''; From 1d8b39260b4b364c5f5d16c81337e7df6c03271a Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Wed, 27 Jul 2022 09:50:43 +0000 Subject: [PATCH 316/826] Fixing style errors. --- htdocs/admin/stock.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/admin/stock.php b/htdocs/admin/stock.php index bbd72667874..2b25d7deb5a 100644 --- a/htdocs/admin/stock.php +++ b/htdocs/admin/stock.php @@ -643,7 +643,7 @@ print ''."\n"; print ''; print ''.$langs->trans("MainDefaultWarehouse").''; print ''; -print $formproduct->selectWarehouses(!empty($conf->global->MAIN_DEFAULT_WAREHOUSE) ? $conf->global->MAIN_DEFAULT_WAREHOUSE : -1 , 'default_warehouse', '', 1, 0, 0, '', 0, 0, array(), 'left reposition'); +print $formproduct->selectWarehouses(!empty($conf->global->MAIN_DEFAULT_WAREHOUSE) ? $conf->global->MAIN_DEFAULT_WAREHOUSE : -1, 'default_warehouse', '', 1, 0, 0, '', 0, 0, array(), 'left reposition'); print ''; print ""; print "\n"; From 40cc55cf910637dfb6d1ce4a05e34ad25c9d3e16 Mon Sep 17 00:00:00 2001 From: Francis Appels Date: Wed, 27 Jul 2022 11:54:55 +0200 Subject: [PATCH 317/826] Fix wrong varname --- htdocs/core/modules/member/doc/pdf_standard.class.php | 4 ++-- .../core/modules/printsheet/doc/pdf_standardlabel.class.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/core/modules/member/doc/pdf_standard.class.php b/htdocs/core/modules/member/doc/pdf_standard.class.php index 842495c242d..91206c2dd9f 100644 --- a/htdocs/core/modules/member/doc/pdf_standard.class.php +++ b/htdocs/core/modules/member/doc/pdf_standard.class.php @@ -179,8 +179,8 @@ class pdf_standard extends CommonStickerGenerator $widthtouse = $maxwidthtouse; $heighttouse = round($widthtouse / $imgratio); } else { - $heightouse = $maxheighttouse; - $widthtouse = round($heightouse * $imgratio); + $heighttouse = $maxheighttouse; + $widthtouse = round($heighttouse * $imgratio); } } //var_dump($this->_Width.'x'.$this->_Height.' with border and scale '.$imgscale.' => max '.$maxwidthtouse.'x'.$maxheighttouse.' => We use '.$widthtouse.'x'.$heighttouse);exit; diff --git a/htdocs/core/modules/printsheet/doc/pdf_standardlabel.class.php b/htdocs/core/modules/printsheet/doc/pdf_standardlabel.class.php index bf1da990923..c1b93be6653 100644 --- a/htdocs/core/modules/printsheet/doc/pdf_standardlabel.class.php +++ b/htdocs/core/modules/printsheet/doc/pdf_standardlabel.class.php @@ -141,8 +141,8 @@ class pdf_standardlabel extends CommonStickerGenerator $widthtouse = $maxwidthtouse; $heighttouse = round($widthtouse / $imgratio); } else { - $heightouse = $maxheighttouse; - $widthtouse = round($heightouse * $imgratio); + $heighttouse = $maxheighttouse; + $widthtouse = round($heighttouse * $imgratio); } } //var_dump($this->_Width.'x'.$this->_Height.' with border and scale '.$imgscale.' => max '.$maxwidthtouse.'x'.$maxheighttouse.' => We use '.$widthtouse.'x'.$heighttouse);exit; From 5f03e91d9a9781b7914598605a820328ca6f13cb Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Wed, 27 Jul 2022 12:00:36 +0200 Subject: [PATCH 318/826] c --- ChangeLog | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 76709bd8f85..763d8a0920c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -30,25 +30,23 @@ For users: NEW: PHP 8.1 compatibility NEW: Support for recurring purchase invoices. NEW: #20292 Include German public holidays -NEW: Can show ZATCA QRCode on PDFs -NEW: Can show Swiss QR Code on PDFs +NEW: Can show ZATCA QR-Code on PDFs +NEW: Can show Swiss QR-Code on PDFs NEW: #17123 added ExtraFields for Stock Mouvement -NEW: #20609 : new massaction to assign a sale representatives on a selection of thirdparties +NEW: #20609 new massaction to assign a sale representatives on a selection of thirdparties NEW: #20653 edit discount pourcentage for all lines in one shot NEW: Accept 'auto' for ref of object on import of purchase order/proposal NEW: Accountancy - Add more filters and info on page to bind accounting accounts -NEW: Accountancy - Add subledger account when we generate a transaction with a deposit invoice +NEW: Accountancy - Add subledger account when generate a transaction with a deposit invoice NEW: Accountancy - Add a massaction to preselect an account (customer and supplier list) NEW: ACE Editor is restored at same cursor position after a save. NEW: Add "addMoreActionsButtons" hook to subscription form NEW: Add an option in GUI to show a Quick add button into top menu bar -NEW: Module Recruitment - Add a public page with all list of open job positions. -NEW: Module Recruitment - Add a tab with list of application on the jobposition file. NEW: Add a workflow to auto link contract on a ticket NEW: Add column date of Signature on proposal list NEW: Add column template invoice in invoice list NEW: Add column "Total HT" to products array on document creation card -NEW: ADD configuration for text color of button action +NEW: Add configuration for text color of button action NEW: Add constant to hide categories in TakePos NEW: Add constant to show category description in TakePos NEW: Add constant to show only the products in stock in TakePos @@ -56,7 +54,7 @@ NEW: Add entity filter in exports NEW: Show the event block on recurring invoices #20870 NEW: Add filter "opportunity status" on statistics of projects. NEW: Add firstname, lastname and max number of attendees for module "Event Organization" -NEW: add margin info in proposal and order list +NEW: Add margin info in proposal and order list NEW: Add massaction "Edit Extrafield" for Product NEW: Add more fields to detect duplicate during import of thirdparties NEW: Add option to foce delivery on email for purchase order receipt to yes @@ -67,14 +65,12 @@ NEW: Add possibility with constant MAIN_LOGIN_BADCHARUNAUTHORIZED to define bad NEW: Add private and public notes on tax files. NEW: Add status "Obsolete" to KM articles NEW: Add substitutions "user numbers" -NEW: Add the possibility to add sub-BOMs to BOM NEW: allow a ticket to be automatically marked as read when created from backend. NEW: allow cut&paste as real numeric value to excel NEW: A public form to send a message and create a lead is available NEW: automatically set totally received status in reception NEW: Auto set invoice paid when adding credit not and remain to pay is 0 NEW: Availibility dictionnary has a new column unit and number -NEW: barcode rule to insert product in takepos NEW: Can change value of AWP during the inventory NEW: Can enter price with tax for predefined products on purchase objects NEW: Can filter on a thirdparty on product statistics @@ -90,7 +86,7 @@ NEW: create third-party with contact if not found on public ticket NEW: Default value for MAIN_SECURITY_CSRF_WITH_TOKEN is now 2 (GET are also protected agains CSRF attacks) NEW: deposit payment terms: add field into dictionary admin page to define default percentage of deposit. NEW: Dictionaries - add possibility to manage countries in EEC -NEW: display errors in a message box after generating documents +NEW: Display errors in a message box after generating documents NEW: Display physical and virtual stock of the products when creating OF from a BOM NEW: Display product ref in "Object link" product tab for BOM NEW: Enhance the import. Can use 'auto' for the ref (import of orders) @@ -102,10 +98,13 @@ NEW: leave requests: add field into type dictionary to block request if balance NEW: MAIN_MAIL_AUTOCOPY_TO can accept several email and special keys NEW: MAIN_SEARCH_CAT_OR_BY_DEFAULT const for search by category NEW: Mass action "Close shipments" +NEW: Module BOM - Add tabs for nets Bom +NEW: Module BOM - Add the possibility to add sub-BOMs to BOM +NEW: Module Recruitment - Add a public page with all list of open job positions. +NEW: Module Recruitment - Add a tab with list of application on the jobposition file. NEW: Module website now supports the multicompany module NEW: More mode for THEME_TOPMENU_DISABLE_IMAGE (2, 3, ...) NEW: Add option to move checkbox column as first column on Thirdparty list (only few screens) -NEW: Add tabs for nets Bom NEW: on redirect of page in website module, GET parameters are kept. NEW: optional display warning icons on ticket list NEW: option to default check "notify tier at creation" in ticket module @@ -117,15 +116,15 @@ NEW: Send email to the supplier order contact NEW: New permission to report time on timesheet. NEW: SEPA XML - option to place payment Type Info at Credit transfer Transaction level NEW: Show number of votes into the label of tab "Results" of a survey -NEW: Show product reference in Takepos NEW: Some core tables are created only at module activation NEW: split consumption line on MO NEW: stock filter in reassort lists NEW: stock limit in stock export CSV -NEW: Sub-bom are availables NEW: Supplier order - Show ref supplier of reception in linked object block NEW: support user_modif in order -NEW: TakePos - pagination on search results +NEW: TakePOS - barcode rule to insert product in TakePOS +NEW: TakePOS - pagination on search results +NEW: TakePOS - show product reference NEW: The backup tools has an "lowmemory" option for mysqldump on large database NEW: The 'reposition' class works on ajax constantonoff that make redirects NEW: Thirdparty - Add rules "customer accountancy code" is mandatory to validate invoice @@ -140,7 +139,7 @@ NEW: Added MMK currency (Myanmar Kyat) Modules NEW: Module Partnership Management -NEW: Experimental module Event Organization Management +NEW: Experimental Module Event Organization Management For developers or integrators: @@ -155,7 +154,6 @@ NEW: Suggest a way to run upgrade per entities. NEW: Support html content for multiselect component. NEW: ModuleBuilder - Add tabs view in module builder NEW: ModuleBuilder - More feature that can be modifed after module generation -NEW: Hook getNomUrl available everywhere in tooltip of ref links NEW: Identification of tr is possible with by attribute data-id on some pages NEW: Import with select boxes V2 NEW: Can update rank of invoice, proposal and order lines with API update @@ -182,6 +180,9 @@ NEW: Add a protection into PHPunit to avoid to forget a var_dump NEW: Add datem and type parameters to API to create movements NEW: Add hidden option on contract PDF line to hide qty and price NEW: Option MAIL_MASS_ACTION_ADD_LAST_IF_MAIN_DOC_NOT_FOUND to send last document in mass mailing action + +Hooks: +NEW: Hook getNomUrl available everywhere in tooltip of ref links NEW: Add hooks: selectContactListWhere hook, selectThirdpartyListWhere hook NEW: TakePos - add hooks complete product display NEW: TakePos - add hooks for cart display From fc9b3e3d703c5032ebf1186a62d76c6b7757b6f6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 27 Jul 2022 13:42:32 +0200 Subject: [PATCH 319/826] Factorize code into a function dolJSToSetRandomPassword() --- htdocs/admin/agenda_xcal.php | 20 +++-------- htdocs/admin/clicktodial.php | 20 +++-------- htdocs/admin/eventorganization.php | 19 +++-------- htdocs/admin/hrm.php | 19 +++-------- htdocs/admin/mailing.php | 20 +++-------- htdocs/admin/webhook.php | 19 +++-------- htdocs/asset/admin/setup.php | 19 +++-------- htdocs/core/ajax/security.php | 9 +++-- htdocs/core/class/html.formsetup.class.php | 20 +++-------- htdocs/core/lib/security2.lib.php | 33 ++++++++++++++++++- htdocs/core/tpl/onlinepaymentlinks.tpl.php | 20 +++-------- htdocs/cron/admin/cron.php | 21 +++--------- .../install/mysql/migration/16.0.0-17.0.0.sql | 2 ++ htdocs/install/upgrade2.php | 1 + htdocs/user/card.php | 20 ++++------- htdocs/webservices/admin/index.php | 19 +++-------- 16 files changed, 96 insertions(+), 185 deletions(-) diff --git a/htdocs/admin/agenda_xcal.php b/htdocs/admin/agenda_xcal.php index ce36d97d06a..e3f2c7307f7 100644 --- a/htdocs/admin/agenda_xcal.php +++ b/htdocs/admin/agenda_xcal.php @@ -207,21 +207,11 @@ $message .= $langs->trans("AgendaUrlOptionsIncludeHolidays", '1', '1').'
'; print info_admin($message); -if (!empty($conf->use_javascript_ajax)) { - print "\n".''; -} +$constname = 'MAIN_AGENDA_XCAL_EXPORTKEY'; + +// Add button to autosuggest a key +include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; +print dolJSToSetRandomPassword($constname); // End of page llxFooter(); diff --git a/htdocs/admin/clicktodial.php b/htdocs/admin/clicktodial.php index a8d33ae5a09..8f98b4d25e9 100644 --- a/htdocs/admin/clicktodial.php +++ b/htdocs/admin/clicktodial.php @@ -188,22 +188,10 @@ if (!empty($conf->global->CLICKTODIAL_URL)) { } } -if (!empty($conf->use_javascript_ajax)) { - print "\n".''; -} +// Add button to autosuggest a key +include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; +print dolJSToSetRandomPassword('CLICKTODIAL_KEY_FOR_CIDLOOKUP'); + // End of page llxFooter(); diff --git a/htdocs/admin/eventorganization.php b/htdocs/admin/eventorganization.php index ee6c2ae6b52..05df4187130 100644 --- a/htdocs/admin/eventorganization.php +++ b/htdocs/admin/eventorganization.php @@ -273,21 +273,10 @@ if ($action == 'edit') { if (!empty($conf->use_javascript_ajax)) { print ' '.img_picto($langs->trans('Generate'), 'refresh', 'id="generate_token'.$constname.'" class="linkobject"'); } - if (!empty($conf->use_javascript_ajax)) { - print "\n".''; - } + + // Add button to autosuggest a key + include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; + print dolJSToSetRandomPassword($constname, 'generate_token'.$constname); } elseif ($val['type'] == 'product') { if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { $selected = (empty($conf->global->$constname) ? '' : $conf->global->$constname); diff --git a/htdocs/admin/hrm.php b/htdocs/admin/hrm.php index b1b74189d35..cfe40c006b7 100644 --- a/htdocs/admin/hrm.php +++ b/htdocs/admin/hrm.php @@ -540,21 +540,10 @@ if ($action == 'edit') { if (!empty($conf->use_javascript_ajax)) { print ' '.img_picto($langs->trans('Generate'), 'refresh', 'id="generate_token'.$constname.'" class="linkobject"'); } - if (!empty($conf->use_javascript_ajax)) { - print "\n".''; - } + + // Add button to autosuggest a key + include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; + print dolJSToSetRandomPassword($constname, 'generate_token'.$constname); } elseif ($val['type'] == 'product') { if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { $selected = (empty($conf->global->$constname) ? '' : $conf->global->$constname); diff --git a/htdocs/admin/mailing.php b/htdocs/admin/mailing.php index 37735a43ed3..da2df89b21a 100644 --- a/htdocs/admin/mailing.php +++ b/htdocs/admin/mailing.php @@ -107,21 +107,11 @@ llxHeader('', $langs->trans("MailingSetup")); $linkback = '
'.$langs->trans("BackToModuleList").''; print load_fiche_titre($langs->trans("MailingSetup"), $linkback, 'title_setup'); -if (!empty($conf->use_javascript_ajax)) { - print "\n".''; -} +$constname = 'MAILING_EMAIL_UNSUBSCRIBE_KEY'; + +// Add button to autosuggest a key +include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; +print dolJSToSetRandomPassword($constname); print '
'; print '
'; diff --git a/htdocs/admin/webhook.php b/htdocs/admin/webhook.php index 963b76c238a..9dec7a8eeec 100644 --- a/htdocs/admin/webhook.php +++ b/htdocs/admin/webhook.php @@ -338,21 +338,10 @@ if ($action == 'edit') { if (!empty($conf->use_javascript_ajax)) { print ' '.img_picto($langs->trans('Generate'), 'refresh', 'id="generate_token'.$constname.'" class="linkobject"'); } - if (!empty($conf->use_javascript_ajax)) { - print "\n".''; - } + + // Add button to autosuggest a key + include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; + print dolJSToSetRandomPassword($constname, 'generate_token'.$constname); } elseif ($val['type'] == 'product') { if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { $selected = (empty($conf->global->$constname) ? '' : $conf->global->$constname); diff --git a/htdocs/asset/admin/setup.php b/htdocs/asset/admin/setup.php index 29ee4b074fb..448473003b3 100644 --- a/htdocs/asset/admin/setup.php +++ b/htdocs/asset/admin/setup.php @@ -519,21 +519,10 @@ if ($action == 'edit') { if (!empty($conf->use_javascript_ajax)) { print ' '.img_picto($langs->trans('Generate'), 'refresh', 'id="generate_token'.$constname.'" class="linkobject"'); } - if (!empty($conf->use_javascript_ajax)) { - print "\n".''; - } + + // Add button to autosuggest a key + include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; + print dolJSToSetRandomPassword($constname, 'generate_token'.$constname); } elseif ($val['type'] == 'product') { if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { $selected = (empty($conf->global->$constname) ? '' : $conf->global->$constname); diff --git a/htdocs/core/ajax/security.php b/htdocs/core/ajax/security.php index 0056120c6bd..1f2143d4b72 100644 --- a/htdocs/core/ajax/security.php +++ b/htdocs/core/ajax/security.php @@ -42,6 +42,9 @@ if (!defined('NOREQUIRETRAN')) { require '../../main.inc.php'; +$action = GETPOST('action'); + + /* * View */ @@ -52,10 +55,10 @@ top_httphead(); //print ''."\n"; // Registering the location of boxes -if (isset($_GET['action']) && !empty($_GET['action'])) { - if ($_GET['action'] == 'getrandompassword' && ($user->admin || $user->rights->api->apikey->generate)) { +if ($action) { + if ($action == 'getrandompassword' && ($user->admin || $user->rights->api->apikey->generate)) { require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; - $generic = $_GET['generic'] ? true : false; + $generic = GETPOST('generic') ? true : false; echo getRandomPassword($generic); } } diff --git a/htdocs/core/class/html.formsetup.class.php b/htdocs/core/class/html.formsetup.class.php index 1cfddb588fd..2dd729df91d 100644 --- a/htdocs/core/class/html.formsetup.class.php +++ b/htdocs/core/class/html.formsetup.class.php @@ -952,21 +952,11 @@ class FormSetupItem if (!empty($conf->use_javascript_ajax)) { $out.= ' '.img_picto($this->langs->trans('Generate'), 'refresh', 'id="generate_token'.$this->confKey.'" class="linkobject"'); } - if (!empty($conf->use_javascript_ajax)) { - $out .= "\n" . ''; - } + + // Add button to autosuggest a key + include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; + $out .= dolJSToSetRandomPassword($this->confKey, 'generate_token'.$this->confKey); + return $out; } diff --git a/htdocs/core/lib/security2.lib.php b/htdocs/core/lib/security2.lib.php index 4b70419630f..8f4abca6167 100644 --- a/htdocs/core/lib/security2.lib.php +++ b/htdocs/core/lib/security2.lib.php @@ -449,7 +449,7 @@ function encodedecode_dbpassconf($level = 0) * @param array $replaceambiguouschars Discard ambigous characters. For example array('I'). * @param int $length Length of random string (Used only if $generic is true) * @return string New value for password - * @see dol_hash() + * @see dol_hash(), dolJSToSetRandomPassword() */ function getRandomPassword($generic = false, $replaceambiguouschars = null, $length = 32) { @@ -527,3 +527,34 @@ function getRandomPassword($generic = false, $replaceambiguouschars = null, $len return $generated_password; } + +/** + * Ouput javacript to autoset a generated password using default module into a HTML element. + * + * @param string $htmlname HTML name of element to insert key into + * @param string $htmlnameofbutton HTML name of button + * @return string HTML javascript code to set a password + * @see getRandomPassword() + */ +function dolJSToSetRandomPassword($htmlname, $htmlnameofbutton = 'generate_token') +{ + global $conf; + + if (!empty($conf->use_javascript_ajax)) { + print "\n".''; + } +} diff --git a/htdocs/core/tpl/onlinepaymentlinks.tpl.php b/htdocs/core/tpl/onlinepaymentlinks.tpl.php index e355f9654a3..657d32a0a36 100644 --- a/htdocs/core/tpl/onlinepaymentlinks.tpl.php +++ b/htdocs/core/tpl/onlinepaymentlinks.tpl.php @@ -141,21 +141,11 @@ if (!empty($conf->don->enabled)) { print '
'; } -if (!empty($conf->use_javascript_ajax)) { - print "\n".''; -} +$constname = 'PAYMENT_SECURITY_TOKEN'; + +// Add button to autosuggest a key +include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; +print dolJSToSetRandomPassword($constname); print info_admin($langs->trans("YouCanAddTagOnUrl")); diff --git a/htdocs/cron/admin/cron.php b/htdocs/cron/admin/cron.php index ff413a8a1c2..d214c112aa3 100644 --- a/htdocs/cron/admin/cron.php +++ b/htdocs/cron/admin/cron.php @@ -129,22 +129,11 @@ dol_print_cron_urls(); print '
'; -if (!empty($conf->use_javascript_ajax)) { - print "\n".''; -} +$constname = 'CRON_KEY'; + +// Add button to autosuggest a key +include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; +print dolJSToSetRandomPassword($constname); llxFooter(); $db->close(); diff --git a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql index 2362036c93a..6713d410fc6 100644 --- a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql +++ b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql @@ -41,12 +41,14 @@ ALTER TABLE llx_c_email_templates ADD COLUMN email_from varchar(255); ALTER TABLE llx_c_email_templates ADD COLUMN email_to varchar(255); ALTER TABLE llx_c_email_templates ADD COLUMN email_tocc varchar(255); ALTER TABLE llx_c_email_templates ADD COLUMN email_tobcc varchar(255); +ALTER TABLE llx_c_email_templates ADD COLUMN content_lines text; ALTER TABLE llx_expedition ADD COLUMN billed smallint DEFAULT 0; ALTER TABLE llx_accounting_system MODIFY COLUMN pcg_version varchar(32) NOT NULL; + -- v17 ALTER TABLE llx_facture ADD COLUMN close_missing_amount double(24, 8) after close_code; diff --git a/htdocs/install/upgrade2.php b/htdocs/install/upgrade2.php index 30e7b45d198..66200898e95 100644 --- a/htdocs/install/upgrade2.php +++ b/htdocs/install/upgrade2.php @@ -4116,6 +4116,7 @@ function migrate_delete_old_files($db, $langs, $conf) '/core/boxes/box_members.php', '/api/class/api_generic.class.php', + '/asterisk/cidlookup.php', '/categories/class/api_category.class.php', '/categories/class/api_deprecated_category.class.php', '/compta/facture/class/api_invoice.class.php', diff --git a/htdocs/user/card.php b/htdocs/user/card.php index c4f1be97eb8..3015657252b 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -2834,20 +2834,12 @@ if ($action == 'create' || $action == 'adduserldap') { } } -if (!empty($conf->api->enabled) && !empty($conf->use_javascript_ajax)) { - print "\n".''; +if (!empty($conf->api->enabled)) { + $constname = 'api_key'; + + // Add button to autosuggest a key + include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; + print dolJSToSetRandomPassword($constname, 'generate_api_key'); } // End of page diff --git a/htdocs/webservices/admin/index.php b/htdocs/webservices/admin/index.php index 14af2e88b3f..8ae62d1bf3c 100644 --- a/htdocs/webservices/admin/index.php +++ b/htdocs/webservices/admin/index.php @@ -140,21 +140,10 @@ print '
'; print '
'; print $langs->trans("OnlyActiveElementsAreShown", DOL_URL_ROOT.'/admin/modules.php'); -if (!empty($conf->use_javascript_ajax)) { - print "\n".''; -} +$constname = 'WEBSERVICES_KEY'; + +print dolJSToSetRandomPassword($constname); + // End of page llxFooter(); From 267ea10f080125e38121daf2fa8826699ba5b1aa Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 27 Jul 2022 13:42:59 +0200 Subject: [PATCH 320/826] Fix missing link to public interface --- htdocs/recruitment/admin/public_interface.php | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/htdocs/recruitment/admin/public_interface.php b/htdocs/recruitment/admin/public_interface.php index b951f440005..7212a687442 100644 --- a/htdocs/recruitment/admin/public_interface.php +++ b/htdocs/recruitment/admin/public_interface.php @@ -139,12 +139,12 @@ print dol_get_fiche_end(); print ''; -/* + if (!empty($conf->global->RECRUITMENT_ENABLE_PUBLIC_INTERFACE)) { print '
'; //print $langs->trans('FollowingLinksArePublic').'
'; - print img_picto('', 'globe').' '.$langs->trans('BlankSubscriptionForm').':
'; - if ($conf->multicompany->enabled) { + print img_picto('', 'globe').' '.$langs->trans('BlankSubscriptionForm').'
'; + if (!empty($conf->multicompany->enabled)) { $entity_qr = '?entity='.$conf->entity; } else { $entity_qr = ''; @@ -155,9 +155,12 @@ if (!empty($conf->global->RECRUITMENT_ENABLE_PUBLIC_INTERFACE)) { $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current - print ''.$urlwithroot.'/public/members/new.php'.$entity_qr.''; + print ''; + print ajax_autoselect('publicurlmember'); } -*/ // End of page llxFooter(); From e1cd297d99f7a1b6768815a8e15b965b50c98328 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 27 Jul 2022 13:49:28 +0200 Subject: [PATCH 321/826] css --- htdocs/user/card.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/user/card.php b/htdocs/user/card.php index 3015657252b..546104cc01e 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -833,7 +833,7 @@ if ($action == 'create' || $action == 'adduserldap') { print ''; // Civility - print ''; @@ -2077,7 +2077,7 @@ if ($action == 'create' || $action == 'adduserldap') { } // Civility - print ' --- htdocs/admin/tools/dolibarr_export.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/admin/tools/dolibarr_export.php b/htdocs/admin/tools/dolibarr_export.php index 0cde0348314..1a68b17c3e0 100644 --- a/htdocs/admin/tools/dolibarr_export.php +++ b/htdocs/admin/tools/dolibarr_export.php @@ -195,6 +195,7 @@ print ''; print ''; print ''; +print ''; print ''; print ''; // Group @@ -219,12 +219,12 @@ class FormTicket if ($public) { $filter = 'public=1'; } - $this->selectGroupTickets((GETPOST('category_code') ? GETPOST('category_code') : $this->category_code), 'category_code', $filter, 2, 0, 0, 0, 'minwidth200'); + $this->selectGroupTickets((GETPOST('category_code') ? GETPOST('category_code') : $this->category_code), 'category_code', $filter, 2, $conf->global->TICKET_FORCE_DISPLAY_EMPTY_OPTION, 0, 0, 'minwidth200'); print ''; // Severity print ''; // Subject diff --git a/htdocs/ticket/card.php b/htdocs/ticket/card.php index 7decdeadd7b..8754c40ac99 100644 --- a/htdocs/ticket/card.php +++ b/htdocs/ticket/card.php @@ -171,7 +171,19 @@ if (empty($reshook)) { if (GETPOST('save', 'alpha') && !empty($user->rights->ticket->write)) { $error = 0; - if (!GETPOST("subject", 'alphanohtml')) { + if (!GETPOST("type_code", 'alpha')) { + $error++; + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("TicketTypeRequest")), null, 'errors'); + $action = 'create'; + } elseif (!GETPOST("category_code", 'alpha')) { + $error++; + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("TicketCategory")), null, 'errors'); + $action = 'create'; + } elseif (!GETPOST("severity_code", 'alpha')) { + $error++; + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("TicketSeverity")), null, 'errors'); + $action = 'create'; + } elseif (!GETPOST("subject", 'alphanohtml')) { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Subject")), null, 'errors'); $action = 'create'; From 29cb21fdabeb7e2026598ccd0da2ef477f837026 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Wed, 27 Jul 2022 17:48:10 +0200 Subject: [PATCH 324/826] FIX - php V8 functions lib dolGetButtonAction --- htdocs/core/lib/functions.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 61a603f48bd..1eb72d50455 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -10422,7 +10422,7 @@ function dolGetButtonAction($label, $html = '', $actionType = 'default', $url = global $hookmanager, $action, $object, $langs; //var_dump($params); - if ($params['isDropdown']) + if (isset($params['isDropdown'])) $class = "dropdown-item"; else { $class = 'butAction'; From 31d4d0dcd42c56c2664e029b04ba23e566325f51 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Wed, 27 Jul 2022 18:09:11 +0200 Subject: [PATCH 325/826] FIX - php V8 user right in propal card and use $user->hasRight --- htdocs/comm/propal/card.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 06c36ce517c..f1a92d032cf 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -120,9 +120,9 @@ $usercanclose = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $usercancreat $usercanvalidate = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $usercancreate) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->propal->propal_advance->validate))); $usercansend = (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->propal->propal_advance->send))); -$usercancreateorder = $user->rights->commande->creer; -$usercancreateinvoice = $user->rights->facture->creer; -$usercancreatecontract = $user->rights->contrat->creer; +$usercancreateorder = $user->hasRight('commande', 'creer'); +$usercancreateinvoice = $user->hasRight('facture', 'creer'); +$usercancreatecontract = $user->hasRight('contrat', 'creer'); $usercancreateintervention = $user->hasRight('ficheinter', 'creer'); $usercancreatepurchaseorder = ($user->hasRight('fournisseur', 'commande', 'creer') || $user->hasRight('supplier_order', 'creer')); From c5e5f2915e600b80c4ba6d8b809e06ff69d934fe Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 27 Jul 2022 19:01:26 +0200 Subject: [PATCH 326/826] Look and feel v17 --- htdocs/core/lib/functions.lib.php | 2 +- htdocs/langs/en_US/website.lang | 5 +++++ htdocs/theme/eldy/global.inc.php | 1 + htdocs/theme/md/style.css.php | 1 + htdocs/website/index.php | 35 +++++++++++++++++-------------- 5 files changed, 27 insertions(+), 17 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 61a603f48bd..b286adae481 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -1718,7 +1718,7 @@ function dolButtonToOpenUrlInDialogPopup($name, $label, $buttonstring, $url, $di //print ''; $out .= ''."\n"; - $out .= ''.$buttonstring.''; + $out .= ''.$buttonstring.''; $out .= ''; $out .= ''; $out .= ''; diff --git a/htdocs/langs/en_US/website.lang b/htdocs/langs/en_US/website.lang index b5ef14bd118..59a23e65d9b 100644 --- a/htdocs/langs/en_US/website.lang +++ b/htdocs/langs/en_US/website.lang @@ -1,5 +1,6 @@ # Dolibarr language file - Source file is en_US - website Shortname=Code +WebsiteName=Name of the website WebsiteSetupDesc=Create here the websites you wish to use. Then go into menu Websites to edit them. DeleteWebsite=Delete website ConfirmDeleteWebsite=Are you sure you want to delete this web site? All its pages and content will also be removed. The files uploaded (like into the medias directory, the ECM module, ...) will remain. @@ -42,6 +43,8 @@ ViewPageInNewTab=View page in new tab SetAsHomePage=Set as Home page RealURL=Real URL ViewWebsiteInProduction=View web site using home URLs +Virtualhost=Virtual host or domain name +VirtualhostDesc=The name of the Virtual host or domain (For example: www.mywebsite.com, mybigcompany.net, ...) SetHereVirtualHost=Use with Apache/NGinx/...
Create on your web server (Apache, Nginx, ...) a dedicated Virtual Host with PHP enabled and a Root directory on
%s ExampleToUseInApacheVirtualHostConfig=Example to use in Apache virtual host setup: YouCanAlsoTestWithPHPS=Use with PHP embedded server
On develop environment, you may prefer to test the site with the PHP embedded web server (PHP 5.5 required) by running
php -S 0.0.0.0:8080 -t %s @@ -145,3 +148,5 @@ ImportFavicon=Favicon ErrorFaviconType=Favicon must be png ErrorFaviconSize=Favicon must be sized 16x16, 32x32 or 64x64 FaviconTooltip=Upload an image which needs to be a png (16x16, 32x32 or 64x64) +NextContainer=Next page/container +PreviousContainer=Previous page/container diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index 6a2ce22fa68..2074325c6e4 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -5143,6 +5143,7 @@ span[phptag] { } .centpercent.websitebar { width: calc(100% - 10px); + font-size: 0.94em; } .websitebar .buttonDelete, .websitebar .button { text-shadow: none; diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 03e9565db21..81c3941d434 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -4992,6 +4992,7 @@ span[phptag] { } .centpercent.websitebar { width: calc(100% - 10px); + font-size: 0.94em; } .websitebar .buttonDelete, .websitebar .button { text-shadow: none; diff --git a/htdocs/website/index.php b/htdocs/website/index.php index 2b3eedf995f..b05cfe51eed 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -2933,12 +2933,12 @@ if (!GETPOST('hide_websitemenu')) { if ($pagepreviousid) { print ''.img_previous($langs->trans("PreviousContainer")).''; } else { - print ''.img_previous($langs->trans("Previous")).''; + print ''.img_previous($langs->trans("PreviousContainer")).''; } if ($pagenextid) { print ''.img_next($langs->trans("NextContainer")).''; } else { - print ''.img_next($langs->trans("Next")).''; + print ''.img_next($langs->trans("NextContainer")).''; } print ''; @@ -3547,7 +3547,7 @@ if ($action == 'createsite') { } print ''."\n"; - //print '
'; + print '
'; print '
'; + print '
'; print $formcompany->select_civility(GETPOSTISSET("civility_code") ? GETPOST("civility_code", 'aZ09') : $object->civility_code, 'civility_code'); print '
'; + print '
'; if ($caneditfield && !$object->ldap_sid) { print $formcompany->select_civility(GETPOSTISSET("civility_code") ? GETPOST("civility_code", 'aZ09') : $object->civility_code, 'civility_code'); } elseif ($object->civility_code) { From f1b3f51b3a3a901f33db90161fe81c8c6b3bf638 Mon Sep 17 00:00:00 2001 From: bagtaib Date: Wed, 27 Jul 2022 14:14:34 +0200 Subject: [PATCH 322/826] add missing
'; print '
'; From 209db182b3c0a2c09f9bc69de21c539bf8332732 Mon Sep 17 00:00:00 2001 From: Franck Lauby Date: Wed, 27 Jul 2022 17:03:45 +0200 Subject: [PATCH 323/826] give the possibility to leave the "Request type", "Ticket categorization" and "Severity" selectors empty --- htdocs/core/class/html.formticket.class.php | 6 +++--- htdocs/ticket/card.php | 14 +++++++++++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/htdocs/core/class/html.formticket.class.php b/htdocs/core/class/html.formticket.class.php index 6866bfa8356..05ecdf3a005 100644 --- a/htdocs/core/class/html.formticket.class.php +++ b/htdocs/core/class/html.formticket.class.php @@ -210,7 +210,7 @@ class FormTicket // Type print '
'; - $this->selectTypesTickets((GETPOST('type_code', 'alpha') ? GETPOST('type_code', 'alpha') : $this->type_code), 'type_code', '', 2, 0, 0, 0, 'minwidth200'); + $this->selectTypesTickets((GETPOST('type_code', 'alpha') ? GETPOST('type_code', 'alpha') : $this->type_code), 'type_code', '', 2, $conf->global->TICKET_FORCE_DISPLAY_EMPTY_OPTION, 0, 0, 'minwidth200'); print '
'; - $this->selectSeveritiesTickets((GETPOST('severity_code') ? GETPOST('severity_code') : $this->severity_code), 'severity_code', '', 2, 0); + $this->selectSeveritiesTickets((GETPOST('severity_code') ? GETPOST('severity_code') : $this->severity_code), 'severity_code', '', 2, $conf->global->TICKET_FORCE_DISPLAY_EMPTY_OPTION); print '
'; @@ -3566,7 +3566,7 @@ if ($action == 'createsite') { } print ''; @@ -3575,9 +3575,18 @@ if ($action == 'createsite') { print $langs->trans('MainLanguage'); print ''; + print ''; + print ''; print ''; - print ''; - print '
'; - print $form->textwithpicto($langs->trans('WebSite'), $langs->trans("Example").': www.mywebsite.com, myportal, ...'); + print $form->textwithpicto($langs->trans('WebsiteName'), $langs->trans("Example").': MyPortal, www.mywebsite.com, ...'); print ''; print ''; print '
'; $shortlangcode = preg_replace('/[_-].*$/', '', trim($langs->defaultlang)); + print img_picto('', 'language', 'class="pictofixedwidth"'); print $formadmin->select_language((GETPOSTISSET('WEBSITE_LANG') ? GETPOST('WEBSITE_LANG', 'aZ09comma') : $shortlangcode), 'WEBSITE_LANG', 0, null, 1, 0, 0, 'minwidth300', 2, 0, 0, array(), 1); print '
'; + $htmltext = $langs->trans("Example").': fr,de,sv,it,pt'; + print $form->textwithpicto($langs->trans('OtherLanguages'), $htmltext, 1, 'help', '', 0, 2); + print ''; + print img_picto('', 'language', 'class="pictofixedwidth"'); + print ''; + print '
'; print $langs->trans('Description'); print ''; @@ -3585,28 +3594,22 @@ if ($action == 'createsite') { print '
'; - $htmltext = $langs->trans("Example").': fr,de,sv,it,pt'; - print $form->textwithpicto($langs->trans('OtherLanguages'), $htmltext, 1, 'help', '', 0, 2); - print ''; - print ''; - print '
'; - - $htmltext = $langs->trans("SetHereVirtualHost", '{s1}'); - $htmltext = str_replace('{s1}', DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/websiteref', $htmltext); + $htmltext = $langs->trans("VirtualhostDesc"); + /*$htmltext = str_replace('{s1}', DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/websiteref', $htmltext); $htmltext .= '
'; $htmltext .= '
'.$langs->trans("CheckVirtualHostPerms", $langs->transnoentitiesnoconv("ReadPerm"), DOL_DOCUMENT_ROOT); $htmltext .= '
'.$langs->trans("CheckVirtualHostPerms", $langs->transnoentitiesnoconv("WritePerm"), '{s1}'); - $htmltext = str_replace('{s1}', DOL_DATA_ROOT.'/website
'.DOL_DATA_ROOT.'/medias', $htmltext); + $htmltext = str_replace('{s1}', DOL_DATA_ROOT.'/website
'.DOL_DATA_ROOT.'/medias', $htmltext);*/ - print $form->textwithpicto($langs->trans('Virtualhost'), $htmltext, 1, 'help', '', 0, 2, 'virtualhosttooltip'); + + print $form->textwithpicto($langs->trans('Virtualhost'), $htmltext, 1, 'help', '', 0, 2, ''); print '
'; print ''; print '
'; + print ''; if ($action == 'createsite') { print '
'; From 5e94e464617080fced85839689a160088bf6ce6e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 27 Jul 2022 20:11:57 +0200 Subject: [PATCH 327/826] Trans --- htdocs/website/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/website/index.php b/htdocs/website/index.php index b05cfe51eed..d2015df83b5 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -587,7 +587,7 @@ if ($action == 'addsite' && $usercanedit) { if (!$error && !GETPOST('WEBSITE_REF', 'alpha')) { $error++; $langs->load("errors"); - setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->transnoentities("Ref")), null, 'errors'); + setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->transnoentities("WebsiteName")), null, 'errors'); } if (!$error && !preg_match('/^[a-z0-9_\-\.]+$/i', GETPOST('WEBSITE_REF', 'alpha'))) { $error++; From 37c725fc6c9f83cbec60b5d54723e0e51f2ac144 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 27 Jul 2022 23:01:33 +0200 Subject: [PATCH 328/826] NEW Can delete a website even if not empty --- htdocs/core/class/html.form.class.php | 5 +-- htdocs/langs/en_US/errors.lang | 3 +- .../template/class/myobject.class.php | 2 +- htdocs/website/class/website.class.php | 31 +++++++++---------- htdocs/website/index.php | 12 +++++-- 5 files changed, 30 insertions(+), 23 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index d31cdda5770..82e73186233 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -4914,8 +4914,9 @@ class Form * @param string $question Question * @param string $action Action * @param array|string $formquestion An array with complementary inputs to add into forms: array(array('label'=> ,'type'=> , 'size'=>, 'morecss'=>, 'moreattr'=>'autofocus' or 'style=...')) - * 'type' can be 'hidden', 'text', 'password', 'checkbox', 'radio', 'date', 'select', 'multiselect', 'morecss', 'other' or 'onecolumn'... - * @param string $selectedchoice '' or 'no', or 'yes' or '1' or '0' + * 'type' can be 'text', 'password', 'checkbox', 'radio', 'date', 'select', 'multiselect', 'morecss', + * 'other', 'onecolumn' or 'hidden'... + * @param int|string $selectedchoice '' or 'no', or 'yes' or '1', 1, '0' or 0 * @param int|string $useajax 0=No, 1=Yes, 2=Yes but submit page with &confirm=no if choice is No, 'xxx'=Yes and preoutput confirm box with div id=dialog-confirm-xxx * @param int|string $height Force height of box (0 = auto) * @param int $width Force width of box ('999' or '90%'). Ignored and forced to 90% on smartphones. diff --git a/htdocs/langs/en_US/errors.lang b/htdocs/langs/en_US/errors.lang index 7e29572c9f5..5326a0f11d1 100644 --- a/htdocs/langs/en_US/errors.lang +++ b/htdocs/langs/en_US/errors.lang @@ -324,7 +324,8 @@ WarningAvailableOnlyForHTTPSServers=Available only if using HTTPS secured connec WarningModuleXDisabledSoYouMayMissEventHere=Module %s has not been enabled. So you may miss a lot of event here. WarningPaypalPaymentNotCompatibleWithStrict=The value 'Strict' makes the online payment features not working correctly. Use 'Lax' instead. WarningThemeForcedTo=Warning, theme has been forced to %s by hidden constant MAIN_FORCETHEME - +WarningPagesWillBeDeleted=Warning, this will also delete all existing pages/containers of the website. You should export your website before, so you have a backup to re-import it later. + # Validate RequireValidValue = Value not valid RequireAtLeastXString = Requires at least %s character(s) diff --git a/htdocs/modulebuilder/template/class/myobject.class.php b/htdocs/modulebuilder/template/class/myobject.class.php index 767cb1105fc..664eb44d5f6 100644 --- a/htdocs/modulebuilder/template/class/myobject.class.php +++ b/htdocs/modulebuilder/template/class/myobject.class.php @@ -524,7 +524,7 @@ class MyObject extends CommonObject * Delete object in database * * @param User $user User that deletes - * @param bool $notrigger false=launch triggers after, true=disable triggers + * @param bool $notrigger false=launch triggers, true=disable triggers * @return int <0 if KO, >0 if OK */ public function delete(User $user, $notrigger = false) diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index 3cb5386e831..0e062b038a0 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -30,6 +30,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; //require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php'; //require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; + /** * Class Website */ @@ -50,6 +51,10 @@ class Website extends CommonObject */ public $ismultientitymanaged = 1; + + protected $childtablesoncascade = array(); + + /** * @var string String with name of icon for website. Must be the part after the 'object_' into object_myobject.png */ @@ -580,8 +585,8 @@ class Website extends CommonObject /** * Delete object in database * - * @param User $user User that deletes - * @param bool $notrigger false=launch triggers after, true=disable triggers + * @param User $user User that deletes + * @param bool $notrigger false=launch triggers, true=disable triggers * * @return int <0 if KO, >0 if OK */ @@ -596,20 +601,8 @@ class Website extends CommonObject $this->db->begin(); if (!$error) { - if (!$notrigger) { - // Uncomment this and change WEBSITE to your own tag if you - // want this action calls a trigger. - - //// Call triggers - //$result=$this->call_trigger('WEBSITE_DELETE',$user); - //if ($result < 0) { $error++; //Do also what you must do to rollback action if trigger fail} - //// End call triggers - } - } - - if (!$error) { - $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element; - $sql .= ' WHERE rowid='.((int) $this->id); + $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'website_page'; + $sql .= ' WHERE fk_website = '.((int) $this->id); $resql = $this->db->query($sql); if (!$resql) { @@ -619,6 +612,12 @@ class Website extends CommonObject } } + // Delete common code. This include execution of trigger. + $result = $this->deleteCommon($user, $notrigger); + if ($result <= 0) { + $error++; + } + if (!$error && !empty($this->ref)) { $pathofwebsite = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/'.$this->ref; diff --git a/htdocs/website/index.php b/htdocs/website/index.php index d2015df83b5..35591c3447d 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -1230,7 +1230,7 @@ if ($action == 'confirm_deletesite' && $confirm == 'yes' && $permissiontodelete) exit; } else { $db->rollback(); - dol_print_error($db); + setEventMessages($object->error, $object->errors, 'errors'); } } @@ -2741,7 +2741,8 @@ if (!GETPOST('hide_websitemenu')) { print ''; - print ''; + //print ''; + print ''; // Regenerate all pages print 'ref).'" class="button bordertransp"'.$disabled.' title="'.dol_escape_htmltag($langs->trans("RegenerateWebsiteContent")).'">'; @@ -2964,7 +2965,12 @@ if (!GETPOST('hide_websitemenu')) { //array('type' => 'other','name' => 'newwebsite','label' => $langs->trans("WebSite"), 'value' => $formwebsite->selectWebsite($object->id, 'newwebsite', 0)) ); - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteWebsite'), '', 'confirm_deletesite', $formquestion, 0, 1, 200); + if ($atleastonepage) { + $langs->load("errors"); + $formquestion[] = array('type' => 'onecolumn', 'value' => '
'.$langs->trans("WarningPagesWillBeDeleted").'
'); + } + + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteWebsite'), '', 'confirm_deletesite', $formquestion, 0, 1, 210 + ($atleastonepage ? 70 : 0), 580); print $formconfirm; } From 630dced71cb668bac9274ed0efe020be130cad7e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 27 Jul 2022 23:09:29 +0200 Subject: [PATCH 329/826] Look and feel v17 --- htdocs/website/index.php | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/htdocs/website/index.php b/htdocs/website/index.php index 35591c3447d..90277e59594 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -1,5 +1,5 @@ +/* Copyright (C) 2016-2022 Laurent Destailleur * Copyright (C) 2020 Nicolas ZABOURI * * This program is free software; you can redistribute it and/or modify @@ -3385,6 +3385,7 @@ if ($action == 'editcss') { $htmltext = ''; print $form->textwithpicto($langs->trans('MainLanguage'), $htmltext, 1, 'help', '', 0, 2, 'WEBSITE_LANG'); print ''; + print img_picto('', 'language', 'class="picotfixedwidth"'); print $formadmin->select_language((GETPOSTISSET('WEBSITE_LANG') ? GETPOST('WEBSITE_LANG', 'aZ09comma') : ($object->lang ? $object->lang : '0')), 'WEBSITE_LANG', 0, null, 1, 0, 0, 'minwidth300', 2, 0, 0, array(), 1); print ''; print ''; @@ -3394,6 +3395,7 @@ if ($action == 'editcss') { $htmltext = $langs->trans("Example").': fr,de,sv,it,pt'; print $form->textwithpicto($langs->trans('OtherLanguages'), $htmltext, 1, 'help', '', 0, 2); print ''; + print img_picto('', 'language', 'class="picotfixedwidth"'); print ''; print ''; print ''; @@ -3401,13 +3403,7 @@ if ($action == 'editcss') { // VirtualHost print ''; - $htmltext = $langs->trans("SetHereVirtualHost", DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/{s1}'.$websitekey.'{s2}'); - $htmltext = str_replace(array('{s1}', '{s2}'), array('', ''), $htmltext); - $htmltext .= '
'; - $htmltext .= '
'.$langs->trans("CheckVirtualHostPerms", $langs->transnoentitiesnoconv("ReadPerm"), DOL_DOCUMENT_ROOT); - $htmltext .= '
'.$langs->trans("CheckVirtualHostPerms", $langs->transnoentitiesnoconv("WritePerm"), '{s1}'); - $htmltext = str_replace('{s1}', DOL_DATA_ROOT.'/website
'.DOL_DATA_ROOT.'/medias', $htmltext); - + $htmltext = $langs->trans("VirtualhostDesc"); print $form->textwithpicto($langs->trans('Virtualhost'), $htmltext, 1, 'help', '', 0, 2, 'virtualhosttooltip'); print ''; print ''; From 2020a58ebd8db13f0bf6801caa735db33915438a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 28 Jul 2022 10:47:36 +0200 Subject: [PATCH 330/826] Fix fatal error in Stripe setup page --- htdocs/langs/en_US/stripe.lang | 3 +- htdocs/stripe/admin/stripe.php | 53 +++++++++++++++++++--------------- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/htdocs/langs/en_US/stripe.lang b/htdocs/langs/en_US/stripe.lang index 0a376ca9fb1..3ea0cf2354b 100644 --- a/htdocs/langs/en_US/stripe.lang +++ b/htdocs/langs/en_US/stripe.lang @@ -68,4 +68,5 @@ ToOfferALinkForTestWebhook=Link to setup Stripe WebHook to call the IPN (test mo ToOfferALinkForLiveWebhook=Link to setup Stripe WebHook to call the IPN (live mode) PaymentWillBeRecordedForNextPeriod=Payment will be recorded for the next period. ClickHereToTryAgain=Click here to try again... -CreationOfPaymentModeMustBeDoneFromStripeInterface=Due to Strong Customer Authentication rules, creation of a card must be done from Stripe backoffice. You can click here to switch on Stripe customer record: %s \ No newline at end of file +CreationOfPaymentModeMustBeDoneFromStripeInterface=Due to Strong Customer Authentication rules, creation of a card must be done from Stripe backoffice. You can click here to switch on Stripe customer record: %s +TERMINAL_LOCATION=Location (address) for terminals \ No newline at end of file diff --git a/htdocs/stripe/admin/stripe.php b/htdocs/stripe/admin/stripe.php index d61d03b2be6..67e0c26ce8c 100644 --- a/htdocs/stripe/admin/stripe.php +++ b/htdocs/stripe/admin/stripe.php @@ -227,10 +227,10 @@ if (empty($conf->stripeconnect->enabled)) { print ''; print ''.$langs->trans("STRIPE_TEST_WEBHOOK_KEY").''; if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { - print ''; + print ''; print '
'; } - print ''; + print ''; $out = img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForTestWebhook").' '; $url = dol_buildpath('/public/stripe/ipn.php?test', 3); $out .= ''; @@ -278,21 +278,21 @@ if (empty($conf->stripeconnect->enabled)) { if (empty($conf->stripeconnect->enabled)) { print ''; print ''.$langs->trans("STRIPE_LIVE_PUBLISHABLE_KEY").''; - print ''; + print ''; print ''; print ''; print ''.$langs->trans("STRIPE_LIVE_SECRET_KEY").''; - print ''; + print ''; print ''; print ''; print ''.$langs->trans("STRIPE_LIVE_WEBHOOK_KEY").''; if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { - print ''; + print ''; print '
'; } - print ''; + print ''; $out = img_picto('', 'globe', 'class="pictofixedwidth"').' '.$langs->trans("ToOfferALinkForLiveWebhook").' '; $url = dol_buildpath('/public/stripe/ipn.php', 3); $out .= ''; @@ -347,26 +347,26 @@ print "\n"; print ''; print $langs->trans("PublicVendorName").''; -print ''; +print ''; print '   '.$langs->trans("Example").': '.$mysoc->name.''; print ''; print ''; print $langs->trans("StripeUserAccountForActions").''; -print img_picto('', 'user', 'class="pictofixedwidth"').$form->select_dolusers($conf->global->STRIPE_USER_ACCOUNT_FOR_ACTIONS, 'STRIPE_USER_ACCOUNT_FOR_ACTIONS', 0); +print img_picto('', 'user', 'class="pictofixedwidth"').$form->select_dolusers(getDolGlobalString('STRIPE_USER_ACCOUNT_FOR_ACTIONS'), 'STRIPE_USER_ACCOUNT_FOR_ACTIONS', 0); print ''; print ''; print $langs->trans("BankAccount").''; print img_picto('', 'bank_account', 'class="pictofixedwidth"'); -$form->select_comptes($conf->global->STRIPE_BANK_ACCOUNT_FOR_PAYMENTS, 'STRIPE_BANK_ACCOUNT_FOR_PAYMENTS', 0, '', 1); +$form->select_comptes(getDolGlobalString('STRIPE_BANK_ACCOUNT_FOR_PAYMENTS'), 'STRIPE_BANK_ACCOUNT_FOR_PAYMENTS', 0, '', 1); print ''; if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) { // What is this for ? print ''; print $langs->trans("BankAccountForBankTransfer").''; print img_picto('', 'bank_account', 'class="pictofixedwidth"'); - $form->select_comptes($conf->global->STRIPE_BANK_ACCOUNT_FOR_BANKTRANSFERS, 'STRIPE_BANK_ACCOUNT_FOR_BANKTRANSFERS', 0, '', 1); + $form->select_comptes(getDolGlobalString('STRIPE_BANK_ACCOUNT_FOR_BANKTRANSFERS'), 'STRIPE_BANK_ACCOUNT_FOR_BANKTRANSFERS', 0, '', 1); print ''; } @@ -386,7 +386,7 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { // TODO Not used by current code // Locations for Stripe Terminal if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { // TODO Not used by current code print ''; - print $langs->trans("STRIPE_LOCATION").''; + print $langs->trans("TERMINAL_LOCATION").''; $service = 'StripeTest'; $servicestatus = 0; if (!empty($conf->global->STRIPE_LIVE) && !GETPOST('forcesandbox', 'alpha')) { @@ -395,7 +395,9 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { // TODO Not used by current code } global $stripearrayofkeysbyenv; $site_account = $stripearrayofkeysbyenv[$servicestatus]['secret_key']; - \Stripe\Stripe::setApiKey($site_account); + if (!empty($site_account)) { + \Stripe\Stripe::setApiKey($site_account); + } if (!empty($conf->stripe->enabled) && (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha'))) { $service = 'StripeTest'; $servicestatus = '0'; @@ -405,30 +407,34 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { // TODO Not used by current code $servicestatus = '1'; } $stripe = new Stripe($db); - $stripeacc = $stripe->getStripeAccount($service); - if ($stripeacc) { - $locations = \Stripe\Terminal\Location::all('', array("stripe_account" => $stripeacc)); - } else { - $locations = \Stripe\Terminal\Location::all(); + if (!empty($site_account)) { + // If $site_account not defined, then key not set and no way to call API Location + $stripeacc = $stripe->getStripeAccount($service); + if ($stripeacc) { + $locations = \Stripe\Terminal\Location::all('', array("stripe_account" => $stripeacc)); + } else { + $locations = \Stripe\Terminal\Location::all(); + } } + $location = array(); - $location[""] = $langs->trans("EmptyLocation"); + $location[""] = $langs->trans("NotDefined"); foreach ($locations as $locations) { $location[$locations->id] = $locations->display_name; } - print $form->selectarray("STRIPE_LOCATION", $location, $conf->global->STRIPE_LOCATION); + print $form->selectarray("STRIPE_LOCATION", $location, getDolGlobalString('STRIPE_LOCATION')); print ''; } // Activate Payment Request API if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { // TODO Not used by current code print ''; - print $langs->trans("STRIPE_PAYMENT_REQUEST_API").''; + print $langs->trans("STRIPE_PAYMENT_REQUEST_API").' ?? Not used, what is it for ??'; if ($conf->use_javascript_ajax) { print ajax_constantonoff('STRIPE_PAYMENT_REQUEST_API'); } else { $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); - print $form->selectarray("STRIPE_PAYMENT_REQUEST_API", $arrval, $conf->global->STRIPE_PAYMENT_REQUEST_API); + print $form->selectarray("STRIPE_PAYMENT_REQUEST_API", $arrval, getDolGlobalString('STRIPE_PAYMENT_REQUEST_API')); } print ''; } @@ -441,7 +447,7 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { // TODO Not used by current code print ajax_constantonoff('STRIPE_SEPA_DIRECT_DEBIT'); } else { $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); - print $form->selectarray("STRIPE_SEPA_DIRECT_DEBIT", $arrval, $conf->global->STRIPE_SEPA_DIRECT_DEBIT); + print $form->selectarray("STRIPE_SEPA_DIRECT_DEBIT", $arrval, getDolGlobalString('STRIPE_SEPA_DIRECT_DEBIT')); } print ''; } @@ -542,6 +548,7 @@ print ''; print ''; print $langs->trans("ONLINE_PAYMENT_SENDEMAIL").''; +print img_picto('', 'email', 'class="pictofixedwidth"'); print ''; print '   '.$langs->trans("Example").': myemail@myserver.com, Payment service <myemail2@myserver2.com>'; print ''; @@ -575,7 +582,7 @@ print ''; print ''; print $langs->trans("SecurityTokenIsUnique").''; if ($conf->use_javascript_ajax) { - print ajax_constantonoff('PAYMENT_SECURITY_TOKEN_UNIQUE'); + print ajax_constantonoff('PAYMENT_SECURITY_TOKEN_UNIQUE', null, null, 0, 0, 1); } else { $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); print $form->selectarray("PAYMENT_SECURITY_TOKEN_UNIQUE", $arrval, $conf->global->PAYMENT_SECURITY_TOKEN_UNIQUE); From c34579a2b0f1e6f58cab64b4e2ed7ed1970697eb Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 28 Jul 2022 11:16:21 +0200 Subject: [PATCH 331/826] CSS --- htdocs/societe/paymentmodes.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/htdocs/societe/paymentmodes.php b/htdocs/societe/paymentmodes.php index a63b91b024b..0f41ce6a56b 100644 --- a/htdocs/societe/paymentmodes.php +++ b/htdocs/societe/paymentmodes.php @@ -815,7 +815,8 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' print ''; print ''; print ''; - print ''; + print img_picto($langs->trans("CreateCustomerOnStripe"), 'stripe'); + print ''; print ''; } print ''; @@ -1289,6 +1290,7 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' $morehtmlright = dolGetButtonTitle($langs->trans('Add'), '', 'fa fa-plus-circle', $_SERVER["PHP_SELF"] . '?socid=' . $object->id . '&action=create'); } + print load_fiche_titre($langs->trans("BankAccounts"), $morehtmlright, 'bank'); $rib_list = $object->get_all_rib(); @@ -1454,6 +1456,10 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' // Edit/Delete print ''; if ($permissiontoaddupdatepaymentinformation) { + print ''; + print img_picto($langs->trans("CreateBAN"), 'stripe'); + print ''; + print ''; print img_picto($langs->trans("Modify"), 'edit'); print ''; From d8ae2361a984f0c3e337c96262ec488cc9cc7cf0 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Thu, 28 Jul 2022 11:29:36 +0200 Subject: [PATCH 332/826] NEW - Add user right order generete doc --- htdocs/commande/card.php | 7 ++++--- htdocs/core/actions_builddoc.inc.php | 2 +- htdocs/core/modules/modCommande.class.php | 10 +++++++++- htdocs/langs/en_US/admin.lang | 1 + 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 668787349be..a85aa2c5f77 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -108,14 +108,15 @@ $extrafields->fetch_name_optionals_label($object->table_element); // Load object include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once -$usercanread = $user->rights->commande->lire; -$usercancreate = $user->rights->commande->creer; -$usercandelete = $user->rights->commande->supprimer; +$usercanread = $user->hasRight('commande', 'lire'); +$usercancreate = $user->hasRight('commande', 'creer'); +$usercandelete = $user->hasRight('commande', 'supprimer'); // Advanced permissions $usercanclose = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->commande->creer)) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->commande->order_advance->close))); $usercanvalidate = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $usercancreate) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->commande->order_advance->validate))); $usercancancel = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $usercancreate) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->commande->order_advance->annuler))); $usercansend = (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || $user->rights->commande->order_advance->send); +$usercangeneretedoc = (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || $user->hasRight('commande', 'order_advance', 'generetedoc')); $usercancreatepurchaseorder = ($user->rights->fournisseur->commande->creer || $user->rights->supplier_order->creer); diff --git a/htdocs/core/actions_builddoc.inc.php b/htdocs/core/actions_builddoc.inc.php index 69d46dae51c..385b36bdbce 100644 --- a/htdocs/core/actions_builddoc.inc.php +++ b/htdocs/core/actions_builddoc.inc.php @@ -34,7 +34,7 @@ if (!empty($permissioncreate) && empty($permissiontoadd)) { } // Build doc -if ($action == 'builddoc' && $permissiontoadd) { +if ($action == 'builddoc' && ($permissiontoadd || !empty($usercangeneretedoc))) { if (is_numeric(GETPOST('model', 'alpha'))) { $error = $langs->trans("ErrorFieldRequired", $langs->transnoentities("Model")); } else { diff --git a/htdocs/core/modules/modCommande.class.php b/htdocs/core/modules/modCommande.class.php index e75147ba78a..70f06169394 100644 --- a/htdocs/core/modules/modCommande.class.php +++ b/htdocs/core/modules/modCommande.class.php @@ -139,9 +139,17 @@ class modCommande extends DolibarrModules $this->rights[$r][4] = 'order_advance'; $this->rights[$r][5] = 'validate'; + $r++; + $this->rights[$r][0] = 85; + $this->rights[$r][1] = 'Generate the documents sales orders'; + $this->rights[$r][2] = 'd'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'order_advance'; + $this->rights[$r][5] = 'generetedoc'; + $r++; $this->rights[$r][0] = 86; - $this->rights[$r][1] = 'Send sale orders by email'; + $this->rights[$r][1] = 'Send sales orders by email'; $this->rights[$r][2] = 'd'; $this->rights[$r][3] = 0; $this->rights[$r][4] = 'order_advance'; diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 16c39de46b9..f004079ea09 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -739,6 +739,7 @@ Permission79=Create/modify subscriptions Permission81=Read customers orders Permission82=Create/modify customers orders Permission84=Validate customers orders +Permission85=Generate the documents sales orders Permission86=Send customers orders Permission87=Close customers orders Permission88=Cancel customers orders From 03e265b080acf46478ae4049e2557cea3b2153bc Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Thu, 28 Jul 2022 11:43:00 +0200 Subject: [PATCH 333/826] FIX - php V8 user right order card --- htdocs/commande/card.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 668787349be..cf8e16f94ec 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -108,16 +108,16 @@ $extrafields->fetch_name_optionals_label($object->table_element); // Load object include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once -$usercanread = $user->rights->commande->lire; -$usercancreate = $user->rights->commande->creer; -$usercandelete = $user->rights->commande->supprimer; +$usercanread = $user->hasRight('commande', 'lire'); +$usercancreate = $user->hasRight('commande', 'creer'); +$usercandelete = $user->hasRight('commande', 'supprimer'); // Advanced permissions -$usercanclose = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->commande->creer)) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->commande->order_advance->close))); -$usercanvalidate = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $usercancreate) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->commande->order_advance->validate))); -$usercancancel = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $usercancreate) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->commande->order_advance->annuler))); -$usercansend = (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || $user->rights->commande->order_advance->send); +$usercanclose = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($usercancreate)) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->hasRight('commande', 'order_advance', 'close')))); +$usercanvalidate = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $usercancreate) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->hasRight('commande', 'order_advance', 'validate')))); +$usercancancel = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $usercancreate) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->hasRight('commande', 'order_advance', 'annuler')))); +$usercansend = (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || $user->hasRight('commande', 'order_advance', 'send')); -$usercancreatepurchaseorder = ($user->rights->fournisseur->commande->creer || $user->rights->supplier_order->creer); +$usercancreatepurchaseorder = ($user->hasRight('fournisseur', 'commande', 'creer') || $user->hasRight('supplier_order', 'creer')); $permissionnote = $usercancreate; // Used by the include of actions_setnotes.inc.php $permissiondellink = $usercancreate; // Used by the include of actions_dellink.inc.php From a778a5ff78a649043c9b061fc22cb1da8c84a6d9 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Thu, 28 Jul 2022 11:50:42 +0200 Subject: [PATCH 334/826] and order lib --- htdocs/commande/card.php | 8 ++++---- htdocs/core/lib/order.lib.php | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index cf8e16f94ec..0af1c2b7d9f 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -2747,7 +2747,7 @@ if ($action == 'create' && $usercancreate) { $langs->load("interventions"); if ($object->statut > Commande::STATUS_DRAFT && $object->statut < Commande::STATUS_CLOSED && $object->getNbOfServicesLines() > 0) { - if ($user->rights->ficheinter->creer) { + if ($user->hasRight('ficheinter', 'creer')) { print dolGetButtonAction('', $langs->trans('AddIntervention'), 'default', DOL_URL_ROOT.'/fichinter/card.php?action=create&origin='.$object->element.'&originid='.$object->id.'&socid='.$object->socid, ''); } else { print dolGetButtonAction($langs->trans('NotAllowed'), $langs->trans('AddIntervention'), 'default', $_SERVER['PHP_SELF']. '#', '', false); @@ -2759,7 +2759,7 @@ if ($action == 'create' && $usercancreate) { if (!empty($conf->contrat->enabled) && ($object->statut == Commande::STATUS_VALIDATED || $object->statut == Commande::STATUS_SHIPMENTONPROCESS || $object->statut == Commande::STATUS_CLOSED)) { $langs->load("contracts"); - if ($user->rights->contrat->creer) { + if ($user->hasRight('contrat', 'creer')) { print dolGetButtonAction('', $langs->trans('AddContract'), 'default', DOL_URL_ROOT.'/contrat/card.php?action=create&origin='.$object->element.'&originid='.$object->id.'&socid='.$object->socid, ''); } } @@ -2771,7 +2771,7 @@ if ($action == 'create' && $usercancreate) { if ($object->statut > Commande::STATUS_DRAFT && $object->statut < Commande::STATUS_CLOSED && ($object->getNbOfProductsLines() > 0 || !empty($conf->global->STOCK_SUPPORTS_SERVICES))) { if ((isModEnabled('expedition_bon') && $user->rights->expedition->creer) || ($conf->delivery_note->enabled && $user->rights->expedition->delivery->creer)) { - if ($user->rights->expedition->creer) { + if ($user->hasRight('expedition', 'creer')) { print dolGetButtonAction('', $langs->trans('CreateShipment'), 'default', DOL_URL_ROOT.'/expedition/shipment.php?id='.$object->id, ''); } else { print dolGetButtonAction($langs->trans('NotAllowed'), $langs->trans('CreateShipment'), 'default', $_SERVER['PHP_SELF']. '#', '', false); @@ -2790,7 +2790,7 @@ if ($action == 'create' && $usercancreate) { // Create bill and Classify billed // Note: Even if module invoice is not enabled, we should be able to use button "Classified billed" if ($object->statut > Commande::STATUS_DRAFT && !$object->billed && $object->total_ttc >= 0) { - if (isModEnabled('facture') && $user->rights->facture->creer && empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) { + if (isModEnabled('facture') && $user->hasRight('facture', 'creer') && empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) { print dolGetButtonAction('', $langs->trans('CreateBill'), 'default', DOL_URL_ROOT.'/compta/facture/card.php?action=create&token='.newToken().'&origin='.$object->element.'&originid='.$object->id.'&socid='.$object->socid, ''); } if ($usercancreate && $object->statut >= Commande::STATUS_VALIDATED && empty($conf->global->WORKFLOW_DISABLE_CLASSIFY_BILLED_FROM_ORDER) && empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT)) { diff --git a/htdocs/core/lib/order.lib.php b/htdocs/core/lib/order.lib.php index 8860f4126c4..bde894940de 100644 --- a/htdocs/core/lib/order.lib.php +++ b/htdocs/core/lib/order.lib.php @@ -60,8 +60,8 @@ function commande_prepare_head(Commande $object) $h++; } - if ((isModEnabled('expedition_bon') && $user->rights->expedition->lire) - || ($conf->delivery_note->enabled && $user->rights->expedition->delivery->lire)) { + if ((isModEnabled('expedition_bon') && $user->hasRight('expedition', 'lire')) + || ($conf->delivery_note->enabled && $user->hasRight('expedition', 'delivery', 'lire'))) { $nbShipments = $object->getNbOfShipments(); $nbReceiption = 0; $head[$h][0] = DOL_URL_ROOT.'/expedition/shipment.php?id='.$object->id; From 9c0cf32ef7dbe94f639c7688cf447cc5ce3e8161 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Thu, 28 Jul 2022 11:56:07 +0200 Subject: [PATCH 335/826] FIX - php V8 user right actioncomm class --- htdocs/comm/action/class/actioncomm.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index 68e358f18eb..9a7114a6113 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -1558,13 +1558,13 @@ class ActionComm extends CommonObject } $canread = 0; - if ($user->rights->agenda->myactions->read && $this->authorid == $user->id) { + if (!empty($user->rights->agenda->myactions->read) && $this->authorid == $user->id) { $canread = 1; // Can read my event } - if ($user->rights->agenda->myactions->read && array_key_exists($user->id, $this->userassigned)) { + if (!empty($user->rights->agenda->myactions->read) && array_key_exists($user->id, $this->userassigned)) { $canread = 1; // Can read my event i am assigned } - if ($user->rights->agenda->allactions->read) { + if (!empty($user->rights->agenda->allactions->read)) { $canread = 1; // Can read all event of other } if (!$canread) { From c1b98e8e733ec7205dfadea65161bef5770d048f Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Thu, 28 Jul 2022 12:09:22 +0200 Subject: [PATCH 336/826] FIX - php V8 user right box --- htdocs/core/boxes/box_actions.php | 2 +- htdocs/core/boxes/box_contacts.php | 2 +- htdocs/core/boxes/box_contracts.php | 2 +- htdocs/core/boxes/box_factures_fourn.php | 2 +- htdocs/core/boxes/box_factures_fourn_imp.php | 2 +- htdocs/core/boxes/box_ficheinter.php | 2 +- htdocs/core/boxes/box_propales.php | 2 +- htdocs/core/boxes/box_services_expired.php | 2 +- htdocs/core/boxes/box_supplier_orders.php | 2 +- htdocs/core/boxes/box_supplier_orders_awaiting_reception.php | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/htdocs/core/boxes/box_actions.php b/htdocs/core/boxes/box_actions.php index 551b892f0f7..fb0f93086d2 100644 --- a/htdocs/core/boxes/box_actions.php +++ b/htdocs/core/boxes/box_actions.php @@ -62,7 +62,7 @@ class box_actions extends ModeleBoxes $this->enabled = $conf->agenda->enabled; - $this->hidden = !($user->rights->agenda->myactions->read); + $this->hidden = !($user->hasRight('agenda', 'myactions', 'read')); } /** diff --git a/htdocs/core/boxes/box_contacts.php b/htdocs/core/boxes/box_contacts.php index ea35a080d0e..f257d7db18d 100644 --- a/htdocs/core/boxes/box_contacts.php +++ b/htdocs/core/boxes/box_contacts.php @@ -63,7 +63,7 @@ class box_contacts extends ModeleBoxes $this->db = $db; - $this->hidden = !($user->rights->societe->lire && $user->rights->societe->contact->lire); + $this->hidden = !($user->hasRight('societe', 'lire') && $user->hasRight('societe', 'contact', 'lire')); } /** diff --git a/htdocs/core/boxes/box_contracts.php b/htdocs/core/boxes/box_contracts.php index dddafffdc02..99ea5541c98 100644 --- a/htdocs/core/boxes/box_contracts.php +++ b/htdocs/core/boxes/box_contracts.php @@ -59,7 +59,7 @@ class box_contracts extends ModeleBoxes $this->db = $db; - $this->hidden = !($user->rights->contrat->lire); + $this->hidden = !($user->hasRight('contrat', 'lire')); } /** diff --git a/htdocs/core/boxes/box_factures_fourn.php b/htdocs/core/boxes/box_factures_fourn.php index 5fc3bdafa38..06124d4ab35 100644 --- a/htdocs/core/boxes/box_factures_fourn.php +++ b/htdocs/core/boxes/box_factures_fourn.php @@ -59,7 +59,7 @@ class box_factures_fourn extends ModeleBoxes $this->db = $db; - $this->hidden = !($user->rights->fournisseur->facture->lire); + $this->hidden = !($user->hasRight('fournisseur', 'facture', 'lire')); } /** diff --git a/htdocs/core/boxes/box_factures_fourn_imp.php b/htdocs/core/boxes/box_factures_fourn_imp.php index d8c9321411d..ad6c6c97c27 100644 --- a/htdocs/core/boxes/box_factures_fourn_imp.php +++ b/htdocs/core/boxes/box_factures_fourn_imp.php @@ -58,7 +58,7 @@ class box_factures_fourn_imp extends ModeleBoxes $this->db = $db; - $this->hidden = !($user->rights->fournisseur->facture->lire); + $this->hidden = !($user->hasRight('fournisseur', 'facture', 'lire')); } /** diff --git a/htdocs/core/boxes/box_ficheinter.php b/htdocs/core/boxes/box_ficheinter.php index b0f0e691471..f69ccb0ad94 100644 --- a/htdocs/core/boxes/box_ficheinter.php +++ b/htdocs/core/boxes/box_ficheinter.php @@ -59,7 +59,7 @@ class box_ficheinter extends ModeleBoxes $this->db = $db; - $this->hidden = !($user->rights->ficheinter->lire); + $this->hidden = !($user->hasRight('ficheinter', 'lire')); } /** diff --git a/htdocs/core/boxes/box_propales.php b/htdocs/core/boxes/box_propales.php index cdaf629ae3f..8e8efc8d8f3 100644 --- a/htdocs/core/boxes/box_propales.php +++ b/htdocs/core/boxes/box_propales.php @@ -61,7 +61,7 @@ class box_propales extends ModeleBoxes $this->db = $db; - $this->hidden = !($user->rights->propale->lire); + $this->hidden = !($user->hasRight('propale', 'lire')); } /** diff --git a/htdocs/core/boxes/box_services_expired.php b/htdocs/core/boxes/box_services_expired.php index e9cca792de1..25fa5ca2b1f 100644 --- a/htdocs/core/boxes/box_services_expired.php +++ b/htdocs/core/boxes/box_services_expired.php @@ -58,7 +58,7 @@ class box_services_expired extends ModeleBoxes $this->db = $db; - $this->hidden = !($user->rights->contrat->lire); + $this->hidden = !($user->hasRight('contrat', 'lire')); } /** diff --git a/htdocs/core/boxes/box_supplier_orders.php b/htdocs/core/boxes/box_supplier_orders.php index 6ee0c5ef8a3..f3db3526bb6 100644 --- a/htdocs/core/boxes/box_supplier_orders.php +++ b/htdocs/core/boxes/box_supplier_orders.php @@ -58,7 +58,7 @@ class box_supplier_orders extends ModeleBoxes $this->db = $db; - $this->hidden = !($user->rights->fournisseur->commande->lire); + $this->hidden = !($user->hasRight('fournisseur', 'commande', 'lire')); } /** diff --git a/htdocs/core/boxes/box_supplier_orders_awaiting_reception.php b/htdocs/core/boxes/box_supplier_orders_awaiting_reception.php index 32151828b83..ce0161582de 100644 --- a/htdocs/core/boxes/box_supplier_orders_awaiting_reception.php +++ b/htdocs/core/boxes/box_supplier_orders_awaiting_reception.php @@ -58,7 +58,7 @@ class box_supplier_orders_awaiting_reception extends ModeleBoxes $this->db = $db; - $this->hidden = !($user->rights->fournisseur->commande->lire); + $this->hidden = !($user->hasRight('fournisseur', 'commande', 'lire')); } /** From 524c2e932cafa4ecb38de52af73a7a251ab46a68 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Thu, 28 Jul 2022 13:35:43 +0200 Subject: [PATCH 337/826] NEW display currency in takepos menu --- htdocs/takepos/public/menu.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/takepos/public/menu.php b/htdocs/takepos/public/menu.php index ad4dfd9035e..5d9d318db07 100644 --- a/htdocs/takepos/public/menu.php +++ b/htdocs/takepos/public/menu.php @@ -97,7 +97,7 @@ foreach ($maincategories as $cat) {

'.$pro->label.'

- '.price($pro->price_ttc, 1).' + '.price($pro->price_ttc, 1, $langs, 1, -1, -1, $conf->currency).'
'; } From d66aa960bb57ccdf7cd137ea1ece07540b1d7d31 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Thu, 28 Jul 2022 14:33:33 +0200 Subject: [PATCH 338/826] Resolve --- htdocs/core/lib/functions.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 1eb72d50455..707f8cb7384 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -10422,7 +10422,7 @@ function dolGetButtonAction($label, $html = '', $actionType = 'default', $url = global $hookmanager, $action, $object, $langs; //var_dump($params); - if (isset($params['isDropdown'])) + if (!empty($params['isDropdown'])) $class = "dropdown-item"; else { $class = 'butAction'; From 7301ef6bfa1e40d263e647be63526ed364b7c9d8 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Thu, 28 Jul 2022 14:55:42 +0200 Subject: [PATCH 339/826] FIX - strlower to email --- htdocs/contact/class/contact.class.php | 2 +- htdocs/societe/class/societe.class.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/contact/class/contact.class.php b/htdocs/contact/class/contact.class.php index 9fa3602ee4b..9957174dcc3 100644 --- a/htdocs/contact/class/contact.class.php +++ b/htdocs/contact/class/contact.class.php @@ -563,7 +563,7 @@ class Contact extends CommonObject $this->ref_ext = trim($this->ref_ext); $this->lastname = trim($this->lastname) ?trim($this->lastname) : trim($this->lastname); $this->firstname = trim($this->firstname); - $this->email = trim($this->email); + $this->email = dol_strtolower(trim($this->email)); $this->phone_pro = trim($this->phone_pro); $this->phone_perso = trim($this->phone_perso); $this->phone_mobile = trim($this->phone_mobile); diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 90766323080..2279aa90cdb 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -1279,7 +1279,7 @@ class Societe extends CommonObject $this->fax = trim($this->fax); $this->fax = preg_replace("/\s/", "", $this->fax); $this->fax = preg_replace("/\./", "", $this->fax); - $this->email = trim($this->email); + $this->email = dol_strtolower(trim($this->email)); $this->url = $this->url ?clean_url($this->url, 0) : ''; $this->note_private = trim($this->note_private); $this->note_public = trim($this->note_public); From cfc9819e49496ef2c4297f857650de34ec0f3910 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Thu, 28 Jul 2022 15:13:13 +0200 Subject: [PATCH 340/826] FIX - strlower for email --- htdocs/adherents/class/adherent.class.php | 3 +-- htdocs/contact/class/contact.class.php | 4 ++-- htdocs/core/class/commonobject.class.php | 2 ++ htdocs/societe/class/societe.class.php | 5 ++--- htdocs/user/class/user.class.php | 3 ++- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index c860a19d588..dec7584b68e 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -670,11 +670,10 @@ class Adherent extends CommonObject $this->town = ($this->town ? $this->town : $this->town); $this->country_id = ($this->country_id > 0 ? $this->country_id : $this->country_id); $this->state_id = ($this->state_id > 0 ? $this->state_id : $this->state_id); - $this->setUpperOrLowerCase(); $this->note_public = ($this->note_public ? $this->note_public : $this->note_public); $this->note_private = ($this->note_private ? $this->note_private : $this->note_private); $this->url = $this->url ?clean_url($this->url, 0) : ''; - + $this->setUpperOrLowerCase(); // Check parameters if (!empty($conf->global->ADHERENT_MAIL_REQUIRED) && !isValidEMail($this->email)) { $langs->load("errors"); diff --git a/htdocs/contact/class/contact.class.php b/htdocs/contact/class/contact.class.php index 9957174dcc3..799b53cdad0 100644 --- a/htdocs/contact/class/contact.class.php +++ b/htdocs/contact/class/contact.class.php @@ -563,7 +563,7 @@ class Contact extends CommonObject $this->ref_ext = trim($this->ref_ext); $this->lastname = trim($this->lastname) ?trim($this->lastname) : trim($this->lastname); $this->firstname = trim($this->firstname); - $this->email = dol_strtolower(trim($this->email)); + $this->email = trim($this->email); $this->phone_pro = trim($this->phone_pro); $this->phone_perso = trim($this->phone_perso); $this->phone_mobile = trim($this->phone_mobile); @@ -571,7 +571,6 @@ class Contact extends CommonObject $this->fax = trim($this->fax); $this->zip = (empty($this->zip) ? '' : trim($this->zip)); $this->town = (empty($this->town) ? '' : trim($this->town)); - $this->setUpperOrLowerCase(); $this->country_id = ($this->country_id > 0 ? $this->country_id : $this->country_id); if (empty($this->statut)) { $this->statut = 0; @@ -579,6 +578,7 @@ class Contact extends CommonObject if (empty($this->civility_code) && !is_numeric($this->civility_id)) { $this->civility_code = $this->civility_id; // For backward compatibility } + $this->setUpperOrLowerCase(); $this->db->begin(); $sql = "UPDATE ".MAIN_DB_PREFIX."socpeople SET"; diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 01665e99ca5..f3c49ae1f75 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -759,6 +759,8 @@ abstract class CommonObject $this->address = dol_strtoupper($this->address); $this->town = dol_strtoupper($this->town); } + $this->email = dol_strtolower($this->email); + $this->personal_email = dol_strtolower($this->personal_email); } /** diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 2279aa90cdb..a65b49d4bb2 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -1270,7 +1270,6 @@ class Societe extends CommonObject $this->address = $this->address ?trim($this->address) : trim($this->address); $this->zip = $this->zip ?trim($this->zip) : trim($this->zip); $this->town = $this->town ?trim($this->town) : trim($this->town); - $this->setUpperOrLowerCase(); $this->state_id = trim($this->state_id); $this->country_id = ($this->country_id > 0) ? $this->country_id : 0; $this->phone = trim($this->phone); @@ -1279,7 +1278,7 @@ class Societe extends CommonObject $this->fax = trim($this->fax); $this->fax = preg_replace("/\s/", "", $this->fax); $this->fax = preg_replace("/\./", "", $this->fax); - $this->email = dol_strtolower(trim($this->email)); + $this->email = trim($this->email); $this->url = $this->url ?clean_url($this->url, 0) : ''; $this->note_private = trim($this->note_private); $this->note_public = trim($this->note_public); @@ -1412,7 +1411,7 @@ class Societe extends CommonObject } } } - + $this->setUpperOrLowerCase(); if ($result >= 0) { dol_syslog(get_class($this)."::update verify ok or not done"); diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index fcd1505a402..6fca728ee8b 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -1864,7 +1864,6 @@ class User extends CommonObject $this->address = trim((string) $this->address); $this->zip = trim((string) $this->zip); $this->town = trim((string) $this->town); - $this->setUpperOrLowerCase(); $this->state_id = ($this->state_id > 0 ? $this->state_id : 0); $this->country_id = ($this->country_id > 0 ? $this->country_id : 0); @@ -1891,6 +1890,8 @@ class User extends CommonObject $this->birth = empty($this->birth) ? '' : $this->birth; $this->fk_warehouse = (int) $this->fk_warehouse; + $this->setUpperOrLowerCase(); + // Check parameters $badCharUnauthorizedIntoLoginName = getDolGlobalString('MAIN_LOGIN_BADCHARUNAUTHORIZED', ',@<>"\''); From 915380202c20e8b368117c0b4b90c1a39a69f0c9 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Thu, 28 Jul 2022 17:09:56 +0200 Subject: [PATCH 341/826] FIX - php V8 pdf lib --- htdocs/core/lib/pdf.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/pdf.lib.php b/htdocs/core/lib/pdf.lib.php index ff0350a9552..be89f4700b8 100644 --- a/htdocs/core/lib/pdf.lib.php +++ b/htdocs/core/lib/pdf.lib.php @@ -453,7 +453,7 @@ function pdf_build_address($outputlangs, $sourcecompany, $targetcompany = '', $t if (empty($reshook)) { if ($mode == 'source') { $withCountry = 0; - if (!empty($sourcecompany->country_code) && ($targetcompany->country_code != $sourcecompany->country_code)) { + if (isset($targetcompany->country_code) && !empty($sourcecompany->country_code) && ($targetcompany->country_code != $sourcecompany->country_code)) { $withCountry = 1; } From df727f3b5dd79ac7c3766be7bebe200ddad7add1 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Thu, 28 Jul 2022 17:22:21 +0200 Subject: [PATCH 342/826] FIX - Add colone last_main_doc in societe for migration Error to generate doc --- htdocs/install/mysql/migration/16.0.0-17.0.0.sql | 1 + htdocs/societe/class/societe.class.php | 1 + 2 files changed, 2 insertions(+) diff --git a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql index 6713d410fc6..24b4e20a7b7 100644 --- a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql +++ b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql @@ -62,4 +62,5 @@ ALTER TABLE llx_inventory ADD COLUMN categories_product VARCHAR(255) DEFAULT NUL ALTER TABLE llx_ticket ADD COLUMN ip varchar(250); +ALTER TABLE llx_societe ADD last_main_doc VARCHAR(255) NULL AFTER model_pdf; diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 90766323080..a3f3c45806f 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -232,6 +232,7 @@ class Societe extends CommonObject 'fk_incoterms' =>array('type'=>'integer', 'label'=>'Fk incoterms', 'enabled'=>1, 'visible'=>-1, 'position'=>425), 'location_incoterms' =>array('type'=>'varchar(255)', 'label'=>'Location incoterms', 'enabled'=>1, 'visible'=>-1, 'position'=>430), 'model_pdf' =>array('type'=>'varchar(255)', 'label'=>'Model pdf', 'enabled'=>1, 'visible'=>0, 'position'=>435), + 'last_main_doc' =>array('type'=>'varchar(255)', 'label'=>'LastMainDoc', 'enabled'=>1, 'visible'=>-1, 'position'=>270), 'fk_multicurrency' =>array('type'=>'integer', 'label'=>'Fk multicurrency', 'enabled'=>1, 'visible'=>-1, 'position'=>440), 'multicurrency_code' =>array('type'=>'varchar(255)', 'label'=>'Multicurrency code', 'enabled'=>1, 'visible'=>-1, 'position'=>445), 'fk_account' =>array('type'=>'integer', 'label'=>'AccountingAccount', 'enabled'=>1, 'visible'=>-1, 'position'=>450), From 0fe441bc2a9f7ecad8cad7d7403041f86a4b1439 Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Thu, 28 Jul 2022 17:29:09 +0200 Subject: [PATCH 343/826] use getDolGlobal... --- htdocs/core/lib/takepos.lib.php | 2 +- htdocs/takepos/admin/terminal.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/lib/takepos.lib.php b/htdocs/core/lib/takepos.lib.php index 66ea16a6123..c2468c98169 100644 --- a/htdocs/core/lib/takepos.lib.php +++ b/htdocs/core/lib/takepos.lib.php @@ -56,7 +56,7 @@ function takepos_admin_prepare_head() $numterminals = max(1, $conf->global->TAKEPOS_NUM_TERMINALS); for ($i = 1; $i <= $numterminals; $i++) { $head[$h][0] = DOL_URL_ROOT.'/takepos/admin/terminal.php?terminal='.$i; - $head[$h][1] = (! empty($conf->global->{"TAKEPOS_TERMINAL_NAME_".$i}) ? $conf->global->{"TAKEPOS_TERMINAL_NAME_".$i} : $langs->trans("TerminalName", $i)); + $head[$h][1] = getDolGlobalString('TAKEPOS_TERMINAL_NAME_'.$i, $langs->trans("TerminalName", $i)); $head[$h][2] = 'terminal'.$i; $h++; } diff --git a/htdocs/takepos/admin/terminal.php b/htdocs/takepos/admin/terminal.php index 29bc7fa5712..0bfe4ebd080 100644 --- a/htdocs/takepos/admin/terminal.php +++ b/htdocs/takepos/admin/terminal.php @@ -152,7 +152,7 @@ print "\n"; print ''.$langs->trans("TerminalNameDesc").''; print ''; -print 'global->{"TAKEPOS_TERMINAL_NAME_".$terminal} : $langs->trans("TerminalName", $terminal)).'" >'; +print 'trans("TerminalName", $terminal)).'" >'; print ''; print ''.$langs->trans("CashDeskThirdPartyForSell").''; From 4b3fdcc9f60fb92e0f3f4722ec5408bf06203753 Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Thu, 28 Jul 2022 17:36:58 +0200 Subject: [PATCH 344/826] use getDolGlobal... --- htdocs/takepos/index.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/takepos/index.php b/htdocs/takepos/index.php index 8cbdd7adb13..e9717e7c992 100644 --- a/htdocs/takepos/index.php +++ b/htdocs/takepos/index.php @@ -955,7 +955,7 @@ if (empty($conf->global->TAKEPOS_HIDE_HEAD_BAR)) { - global->{"TAKEPOS_TERMINAL_NAME_".$_SESSION["takeposterminal"]}) ? $conf->global->{"TAKEPOS_TERMINAL_NAME_".$_SESSION["takeposterminal"]} : $langs->trans("TerminalName", $_SESSION["takeposterminal"])); ?> + trans("TerminalName", $_SESSION["takeposterminal"])); ?> - '.dol_print_date(dol_now(), "day").''; @@ -1014,11 +1014,11 @@ if (empty($conf->global->TAKEPOS_HIDE_HEAD_BAR)) {

trans("TerminalSelect"); ?>

From ce87eea3ec842358de9664a42eb53717a8c78af3 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Thu, 28 Jul 2022 18:18:04 +0200 Subject: [PATCH 345/826] ErrorFTPNodisconnect --- htdocs/core/lib/ftp.lib.php | 153 +++++++++++++++++++++++++++++++++ htdocs/ftp/admin/ftpclient.php | 2 +- htdocs/ftp/index.php | 126 ++------------------------- htdocs/langs/en_US/ftp.lang | 15 ++++ htdocs/langs/en_US/other.lang | 15 ---- 5 files changed, 176 insertions(+), 135 deletions(-) create mode 100644 htdocs/core/lib/ftp.lib.php create mode 100644 htdocs/langs/en_US/ftp.lang diff --git a/htdocs/core/lib/ftp.lib.php b/htdocs/core/lib/ftp.lib.php new file mode 100644 index 00000000000..1730a439bcb --- /dev/null +++ b/htdocs/core/lib/ftp.lib.php @@ -0,0 +1,153 @@ + + * Copyright (C) 2022 Anthony Berton + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * or see https://www.gnu.org/ + */ + +/** + * \file htdocs/core/lib/ftp.lib.php + * \brief Set of functions used for FTP + * \ingroup core + */ + + + + +/** + * Connect to FTP server + * + * @param string $ftp_server Server name + * @param string $ftp_port Server port + * @param string $ftp_user FTP user + * @param string $ftp_password FTP password + * @param string $section Directory + * @param integer $ftp_passive Use a passive mode + * @return int <0 if OK, >0 if KO + */ +function dol_ftp_connect($ftp_server, $ftp_port, $ftp_user, $ftp_password, $section, $ftp_passive = 0) +{ + global $langs, $conf; + + $ok = 1; + $error = 0; + $conn_id = null; + $newsectioniso = ''; + $mesg=""; + + if (!is_numeric($ftp_port)) { + $mesg = $langs->transnoentitiesnoconv("FailedToConnectToFTPServer", $ftp_server, $ftp_port); + $ok = 0; + } + + if ($ok) { + $connecttimeout = (empty($conf->global->FTP_CONNECT_TIMEOUT) ? 40 : $conf->global->FTP_CONNECT_TIMEOUT); + if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) { + dol_syslog('Try to connect with ssh2_connect'); + $tmp_conn_id = ssh2_connect($ftp_server, $ftp_port); + } elseif (!empty($conf->global->FTP_CONNECT_WITH_SSL)) { + dol_syslog('Try to connect with ftp_ssl_connect'); + $conn_id = ftp_ssl_connect($ftp_server, $ftp_port, $connecttimeout); + } else { + dol_syslog('Try to connect with ftp_connect'); + $conn_id = ftp_connect($ftp_server, $ftp_port, $connecttimeout); + } + if (!empty($conn_id) || !empty($tmp_conn_id)) { + if ($ftp_user) { + if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) { + dol_syslog('Try to authenticate with ssh2_auth_password'); + if (ssh2_auth_password($tmp_conn_id, $ftp_user, $ftp_password)) { + // Turn on passive mode transfers (must be after a successful login + //if ($ftp_passive) ftp_pasv($conn_id, true); + + // Change the dir + $newsectioniso = utf8_decode($section); + //ftp_chdir($conn_id, $newsectioniso); + $conn_id = ssh2_sftp($tmp_conn_id); + if (!$conn_id) { + dol_syslog('Failed to connect to SFTP after sssh authentication', LOG_DEBUG); + $mesg = $langs->transnoentitiesnoconv("FailedToConnectToSFTPAfterSSHAuthentication"); + $ok = 0; + $error++; + } + } else { + dol_syslog('Failed to connect to FTP with login '.$ftp_user, LOG_DEBUG); + $mesg = $langs->transnoentitiesnoconv("FailedToConnectToFTPServerWithCredentials"); + $ok = 0; + $error++; + } + } else { + if (ftp_login($conn_id, $ftp_user, $ftp_password)) { + // Turn on passive mode transfers (must be after a successful login + if ($ftp_passive) { + ftp_pasv($conn_id, true); + } + + // Change the dir + $newsectioniso = utf8_decode($section); + ftp_chdir($conn_id, $newsectioniso); + } else { + $mesg = $langs->transnoentitiesnoconv("FailedToConnectToFTPServerWithCredentials"); + $ok = 0; + $error++; + } + } + } + } else { + dol_syslog('FailedToConnectToFTPServer '.$ftp_server.' '.$ftp_port, LOG_ERR); + $mesg = $langs->transnoentitiesnoconv("FailedToConnectToFTPServer", $ftp_server, $ftp_port); + $ok = 0; + } + } + + $arrayresult = array('conn_id'=>$conn_id, 'ok'=>$ok, 'mesg'=>$mesg, 'curdir'=>$section, 'curdiriso'=>$newsectioniso); + return $arrayresult; +} + + +/** + * Tell if an entry is a FTP directory + * + * @param resource $connect_id Connection handler + * @param string $dir Directory + * @return int 1=directory, 0=not a directory + */ +function ftp_isdir($connect_id, $dir) +{ + if (@ftp_chdir($connect_id, $dir)) { + ftp_cdup($connect_id); + return 1; + } else { + return 0; + } +} + +/** + * Tell if an entry is a FTP directory + * + * @param resource $connect_id Connection handler + */ +function dol_ftp_close($connect_id) +{ + // Close FTP connection + if ($connect_id) { + if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) { + } elseif (!empty($conf->global->FTP_CONNECT_WITH_SSL)) { + return ftp_close($connect_id); + } else { + return ftp_close($connect_id); + } + } +} \ No newline at end of file diff --git a/htdocs/ftp/admin/ftpclient.php b/htdocs/ftp/admin/ftpclient.php index c3d5509aa36..f914c835b37 100644 --- a/htdocs/ftp/admin/ftpclient.php +++ b/htdocs/ftp/admin/ftpclient.php @@ -25,7 +25,7 @@ require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; -$langs->loadLangs(array("admin", "other")); +$langs->loadLangs(array('ftp', "admin", "other")); $def = array(); $lastftpentry = 0; diff --git a/htdocs/ftp/index.php b/htdocs/ftp/index.php index 626703d4b68..54e66e845d4 100644 --- a/htdocs/ftp/index.php +++ b/htdocs/ftp/index.php @@ -27,9 +27,10 @@ require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/treeview.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/ftp.lib.php'; // Load translation files required by the page -$langs->loadLangs(array('companies', 'other')); +$langs->loadLangs(array('ftp', 'companies', 'other')); // Security check if ($user->socid) { @@ -665,127 +666,14 @@ if (!function_exists('ftp_connect')) { print '
'; -// Close FTP connection -if ($conn_id) { - if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) { - } elseif (!empty($conf->global->FTP_CONNECT_WITH_SSL)) { - ftp_close($conn_id); - } else { - ftp_close($conn_id); +if (!empty($conn_id)) { + $disconnect = dol_ftp_close($conn_id); + + if ($disconnect == false) { + setEventMessages($langs->trans("ErrorFTPNodisconnect"), null, 'errors'); } } // End of page llxFooter(); $db->close(); - - - -/** - * Connect to FTP server - * - * @param string $ftp_server Server name - * @param string $ftp_port Server port - * @param string $ftp_user FTP user - * @param string $ftp_password FTP password - * @param string $section Directory - * @param integer $ftp_passive Use a passive mode - * @return int <0 if OK, >0 if KO - */ -function dol_ftp_connect($ftp_server, $ftp_port, $ftp_user, $ftp_password, $section, $ftp_passive = 0) -{ - global $langs, $conf; - - $ok = 1; - $error = 0; - $conn_id = null; - $newsectioniso = ''; - $mesg=""; - - if (!is_numeric($ftp_port)) { - $mesg = $langs->transnoentitiesnoconv("FailedToConnectToFTPServer", $ftp_server, $ftp_port); - $ok = 0; - } - - if ($ok) { - $connecttimeout = (empty($conf->global->FTP_CONNECT_TIMEOUT) ? 40 : $conf->global->FTP_CONNECT_TIMEOUT); - if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) { - dol_syslog('Try to connect with ssh2_connect'); - $tmp_conn_id = ssh2_connect($ftp_server, $ftp_port); - } elseif (!empty($conf->global->FTP_CONNECT_WITH_SSL)) { - dol_syslog('Try to connect with ftp_ssl_connect'); - $conn_id = ftp_ssl_connect($ftp_server, $ftp_port, $connecttimeout); - } else { - dol_syslog('Try to connect with ftp_connect'); - $conn_id = ftp_connect($ftp_server, $ftp_port, $connecttimeout); - } - if (!empty($conn_id) || !empty($tmp_conn_id)) { - if ($ftp_user) { - if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) { - dol_syslog('Try to authenticate with ssh2_auth_password'); - if (ssh2_auth_password($tmp_conn_id, $ftp_user, $ftp_password)) { - // Turn on passive mode transfers (must be after a successful login - //if ($ftp_passive) ftp_pasv($conn_id, true); - - // Change the dir - $newsectioniso = utf8_decode($section); - //ftp_chdir($conn_id, $newsectioniso); - $conn_id = ssh2_sftp($tmp_conn_id); - if (!$conn_id) { - dol_syslog('Failed to connect to SFTP after sssh authentication', LOG_DEBUG); - $mesg = $langs->transnoentitiesnoconv("FailedToConnectToSFTPAfterSSHAuthentication"); - $ok = 0; - $error++; - } - } else { - dol_syslog('Failed to connect to FTP with login '.$ftp_user, LOG_DEBUG); - $mesg = $langs->transnoentitiesnoconv("FailedToConnectToFTPServerWithCredentials"); - $ok = 0; - $error++; - } - } else { - if (ftp_login($conn_id, $ftp_user, $ftp_password)) { - // Turn on passive mode transfers (must be after a successful login - if ($ftp_passive) { - ftp_pasv($conn_id, true); - } - - // Change the dir - $newsectioniso = utf8_decode($section); - ftp_chdir($conn_id, $newsectioniso); - } else { - $mesg = $langs->transnoentitiesnoconv("FailedToConnectToFTPServerWithCredentials"); - $ok = 0; - $error++; - } - } - } - } else { - dol_syslog('FailedToConnectToFTPServer '.$ftp_server.' '.$ftp_port, LOG_ERR); - $mesg = $langs->transnoentitiesnoconv("FailedToConnectToFTPServer", $ftp_server, $ftp_port); - $ok = 0; - } - } - - $arrayresult = array('conn_id'=>$conn_id, 'ok'=>$ok, 'mesg'=>$mesg, 'curdir'=>$section, 'curdiriso'=>$newsectioniso); - return $arrayresult; -} - - -/** - * Tell if an entry is a FTP directory - * - * @param resource $connect_id Connection handler - * @param string $dir Directory - * @return int 1=directory, 0=not a directory - */ -function ftp_isdir($connect_id, $dir) -{ - if (@ftp_chdir($connect_id, $dir)) { - ftp_cdup($connect_id); - return 1; - } else { - return 0; - } -} - diff --git a/htdocs/langs/en_US/ftp.lang b/htdocs/langs/en_US/ftp.lang new file mode 100644 index 00000000000..26791d63918 --- /dev/null +++ b/htdocs/langs/en_US/ftp.lang @@ -0,0 +1,15 @@ +# FTP +FTPClientSetup=FTP or SFTP Client module setup +NewFTPClient=New FTP/SFTP connection setup +FTPArea=FTP/SFTP Area +FTPAreaDesc=This screen shows a view of an FTP et SFTP server. +SetupOfFTPClientModuleNotComplete=The setup of the FTP or SFTP client module seems to be incomplete +FTPFeatureNotSupportedByYourPHP=Your PHP does not support FTP or SFTP functions +FailedToConnectToFTPServer=Failed to connect to server (server %s, port %s) +FailedToConnectToFTPServerWithCredentials=Failed to login to server with defined login/password +FTPFailedToRemoveFile=Failed to remove file %s. +FTPFailedToRemoveDir=Failed to remove directory %s: check permissions and that the directory is empty. +FTPPassiveMode=Passive mode +ChooseAFTPEntryIntoMenu=Choose a FTP/SFTP site from the menu... +FailedToGetFile=Failed to get files %s +ErrorFTPNodisconnect=Error to disconnect FTP/SFTP server \ No newline at end of file diff --git a/htdocs/langs/en_US/other.lang b/htdocs/langs/en_US/other.lang index e533dc71fa5..2bb316f648f 100644 --- a/htdocs/langs/en_US/other.lang +++ b/htdocs/langs/en_US/other.lang @@ -310,18 +310,3 @@ ExternalSiteSetup=Setup link to external website ExternalSiteURL=External Site URL of HTML iframe content ExternalSiteModuleNotComplete=Module ExternalSite was not configured properly. ExampleMyMenuEntry=My menu entry - -# FTP -FTPClientSetup=FTP or SFTP Client module setup -NewFTPClient=New FTP/FTPS connection setup -FTPArea=FTP/FTPS Area -FTPAreaDesc=This screen shows a view of an FTP et SFTP server. -SetupOfFTPClientModuleNotComplete=The setup of the FTP or SFTP client module seems to be incomplete -FTPFeatureNotSupportedByYourPHP=Your PHP does not support FTP or SFTP functions -FailedToConnectToFTPServer=Failed to connect to server (server %s, port %s) -FailedToConnectToFTPServerWithCredentials=Failed to login to server with defined login/password -FTPFailedToRemoveFile=Failed to remove file %s. -FTPFailedToRemoveDir=Failed to remove directory %s: check permissions and that the directory is empty. -FTPPassiveMode=Passive mode -ChooseAFTPEntryIntoMenu=Choose a FTP/SFTP site from the menu... -FailedToGetFile=Failed to get files %s From f54b4baee0daa216c80a565eea7fc35fd5c17bde Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Thu, 28 Jul 2022 16:21:53 +0000 Subject: [PATCH 346/826] Fixing style errors. --- htdocs/core/lib/ftp.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/ftp.lib.php b/htdocs/core/lib/ftp.lib.php index 1730a439bcb..d7ce0435c0d 100644 --- a/htdocs/core/lib/ftp.lib.php +++ b/htdocs/core/lib/ftp.lib.php @@ -150,4 +150,4 @@ function dol_ftp_close($connect_id) return ftp_close($connect_id); } } -} \ No newline at end of file +} From 0f154fa60ce4cd5a276a98b6313effef858d78eb Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 28 Jul 2022 18:36:50 +0200 Subject: [PATCH 347/826] CSS --- htdocs/core/class/html.formactions.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/html.formactions.class.php b/htdocs/core/class/html.formactions.class.php index 242c1476736..99003f00276 100644 --- a/htdocs/core/class/html.formactions.class.php +++ b/htdocs/core/class/html.formactions.class.php @@ -327,11 +327,11 @@ class FormActions $cursorevent++; } } else { - print ''.$langs->trans("None").''; + print ''.$langs->trans("None").''; } if ($max && $num > $max) { - print ''.$langs->trans("More").'...'; + print ''.$langs->trans("More").'...'; } print ''; From 455f286ac12f5e7002b259c10a08123afde61eed Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 28 Jul 2022 18:54:45 +0200 Subject: [PATCH 348/826] Debug v17 --- htdocs/core/modules/barcode/mod_barcode_thirdparty_standard.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/barcode/mod_barcode_thirdparty_standard.php b/htdocs/core/modules/barcode/mod_barcode_thirdparty_standard.php index fd0a87efe5b..e25cd1dd115 100644 --- a/htdocs/core/modules/barcode/mod_barcode_thirdparty_standard.php +++ b/htdocs/core/modules/barcode/mod_barcode_thirdparty_standard.php @@ -110,7 +110,7 @@ class mod_barcode_thirdparty_standard extends ModeleNumRefBarCode //$texte.= ''.$langs->trans("Mask").' ('.$langs->trans("BarCodeModel").'):'; $texte .= ''.$langs->trans("Mask").':'; $texte .= ''.$form->textwithpicto('', $tooltip, 1, 1).''; - $texte .= '  '; + $texte .= '  '; $texte .= ''; $texte .= ''; From 77b3e511bedcaa04f4c550df326b4c3eff6462f8 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Fri, 29 Jul 2022 08:51:57 +0200 Subject: [PATCH 349/826] Del file lang --- htdocs/ftp/admin/ftpclient.php | 2 +- htdocs/ftp/index.php | 2 +- htdocs/langs/en_US/ftp.lang | 15 --------------- htdocs/langs/en_US/other.lang | 16 ++++++++++++++++ 4 files changed, 18 insertions(+), 17 deletions(-) delete mode 100644 htdocs/langs/en_US/ftp.lang diff --git a/htdocs/ftp/admin/ftpclient.php b/htdocs/ftp/admin/ftpclient.php index f914c835b37..c3d5509aa36 100644 --- a/htdocs/ftp/admin/ftpclient.php +++ b/htdocs/ftp/admin/ftpclient.php @@ -25,7 +25,7 @@ require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; -$langs->loadLangs(array('ftp', "admin", "other")); +$langs->loadLangs(array("admin", "other")); $def = array(); $lastftpentry = 0; diff --git a/htdocs/ftp/index.php b/htdocs/ftp/index.php index 54e66e845d4..7fc13259cdc 100644 --- a/htdocs/ftp/index.php +++ b/htdocs/ftp/index.php @@ -30,7 +30,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/treeview.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/ftp.lib.php'; // Load translation files required by the page -$langs->loadLangs(array('ftp', 'companies', 'other')); +$langs->loadLangs(array('companies', 'other')); // Security check if ($user->socid) { diff --git a/htdocs/langs/en_US/ftp.lang b/htdocs/langs/en_US/ftp.lang deleted file mode 100644 index 26791d63918..00000000000 --- a/htdocs/langs/en_US/ftp.lang +++ /dev/null @@ -1,15 +0,0 @@ -# FTP -FTPClientSetup=FTP or SFTP Client module setup -NewFTPClient=New FTP/SFTP connection setup -FTPArea=FTP/SFTP Area -FTPAreaDesc=This screen shows a view of an FTP et SFTP server. -SetupOfFTPClientModuleNotComplete=The setup of the FTP or SFTP client module seems to be incomplete -FTPFeatureNotSupportedByYourPHP=Your PHP does not support FTP or SFTP functions -FailedToConnectToFTPServer=Failed to connect to server (server %s, port %s) -FailedToConnectToFTPServerWithCredentials=Failed to login to server with defined login/password -FTPFailedToRemoveFile=Failed to remove file %s. -FTPFailedToRemoveDir=Failed to remove directory %s: check permissions and that the directory is empty. -FTPPassiveMode=Passive mode -ChooseAFTPEntryIntoMenu=Choose a FTP/SFTP site from the menu... -FailedToGetFile=Failed to get files %s -ErrorFTPNodisconnect=Error to disconnect FTP/SFTP server \ No newline at end of file diff --git a/htdocs/langs/en_US/other.lang b/htdocs/langs/en_US/other.lang index 2bb316f648f..0918bf54ac7 100644 --- a/htdocs/langs/en_US/other.lang +++ b/htdocs/langs/en_US/other.lang @@ -310,3 +310,19 @@ ExternalSiteSetup=Setup link to external website ExternalSiteURL=External Site URL of HTML iframe content ExternalSiteModuleNotComplete=Module ExternalSite was not configured properly. ExampleMyMenuEntry=My menu entry + +# ftp +FTPClientSetup=FTP or SFTP Client module setup +NewFTPClient=New FTP/SFTP connection setup +FTPArea=FTP/SFTP Area +FTPAreaDesc=This screen shows a view of an FTP et SFTP server. +SetupOfFTPClientModuleNotComplete=The setup of the FTP or SFTP client module seems to be incomplete +FTPFeatureNotSupportedByYourPHP=Your PHP does not support FTP or SFTP functions +FailedToConnectToFTPServer=Failed to connect to server (server %s, port %s) +FailedToConnectToFTPServerWithCredentials=Failed to login to server with defined login/password +FTPFailedToRemoveFile=Failed to remove file %s. +FTPFailedToRemoveDir=Failed to remove directory %s: check permissions and that the directory is empty. +FTPPassiveMode=Passive mode +ChooseAFTPEntryIntoMenu=Choose a FTP/SFTP site from the menu... +FailedToGetFile=Failed to get files %s +ErrorFTPNodisconnect=Error to disconnect FTP/SFTP server \ No newline at end of file From 05c37bb1e9e3c4b41693dc79dbe05b51e7555ad5 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Fri, 29 Jul 2022 10:05:54 +0200 Subject: [PATCH 350/826] Add functions --- htdocs/core/lib/ftp.lib.php | 117 ++++++++++++++++++++++++++++++++---- htdocs/ftp/index.php | 67 +++------------------ 2 files changed, 114 insertions(+), 70 deletions(-) diff --git a/htdocs/core/lib/ftp.lib.php b/htdocs/core/lib/ftp.lib.php index d7ce0435c0d..db4b6abccf0 100644 --- a/htdocs/core/lib/ftp.lib.php +++ b/htdocs/core/lib/ftp.lib.php @@ -39,11 +39,12 @@ */ function dol_ftp_connect($ftp_server, $ftp_port, $ftp_user, $ftp_password, $section, $ftp_passive = 0) { + global $langs, $conf; $ok = 1; $error = 0; - $conn_id = null; + $connect_id = null; $newsectioniso = ''; $mesg=""; @@ -59,24 +60,24 @@ function dol_ftp_connect($ftp_server, $ftp_port, $ftp_user, $ftp_password, $sect $tmp_conn_id = ssh2_connect($ftp_server, $ftp_port); } elseif (!empty($conf->global->FTP_CONNECT_WITH_SSL)) { dol_syslog('Try to connect with ftp_ssl_connect'); - $conn_id = ftp_ssl_connect($ftp_server, $ftp_port, $connecttimeout); + $connect_id = ftp_ssl_connect($ftp_server, $ftp_port, $connecttimeout); } else { dol_syslog('Try to connect with ftp_connect'); - $conn_id = ftp_connect($ftp_server, $ftp_port, $connecttimeout); + $connect_id = ftp_connect($ftp_server, $ftp_port, $connecttimeout); } - if (!empty($conn_id) || !empty($tmp_conn_id)) { + if (!empty($connect_id) || !empty($tmp_conn_id)) { if ($ftp_user) { if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) { dol_syslog('Try to authenticate with ssh2_auth_password'); if (ssh2_auth_password($tmp_conn_id, $ftp_user, $ftp_password)) { // Turn on passive mode transfers (must be after a successful login - //if ($ftp_passive) ftp_pasv($conn_id, true); + //if ($ftp_passive) ftp_pasv($connect_id, true); // Change the dir $newsectioniso = utf8_decode($section); - //ftp_chdir($conn_id, $newsectioniso); - $conn_id = ssh2_sftp($tmp_conn_id); - if (!$conn_id) { + //ftp_chdir($connect_id, $newsectioniso); + $connect_id = ssh2_sftp($tmp_conn_id); + if (!$connect_id) { dol_syslog('Failed to connect to SFTP after sssh authentication', LOG_DEBUG); $mesg = $langs->transnoentitiesnoconv("FailedToConnectToSFTPAfterSSHAuthentication"); $ok = 0; @@ -89,15 +90,15 @@ function dol_ftp_connect($ftp_server, $ftp_port, $ftp_user, $ftp_password, $sect $error++; } } else { - if (ftp_login($conn_id, $ftp_user, $ftp_password)) { + if (ftp_login($connect_id, $ftp_user, $ftp_password)) { // Turn on passive mode transfers (must be after a successful login if ($ftp_passive) { - ftp_pasv($conn_id, true); + ftp_pasv($connect_id, true); } // Change the dir $newsectioniso = utf8_decode($section); - ftp_chdir($conn_id, $newsectioniso); + ftp_chdir($connect_id, $newsectioniso); } else { $mesg = $langs->transnoentitiesnoconv("FailedToConnectToFTPServerWithCredentials"); $ok = 0; @@ -112,7 +113,7 @@ function dol_ftp_connect($ftp_server, $ftp_port, $ftp_user, $ftp_password, $sect } } - $arrayresult = array('conn_id'=>$conn_id, 'ok'=>$ok, 'mesg'=>$mesg, 'curdir'=>$section, 'curdiriso'=>$newsectioniso); + $arrayresult = array('conn_id'=>$connect_id, 'ok'=>$ok, 'mesg'=>$mesg, 'curdir'=>$section, 'curdiriso'=>$newsectioniso); return $arrayresult; } @@ -126,6 +127,7 @@ function dol_ftp_connect($ftp_server, $ftp_port, $ftp_user, $ftp_password, $sect */ function ftp_isdir($connect_id, $dir) { + if (@ftp_chdir($connect_id, $dir)) { ftp_cdup($connect_id); return 1; @@ -138,9 +140,13 @@ function ftp_isdir($connect_id, $dir) * Tell if an entry is a FTP directory * * @param resource $connect_id Connection handler + * @return result */ function dol_ftp_close($connect_id) { + + global $conf; + // Close FTP connection if ($connect_id) { if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) { @@ -151,3 +157,90 @@ function dol_ftp_close($connect_id) } } } + +/** + * Delete a FTP file + * + * @param resource $connect_id Connection handler + * @param string $file File + * @param string $newsection $newsection + */ +function dol_ftp_delete($connect_id, $file, $newsection) +{ + + global $conf; + + if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) { + $newsection = ssh2_sftp_realpath($connect_id, ".").'/./'; // workaround for bug https://bugs.php.net/bug.php?id=64169 + } + + // Remote file + $filename = $file; + $remotefile = $newsection.(preg_match('@[\\\/]$@', $newsection) ? '' : '/').$file; + $newremotefileiso = utf8_decode($remotefile); + + //print "x".$newremotefileiso; + dol_syslog("ftp/index.php ftp_delete ".$newremotefileiso); + if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) { + return ssh2_sftp_unlink($connect_id, $newremotefileiso); + } else { + var_dump($newremotefileiso); + return @ftp_delete($connect_id, $newremotefileiso); + } +} + +/** + * Download a FTP file + * + * @param resource $connect_id Connection handler + * @param string $file File + * @param string $newsection $newsection + */ +function dol_ftp_get($connect_id, $file, $newsection) +{ + + global $conf; + + if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) { + $newsection = ssh2_sftp_realpath($connect_id, ".").'/./'; // workaround for bug https://bugs.php.net/bug.php?id=64169 + } + + // Remote file + $filename = $file; + $remotefile = $newsection.(preg_match('@[\\\/]$@', $newsection) ? '' : '/').$file; + $newremotefileiso = utf8_decode($remotefile); + + if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) { + return fopen('ssh2.sftp://'.intval($connect_id).$newremotefileiso, 'r'); + } else { + return ftp_get($connect_id, $localfile, $newremotefileiso, FTP_BINARY); + } +} + +/** + * Remove FTP directory + * + * @param resource $connect_id Connection handler + * @param string $file File + * @param string $newsection $newsection + */ +function dol_ftp_rmdir($connect_id, $file, $newsection) +{ + + global $conf; + + if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) { + $newsection = ssh2_sftp_realpath($connect_id, ".").'/./'; // workaround for bug https://bugs.php.net/bug.php?id=64169 + } + + // Remote file + $filename = $file; + $remotefile = $newsection.(preg_match('@[\\\/]$@', $newsection) ? '' : '/').$file; + $newremotefileiso = utf8_decode($remotefile); + + if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) { + $result = ssh2_sftp_rmdir($connect_id, $newremotefileiso); + } else { + $result = @ftp_rmdir($connect_id, $newremotefileiso); + } +} diff --git a/htdocs/ftp/index.php b/htdocs/ftp/index.php index 7fc13259cdc..324e3b27a38 100644 --- a/htdocs/ftp/index.php +++ b/htdocs/ftp/index.php @@ -160,24 +160,8 @@ if ($action == 'confirm_deletefile' && GETPOST('confirm') == 'yes') { if ($conn_id && $ok && !$mesg) { $newsection = $section; - if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) { - $newsection = ssh2_sftp_realpath($conn_id, ".").'/./'; // workaround for bug https://bugs.php.net/bug.php?id=64169 - } + $result = dol_ftp_delete($conn_id, $file, $newsection); - $langs->load("other"); - - // Remote file - $filename = $file; - $remotefile = $newsection.(preg_match('@[\\\/]$@', $newsection) ? '' : '/').$file; - $newremotefileiso = utf8_decode($remotefile); - - //print "x".$newremotefileiso; - dol_syslog("ftp/index.php ftp_delete ".$newremotefileiso); - if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) { - $result = ssh2_sftp_unlink($conn_id, $newremotefileiso); - } else { - $result = @ftp_delete($conn_id, $newremotefileiso); - } if ($result) { setEventMessages($langs->trans("FileWasRemoved", $file), null, 'mesgs'); } else { @@ -185,8 +169,6 @@ if ($action == 'confirm_deletefile' && GETPOST('confirm') == 'yes') { setEventMessages($langs->trans("FTPFailedToRemoveFile", $file), null, 'errors'); } - //ftp_close($conn_id); Close later - $action = ''; } else { dol_print_error('', $mesg); @@ -206,25 +188,17 @@ if (GETPOST("const", 'array') && GETPOST("delete") && GETPOST("delete") == $lang if ($conn_id && $ok && !$mesg) { foreach (GETPOST('const', 'array') as $const) { - if ($const["check"]) { // Is checkbox checked + var_dump($const); + if (isset($const["check"])) { // Is checkbox checked $langs->load("other"); // Remote file $file = $const["file"]; $newsection = $const["section"]; - if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) { - $newsection = ssh2_sftp_realpath($conn_id, ".").'/./'; // workaround for bug https://bugs.php.net/bug.php?id=64169 - } - $remotefile = $newsection.(preg_match('@[\\\/]$@', $newsection) ? '' : '/').$file; - $newremotefileiso = utf8_decode($remotefile); + $newsection = $section; - //print "x".$newremotefileiso; - dol_syslog("ftp/index.php ftp_delete n files for ".$newremotefileiso); - if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) { - $result = ssh2_sftp_unlink($conn_id, $newremotefileiso); - } else { - $result = @ftp_delete($conn_id, $newremotefileiso); - } + $result = dol_ftp_delete($conn_id, $file, $newsection); + var_dump($newsection); if ($result) { setEventMessages($langs->trans("FileWasRemoved", $file), null, 'mesgs'); } else { @@ -255,20 +229,9 @@ if ($action == 'confirm_deletesection' && $confirm == 'yes') { if ($conn_id && $ok && !$mesg) { $newsection = $section; - if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) { - $newsection = ssh2_sftp_realpath($conn_id, ".").'/./'; // workaround for bug https://bugs.php.net/bug.php?id=64169 - } - // Remote file - $filename = $file; - $remotefile = $newsection.(preg_match('@[\\\/]$@', $newsection) ? '' : '/').$file; - $newremotefileiso = utf8_decode($remotefile); + $result = dol_ftp_rmdir($connect_id, $file, $newsection); - if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) { - $result = ssh2_sftp_rmdir($conn_id, $newremotefileiso); - } else { - $result = @ftp_rmdir($conn_id, $newremotefileiso); - } if ($result) { setEventMessages($langs->trans("DirWasRemoved", $file), null, 'mesgs'); } else { @@ -299,20 +262,10 @@ if ($action == 'download') { $localfile = tempnam($download_dir, 'dol_'); $newsection = $section; - if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) { - $newsection = ssh2_sftp_realpath($conn_id, ".").'/./'; // workaround for bug https://bugs.php.net/bug.php?id=64169 - } - // Remote file - $filename = $file; - $remotefile = $newsection.(preg_match('@[\\\/]$@', $newsection) ? '' : '/').$file; - $newremotefileiso = utf8_decode($remotefile); + $result = dol_ftp_get($connect_id, $file, $newsection); + - if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) { - $result = fopen('ssh2.sftp://'.intval($conn_id).$newremotefileiso, 'r'); - } else { - $result = ftp_get($conn_id, $localfile, $newremotefileiso, FTP_BINARY); - } if ($result) { if (!empty($conf->global->MAIN_UMASK)) { @chmod($localfile, octdec($conf->global->MAIN_UMASK)); @@ -345,8 +298,6 @@ if ($action == 'download') { readfile($localfile); - ftp_close($conn_id); - exit; } else { setEventMessages($langs->transnoentitiesnoconv('FailedToGetFile', $remotefile), null, 'errors'); From cb59edb58b28ef015f6c50f873da1ddf7e1843dd Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Fri, 29 Jul 2022 10:06:19 +0200 Subject: [PATCH 351/826] Fix --- htdocs/core/lib/ftp.lib.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/core/lib/ftp.lib.php b/htdocs/core/lib/ftp.lib.php index db4b6abccf0..19dacfdea76 100644 --- a/htdocs/core/lib/ftp.lib.php +++ b/htdocs/core/lib/ftp.lib.php @@ -164,6 +164,7 @@ function dol_ftp_close($connect_id) * @param resource $connect_id Connection handler * @param string $file File * @param string $newsection $newsection + * @return result */ function dol_ftp_delete($connect_id, $file, $newsection) { @@ -195,6 +196,7 @@ function dol_ftp_delete($connect_id, $file, $newsection) * @param resource $connect_id Connection handler * @param string $file File * @param string $newsection $newsection + * @return result */ function dol_ftp_get($connect_id, $file, $newsection) { @@ -223,6 +225,7 @@ function dol_ftp_get($connect_id, $file, $newsection) * @param resource $connect_id Connection handler * @param string $file File * @param string $newsection $newsection + * @return result */ function dol_ftp_rmdir($connect_id, $file, $newsection) { From 8e7fa102b85030e63ee7c50636d35e4f118e3716 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Fri, 29 Jul 2022 11:14:28 +0200 Subject: [PATCH 352/826] Clean --- htdocs/core/lib/ftp.lib.php | 5 ++--- htdocs/ftp/index.php | 13 ++++--------- htdocs/langs/en_US/companies.lang | 2 +- htdocs/langs/fr_FR/companies.lang | 2 +- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/htdocs/core/lib/ftp.lib.php b/htdocs/core/lib/ftp.lib.php index 19dacfdea76..42f5806fba5 100644 --- a/htdocs/core/lib/ftp.lib.php +++ b/htdocs/core/lib/ftp.lib.php @@ -185,7 +185,6 @@ function dol_ftp_delete($connect_id, $file, $newsection) if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) { return ssh2_sftp_unlink($connect_id, $newremotefileiso); } else { - var_dump($newremotefileiso); return @ftp_delete($connect_id, $newremotefileiso); } } @@ -242,8 +241,8 @@ function dol_ftp_rmdir($connect_id, $file, $newsection) $newremotefileiso = utf8_decode($remotefile); if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) { - $result = ssh2_sftp_rmdir($connect_id, $newremotefileiso); + return ssh2_sftp_rmdir($connect_id, $newremotefileiso); } else { - $result = @ftp_rmdir($connect_id, $newremotefileiso); + return @ftp_rmdir($connect_id, $newremotefileiso); } } diff --git a/htdocs/ftp/index.php b/htdocs/ftp/index.php index 324e3b27a38..cf647929ac8 100644 --- a/htdocs/ftp/index.php +++ b/htdocs/ftp/index.php @@ -188,17 +188,15 @@ if (GETPOST("const", 'array') && GETPOST("delete") && GETPOST("delete") == $lang if ($conn_id && $ok && !$mesg) { foreach (GETPOST('const', 'array') as $const) { - var_dump($const); if (isset($const["check"])) { // Is checkbox checked $langs->load("other"); // Remote file $file = $const["file"]; $newsection = $const["section"]; - $newsection = $section; $result = dol_ftp_delete($conn_id, $file, $newsection); - var_dump($newsection); + if ($result) { setEventMessages($langs->trans("FileWasRemoved", $file), null, 'mesgs'); } else { @@ -230,7 +228,7 @@ if ($action == 'confirm_deletesection' && $confirm == 'yes') { if ($conn_id && $ok && !$mesg) { $newsection = $section; - $result = dol_ftp_rmdir($connect_id, $file, $newsection); + $result = dol_ftp_rmdir($conn_id, $file, $newsection); if ($result) { setEventMessages($langs->trans("DirWasRemoved", $file), null, 'mesgs'); @@ -361,12 +359,12 @@ if (!function_exists('ftp_connect')) { if (!empty($ftp_server)) { // Confirm remove file if ($action == 'delete') { - print $form->formconfirm($_SERVER["PHP_SELF"].'?numero_ftp='.$numero_ftp.'§ion='.urlencode(GETPOST('section')).'&file='.urlencode(GETPOST('file')), $langs->trans('DeleteFile'), $langs->trans('ConfirmDeleteFile'), 'confirm_deletefile', '', '', 1); + print $form->formconfirm($_SERVER["PHP_SELF"].'?numero_ftp='.$numero_ftp.'§ion='.urlencode(GETPOST('section')).'&file='.urlencode(GETPOST('file')), $langs->trans('DeleteFile'), $langs->trans('ConfirmDeleteFile', GETPOST('file')), 'confirm_deletefile', '', '', 1); } // Confirmation de la suppression d'une ligne categorie if ($action == 'delete_section') { - print $form->formconfirm($_SERVER["PHP_SELF"].'?numero_ftp='.$numero_ftp.'§ion='.urlencode(GETPOST('section')).'&file='.urlencode(GETPOST('file')), $langs->trans('DeleteSection'), $langs->trans('ConfirmDeleteSection', $ecmdir->label), 'confirm_deletesection', '', '', 1); + print $form->formconfirm($_SERVER["PHP_SELF"].'?numero_ftp='.$numero_ftp.'§ion='.urlencode(GETPOST('section')).'&file='.urlencode(GETPOST('file')), $langs->trans('DeleteSection'), $langs->trans('ConfirmDeleteSection', GETPOST('file')), 'confirm_deletesection', '', '', 1); } print $langs->trans("Server").': '.$ftp_server.'
'; @@ -456,8 +454,6 @@ if (!function_exists('ftp_connect')) { } else { $buff = ftp_rawlist($conn_id, $newsectioniso); $contents = ftp_nlist($conn_id, $newsectioniso); // Sometimes rawlist fails but never nlist - //var_dump($contents); - //var_dump($buff); } $nboflines = count($contents); @@ -467,7 +463,6 @@ if (!function_exists('ftp_connect')) { while ($i < $nboflines && $i < 1000) { $vals = preg_split('@ +@', utf8_encode($buff[$i]), 9); //$vals=preg_split('@ +@','drwxr-xr-x 2 root root 4096 Aug 30 2008 backup_apollon1',9); - //var_dump($vals); $file = $vals[8]; if (empty($file)) { $rawlisthasfailed = true; diff --git a/htdocs/langs/en_US/companies.lang b/htdocs/langs/en_US/companies.lang index 71b16f24506..996c98c203a 100644 --- a/htdocs/langs/en_US/companies.lang +++ b/htdocs/langs/en_US/companies.lang @@ -444,7 +444,7 @@ AddAddress=Add address SupplierCategory=Vendor category JuridicalStatus200=Independent DeleteFile=Delete file -ConfirmDeleteFile=Are you sure you want to delete this file? +ConfirmDeleteFile=Are you sure you want to delete this file %s? AllocateCommercial=Assigned to sales representative Organization=Organization FiscalYearInformation=Fiscal Year diff --git a/htdocs/langs/fr_FR/companies.lang b/htdocs/langs/fr_FR/companies.lang index 889f16b3f75..3359131aa51 100644 --- a/htdocs/langs/fr_FR/companies.lang +++ b/htdocs/langs/fr_FR/companies.lang @@ -443,7 +443,7 @@ AddAddress=Créer adresse SupplierCategory=Catégorie du fournisseur JuridicalStatus200=Indépendant DeleteFile=Suppression d'un fichier -ConfirmDeleteFile=Êtes-vous sûr de vouloir supprimer ce fichier ? +ConfirmDeleteFile=Êtes-vous sûr de vouloir supprimer ce fichier %s? AllocateCommercial=Affecter un commercial Organization=Organisme FiscalYearInformation=Exercice fiscal From 79e0d59978b765bf18a4b77b28cd821e0fc9dd62 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 29 Jul 2022 11:48:17 +0200 Subject: [PATCH 353/826] Fix regression --- htdocs/contact/card.php | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/htdocs/contact/card.php b/htdocs/contact/card.php index 649fcc00fb4..0ef31fe36a4 100644 --- a/htdocs/contact/card.php +++ b/htdocs/contact/card.php @@ -567,19 +567,22 @@ $form = new Form($db); $formadmin = new FormAdmin($db); $formcompany = new FormCompany($db); +$objsoc = new Societe($db); +if ($socid > 0) { + $objsoc->fetch($socid); +} + $title = (!empty($conf->global->SOCIETE_ADDRESSES_MANAGEMENT) ? $langs->trans("Contacts") : $langs->trans("ContactsAddresses")); if (!empty($conf->global->MAIN_HTML_TITLE) && preg_match('/contactnameonly/', $conf->global->MAIN_HTML_TITLE) && $object->lastname) { $title = $object->lastname; } $help_url = 'EN:Module_Third_Parties|FR:Module_Tiers|ES:Empresas'; +$title = (!empty($conf->global->SOCIETE_ADDRESSES_MANAGEMENT) ? $langs->trans("NewContact") : $langs->trans("NewContactAddress")); + +llxHeader('', $title, $help_url); $countrynotdefined = $langs->trans("ErrorSetACountryFirst").' ('.$langs->trans("SeeAbove").')'; -$objsoc = new Societe($db); -if ($socid > 0) { - $objsoc->fetch($socid); -} - if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { // ----------------------------------------- // When used with CANVAS @@ -621,8 +624,6 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { // Show tabs $head = contact_prepare_head($object); - - llxHeader('', $title, $help_url); } if ($user->rights->societe->contact->creer) { @@ -643,9 +644,6 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { } $linkback = ''; - $title = (!empty($conf->global->SOCIETE_ADDRESSES_MANAGEMENT) ? $langs->trans("NewContact") : $langs->trans("NewContactAddress")); - - llxHeader('', $title, $help_url); print load_fiche_titre($title, $linkback, 'address'); From 31fa326615af01987b962af4394691e09533925e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 29 Jul 2022 11:54:56 +0200 Subject: [PATCH 354/826] Fix missing import key --- htdocs/contact/list.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/htdocs/contact/list.php b/htdocs/contact/list.php index 1e497b0ab2e..8d60b37611f 100644 --- a/htdocs/contact/list.php +++ b/htdocs/contact/list.php @@ -373,6 +373,7 @@ $sql = "SELECT s.rowid as socid, s.nom as name,"; $sql .= " p.rowid, p.lastname as lastname, p.statut, p.firstname, p.address, p.zip, p.town, p.poste, p.email,"; $sql .= " p.socialnetworks, p.photo,"; $sql .= " p.phone as phone_pro, p.phone_mobile, p.phone_perso, p.fax, p.fk_pays, p.priv, p.datec as date_creation, p.tms as date_update,"; +$sql .= " p.import_key,"; $sql .= " st.libelle as stcomm, st.picto as stcomm_picto, p.fk_stcommcontact as stcomm_id, p.fk_prospectcontactlevel,"; $sql .= " co.label as country, co.code as country_code"; // Add fields from extrafields @@ -1074,6 +1075,7 @@ while ($i < min($num, $limit)) { $contactstatic->country = $obj->country; $contactstatic->country_code = $obj->country_code; $contactstatic->photo = $obj->photo; + $contactstatic->import_key = $obj->import_key; $contactstatic->fk_prospectlevel = $obj->fk_prospectcontactlevel; @@ -1309,9 +1311,10 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } + // Import key if (!empty($arrayfields['p.import_key']['checked'])) { print ''; - print $obj->import_key; + print dol_escape_htmltag($obj->import_key); print "\n"; if (!$i) { $totalarray['nbfield']++; From 64fc74087bab2020d851ce3622f57c4bc766cc1f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 29 Jul 2022 12:31:51 +0200 Subject: [PATCH 355/826] NEW Add link to create an element from the category page --- htdocs/adherents/card.php | 5 +++++ htdocs/categories/viewcat.php | 41 ++++++++++++++++++++--------------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php index 2e04a29b69f..44a12293e67 100644 --- a/htdocs/adherents/card.php +++ b/htdocs/adherents/card.php @@ -621,6 +621,11 @@ if (empty($reshook)) { } } $action = ($result < 0 || !$error) ? '' : 'create'; + + if (!$error && $backtopage) { + header("Location: ".$backtopage); + exit; + } } if ($user->rights->adherent->supprimer && $action == 'confirm_delete' && $confirm == 'yes') { diff --git a/htdocs/categories/viewcat.php b/htdocs/categories/viewcat.php index 7e8a1252095..5450127bff3 100644 --- a/htdocs/categories/viewcat.php +++ b/htdocs/categories/viewcat.php @@ -103,7 +103,7 @@ if ($confirm == 'no') { $parameters = array(); $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks // Remove element from category -if ($id > 0 && $removeelem > 0) { +if ($id > 0 && $removeelem > 0 && $action == 'unlink') { if ($type == Categorie::TYPE_PRODUCT && ($user->rights->produit->creer || $user->rights->service->creer)) { require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; $tmpobject = new Product($db); @@ -521,7 +521,8 @@ if ($type == Categorie::TYPE_PRODUCT) { print ''; print '
'; - $param = '&limit='.$limit.'&id='.$id.'&type='.$type; $num = count($prods); $nbtotalofrecords = ''; $newcardbutton = ''; + $param = '&limit='.$limit.'&id='.$id.'&type='.$type; $num = count($prods); $nbtotalofrecords = ''; + $newcardbutton = dolGetButtonTitle($langs->trans("AddProduct"), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/product/card.php?action=create&categories[]='.$object->id.'&backtopage='.urlencode($_SERVER["PHP_SELF"].'?id='.$object->id), '', $user->rights->societe->creer); print_barre_liste($langs->trans("ProductsAndServices"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'products', 0, $newcardbutton, '', $limit); @@ -544,7 +545,7 @@ if ($type == Categorie::TYPE_PRODUCT) { // Link to delete from category print ''; if ($permission) { - print "
"; + print "id."'>"; print $langs->trans("DeleteFromCat"); print img_picto($langs->trans("DeleteFromCat"), 'unlink', '', false, 0, 0, '', 'paddingleft'); print ""; @@ -597,7 +598,8 @@ if ($type == Categorie::TYPE_CUSTOMER) { print ''; print '
'; - $param = '&limit='.$limit.'&id='.$id.'&type='.$type; $num = count($socs); $nbtotalofrecords = ''; $newcardbutton = ''; + $param = '&limit='.$limit.'&id='.$id.'&type='.$type; $num = count($socs); $nbtotalofrecords = ''; + $newcardbutton = dolGetButtonTitle($langs->trans("AddThirdParty"), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/societe/card.php?action=create&client=3&custcats[]='.$object->id.'&backtopage='.urlencode($_SERVER["PHP_SELF"].'?id='.$object->id), '', $user->rights->societe->creer); print_barre_liste($langs->trans("Customers"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'companies', 0, $newcardbutton, '', $limit); print ''."\n"; @@ -618,7 +620,7 @@ if ($type == Categorie::TYPE_CUSTOMER) { // Link to delete from category print '
'; if ($permission) { - print ""; + print "id."'>"; print $langs->trans("DeleteFromCat"); print img_picto($langs->trans("DeleteFromCat"), 'unlink', '', false, 0, 0, '', 'paddingleft'); print ""; @@ -671,7 +673,8 @@ if ($type == Categorie::TYPE_SUPPLIER) { print ''; print '
'; - $param = '&limit='.$limit.'&id='.$id.'&type='.$type; $num = count($socs); $nbtotalofrecords = ''; $newcardbutton = ''; + $param = '&limit='.$limit.'&id='.$id.'&type='.$type; $num = count($socs); $nbtotalofrecords = ''; + $newcardbutton = dolGetButtonTitle($langs->trans("AddSupplier"), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/societe/card.php?action=create&fournisseur=1&suppcats[]='.$object->id.'&backtopage='.urlencode($_SERVER["PHP_SELF"].'?id='.$object->id), '', $user->rights->societe->creer); print_barre_liste($langs->trans("Suppliers"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'companies', 0, $newcardbutton, '', $limit); print ''."\n"; @@ -692,7 +695,7 @@ if ($type == Categorie::TYPE_SUPPLIER) { // Link to delete from category print '
'; if ($permission) { - print ""; + print "id."'>"; print $langs->trans("DeleteFromCat"); print img_picto($langs->trans("DeleteFromCat"), 'unlink', '', false, 0, 0, '', 'paddingleft'); print ""; @@ -748,7 +751,8 @@ if ($type == Categorie::TYPE_MEMBER) { print ''; print '
'; - $param = '&limit='.$limit.'&id='.$id.'&type='.$type; $num = count($prods); $nbtotalofrecords = ''; $newcardbutton = ''; + $param = '&limit='.$limit.'&id='.$id.'&type='.$type; $num = count($prods); $nbtotalofrecords = ''; + $newcardbutton = dolGetButtonTitle($langs->trans("AddMember"), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/adherents/card.php?action=create&memcats[]='.$object->id.'&backtopage='.urlencode($_SERVER["PHP_SELF"].'?id='.$object->id), '', $user->rights->adherent->creer); print_barre_liste($langs->trans("Member"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'members', 0, $newcardbutton, '', $limit); print "\n"; @@ -772,7 +776,7 @@ if ($type == Categorie::TYPE_MEMBER) { // Link to delete from category print '\s*$/g,ra={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"
'; if ($permission) { - print ""; + print "id."'>"; print $langs->trans("DeleteFromCat"); print img_picto($langs->trans("DeleteFromCat"), 'unlink', '', false, 0, 0, '', 'paddingleft'); print ""; @@ -788,7 +792,7 @@ if ($type == Categorie::TYPE_MEMBER) { } } -// Categorie contact +// List of contacts if ($type == Categorie::TYPE_CONTACT) { $permission = $user->rights->societe->creer; @@ -808,7 +812,7 @@ if ($type == Categorie::TYPE_CONTACT) { print ''; print ''; print ''; print ''; @@ -826,7 +830,7 @@ if ($type == Categorie::TYPE_CONTACT) { $param = '&limit='.$limit.'&id='.$id.'&type='.$type; $num = count($contacts); $nbtotalofrecords = ''; - $newcardbutton = ''; + $newcardbutton = dolGetButtonTitle($langs->trans("AddContact"), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/contact/card.php?action=create&contcats[]='.$object->id.'&backtopage='.urlencode($_SERVER["PHP_SELF"].'?id='.$object->id), '', $user->rights->societe->creer); $objsoc = new Societe($db); print_barre_liste($langs->trans("Contact"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'contact', 0, $newcardbutton, '', $limit); @@ -853,7 +857,7 @@ if ($type == Categorie::TYPE_CONTACT) { // Link to delete from category print ''; - print ''; + print ''; print '\n"; From 7ff956a1e237121e0baef90f818e3e8cf6bac9c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?This=20Charl=C3=A8ne?= <1179011+defrance@users.noreply.github.com> Date: Fri, 29 Jul 2022 14:24:29 +0200 Subject: [PATCH 359/826] PHP V8 warning --- htdocs/fourn/commande/list.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/fourn/commande/list.php b/htdocs/fourn/commande/list.php index 6d026272cc7..8d03dbb387c 100644 --- a/htdocs/fourn/commande/list.php +++ b/htdocs/fourn/commande/list.php @@ -7,7 +7,7 @@ * Copyright (C) 2014 Juanjo Menent * Copyright (C) 2016 Ferran Marcet * Copyright (C) 2018-2021 Frédéric France - * Copyright (C) 2018-2020 Charlene Benke + * Copyright (C) 2018-2022 Charlene Benke * Copyright (C) 2019 Nicolas Zabouri * Copyright (C) 2021 Alexandre Spangaro * @@ -1557,6 +1557,7 @@ if ($resql) { $totalarray = array('nbfield' => 0, 'val' => array(), 'pos' => array()); $totalarray['val']['cf.total_ht'] = 0; $totalarray['val']['cf.total_ttc'] = 0; + $totalarray['val']['cf.total_tva'] = 0; $imaxinloop = ($limit ? min($num, $limit) : $num); while ($i < $imaxinloop) { From 7404e8fb75567fb06c754f88f0ac21f8c2c01956 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 29 Jul 2022 14:50:21 +0200 Subject: [PATCH 360/826] Debug v16 --- htdocs/compta/index.php | 25 +++++++++++++++---------- htdocs/core/lib/invoice.lib.php | 4 +++- htdocs/langs/en_US/admin.lang | 2 +- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/htdocs/compta/index.php b/htdocs/compta/index.php index e7cb0b1d4b5..55ee99f4cb6 100644 --- a/htdocs/compta/index.php +++ b/htdocs/compta/index.php @@ -102,19 +102,24 @@ print load_fiche_titre($langs->trans("AccountancyTreasuryArea"), '', 'bill'); print '
'; -print getNumberInvoicesPieChart('customers'); -print '
'; +if (isModEnabled('facture')) { + print getNumberInvoicesPieChart('customers'); + print '
'; +} -if (!empty($conf->fournisseur->enabled)) { +if (isModEnabled('fournisseur') || isModEnabled('supplier_invoice')) { print getNumberInvoicesPieChart('fourn'); print '
'; } -print getCustomerInvoiceDraftTable($max, $socid); - -if (!empty($conf->fournisseur->enabled)) { +if (isModEnabled('facture')) { + print getCustomerInvoiceDraftTable($max, $socid); print '
'; +} + +if (isModEnabled('fournisseur') || isModEnabled('supplier_invoice')) { print getDraftSupplierTable($max, $socid); + print '
'; } print '
'; @@ -273,7 +278,7 @@ if (isModEnabled('facture') && !empty($user->rights->facture->lire)) { // Last modified supplier invoices -if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->facture->lire) || (!empty($conf->supplier_invoice->enabled) && $user->rights->supplier_invoice->lire)) { +if ((isModEnabled('fournisseur') && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->facture->lire) || (isModEnabled('supplier_invoice') && $user->rights->supplier_invoice->lire)) { $langs->load("boxes"); $facstatic = new FactureFournisseur($db); @@ -400,7 +405,7 @@ if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SU // Latest donations -if (!empty($conf->don->enabled) && !empty($user->rights->don->lire)) { +if (isModEnabled('don') && !empty($user->rights->don->lire)) { include_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php'; $langs->load("boxes"); @@ -490,7 +495,7 @@ if (!empty($conf->don->enabled) && !empty($user->rights->don->lire)) { /** * Social contributions to pay */ -if (!empty($conf->tax->enabled) && !empty($user->rights->tax->charges->lire)) { +if (isModEnabled('tax') && !empty($user->rights->tax->charges->lire)) { if (!$socid) { $chargestatic = new ChargeSociales($db); @@ -582,7 +587,7 @@ if (!empty($conf->tax->enabled) && !empty($user->rights->tax->charges->lire)) { /* * Customers orders to be billed */ -if (isModEnabled('facture') && !empty($conf->commande->enabled) && $user->rights->commande->lire && empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) { +if (isModEnabled('facture') && isModEnabled('commande') && $user->rights->commande->lire && empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) { $commandestatic = new Commande($db); $langs->load("orders"); diff --git a/htdocs/core/lib/invoice.lib.php b/htdocs/core/lib/invoice.lib.php index ea53ae065e3..52daea0f150 100644 --- a/htdocs/core/lib/invoice.lib.php +++ b/htdocs/core/lib/invoice.lib.php @@ -254,7 +254,9 @@ function supplier_invoice_rec_prepare_head($object) function getNumberInvoicesPieChart($mode) { global $conf, $db, $langs, $user; - if (isModEnabled('facture') && !empty($user->rights->facture->lire)) { + if (($mode == 'customers' && isModEnabled('facture') && !empty($user->rights->facture->lire)) + || ($mode = 'suppliers') && (isModEnabled('fournisseur') || isModEnabled('supplier_invoice')) && !empty($user->rights->facture->lire) + ) { include DOL_DOCUMENT_ROOT.'/theme/'.$conf->theme.'/theme_vars.inc.php'; $now = date_create(date('Y-m-d', dol_now())); diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index c720c3be8a7..c1f01ae85d9 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1130,7 +1130,7 @@ ValueOfConstantKey=Value of a configuration constant ConstantIsOn=Option %s is on NbOfDays=No. of days AtEndOfMonth=At end of month -CurrentNext=Current/Next +CurrentNext=A given day in month Offset=Offset AlwaysActive=Always active Upgrade=Upgrade From 05ca9da7e1a63627cdbf9a3967e320740deae9ec Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Fri, 29 Jul 2022 15:46:13 +0200 Subject: [PATCH 361/826] Fix : php 8.1 warnings --- htdocs/core/lib/functions.lib.php | 2 +- htdocs/core/menus/standard/eldy.lib.php | 4 +- htdocs/main.inc.php | 26 ++++++------- htdocs/user/card.php | 50 ++++++++++++------------- htdocs/user/document.php | 24 ++++++------ htdocs/user/group/card.php | 22 +++++------ htdocs/user/group/list.php | 9 +++-- htdocs/user/group/perms.php | 10 ++--- htdocs/user/hierarchy.php | 4 +- htdocs/user/list.php | 28 +++++++------- htdocs/user/note.php | 14 +++---- htdocs/user/param_ihm.php | 14 +++---- htdocs/user/perms.php | 16 ++++---- 13 files changed, 112 insertions(+), 111 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index b286adae481..89ce32b9069 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -10422,7 +10422,7 @@ function dolGetButtonAction($label, $html = '', $actionType = 'default', $url = global $hookmanager, $action, $object, $langs; //var_dump($params); - if ($params['isDropdown']) + if (!empty($params['isDropdown'])) $class = "dropdown-item"; else { $class = 'butAction'; diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index 3b2a1c1ec50..4707657d3e3 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -1154,7 +1154,7 @@ function get_left_menu_home($mainmenu, &$newmenu, $usemenuhider = 1, $leftmenu = if ($user->rights->user->user->lire) { if ($usemenuhider || empty($leftmenu) || $leftmenu == "users") { $newmenu->add("", $langs->trans("Users"), 1, $user->rights->user->user->lire || $user->admin); - $newmenu->add("/user/card.php?leftmenu=users&action=create", $langs->trans("NewUser"), 2, ($user->rights->user->user->creer || $user->admin) && !(isModEnabled('multicompany') && $conf->entity > 1 && $conf->global->MULTICOMPANY_TRANSVERSE_MODE), '', 'home'); + $newmenu->add("/user/card.php?leftmenu=users&action=create", $langs->trans("NewUser"), 2, ($user->hasRight("user", "user", "write") || $user->admin) && !(isModEnabled('multicompany') && $conf->entity > 1 && $conf->global->MULTICOMPANY_TRANSVERSE_MODE), '', 'home'); $newmenu->add("/user/list.php?leftmenu=users", $langs->trans("ListOfUsers"), 2, $user->rights->user->user->lire || $user->admin); $newmenu->add("/user/hierarchy.php?leftmenu=users", $langs->trans("HierarchicView"), 2, $user->rights->user->user->lire || $user->admin); if (isModEnabled('categorie')) { @@ -1162,7 +1162,7 @@ function get_left_menu_home($mainmenu, &$newmenu, $usemenuhider = 1, $leftmenu = $newmenu->add("/categories/index.php?leftmenu=users&type=7", $langs->trans("UsersCategoriesShort"), 2, $user->rights->categorie->lire, '', $mainmenu, 'cat'); } $newmenu->add("", $langs->trans("Groups"), 1, ($user->rights->user->user->lire || $user->admin) && !(isModEnabled('multicompany') && $conf->entity > 1 && $conf->global->MULTICOMPANY_TRANSVERSE_MODE)); - $newmenu->add("/user/group/card.php?leftmenu=users&action=create", $langs->trans("NewGroup"), 2, ((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) ? $user->rights->user->group_advance->write : $user->rights->user->user->creer) || $user->admin) && !(isModEnabled('multicompany') && $conf->entity > 1 && $conf->global->MULTICOMPANY_TRANSVERSE_MODE)); + $newmenu->add("/user/group/card.php?leftmenu=users&action=create", $langs->trans("NewGroup"), 2, ((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) ? $user->hasRight("user", "group_advance", "create") : $user->hasRight("user", "user", "create")) || $user->admin) && !(isModEnabled('multicompany') && $conf->entity > 1 && $conf->global->MULTICOMPANY_TRANSVERSE_MODE)); $newmenu->add("/user/group/list.php?leftmenu=users", $langs->trans("ListOfGroups"), 2, ((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) ? $user->rights->user->group_advance->read : $user->rights->user->user->lire) || $user->admin) && !(isModEnabled('multicompany') && $conf->entity > 1 && $conf->global->MULTICOMPANY_TRANSVERSE_MODE)); } } diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 5108a5eb332..782f75b0190 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -2413,7 +2413,7 @@ function printDropdownQuickadd() "title" => "MenuNewMember@members", "name" => "Adherent@members", "picto" => "object_member", - "activation" => !empty($conf->adherent->enabled) && $user->rights->adherent->creer, // vs hooking + "activation" => !empty($conf->adherent->enabled) && $user->hasRight("adherent", "write"), // vs hooking "position" => 5, ), array( @@ -2421,7 +2421,7 @@ function printDropdownQuickadd() "title" => "MenuNewThirdParty@companies", "name" => "ThirdParty@companies", "picto" => "object_company", - "activation" => !empty($conf->societe->enabled) && $user->rights->societe->creer, // vs hooking + "activation" => !empty($conf->societe->enabled) && $user->hasRight("societe", "write"), // vs hooking "position" => 10, ), array( @@ -2429,7 +2429,7 @@ function printDropdownQuickadd() "title" => "NewContactAddress@companies", "name" => "Contact@companies", "picto" => "object_contact", - "activation" => !empty($conf->societe->enabled) && $user->rights->societe->contact->creer, // vs hooking + "activation" => !empty($conf->societe->enabled) && $user->hasRight("societe", "contact", "write"), // vs hooking "position" => 20, ), array( @@ -2437,7 +2437,7 @@ function printDropdownQuickadd() "title" => "NewPropal@propal", "name" => "Proposal@propal", "picto" => "object_propal", - "activation" => !empty($conf->propal->enabled) && $user->rights->propale->creer, // vs hooking + "activation" => !empty($conf->propal->enabled) && $user->hasRight("propale", "write"), // vs hooking "position" => 30, ), @@ -2446,7 +2446,7 @@ function printDropdownQuickadd() "title" => "NewOrder@orders", "name" => "Order@orders", "picto" => "object_order", - "activation" => !empty($conf->commande->enabled) && $user->rights->commande->creer, // vs hooking + "activation" => !empty($conf->commande->enabled) && $user->hasRight("commande", "write"), // vs hooking "position" => 40, ), array( @@ -2454,7 +2454,7 @@ function printDropdownQuickadd() "title" => "NewBill@bills", "name" => "Bill@bills", "picto" => "object_bill", - "activation" => isModEnabled('facture') && $user->rights->facture->creer, // vs hooking + "activation" => isModEnabled('facture') && $user->hasRight("facture", "write"), // vs hooking "position" => 50, ), array( @@ -2462,7 +2462,7 @@ function printDropdownQuickadd() "title" => "NewContractSubscription@contracts", "name" => "Contract@contracts", "picto" => "object_contract", - "activation" => !empty($conf->contrat->enabled) && $user->rights->contrat->creer, // vs hooking + "activation" => !empty($conf->contrat->enabled) && $user->hasRight("contrat", "write"), // vs hooking "position" => 60, ), array( @@ -2470,7 +2470,7 @@ function printDropdownQuickadd() "title" => "SupplierProposalNew@supplier_proposal", "name" => "SupplierProposal@supplier_proposal", "picto" => "supplier_proposal", - "activation" => !empty($conf->supplier_proposal->enabled) && $user->rights->supplier_proposal->creer, // vs hooking + "activation" => !empty($conf->supplier_proposal->enabled) && $user->hasRight("supplier_invoice", "write"), // vs hooking "position" => 70, ), array( @@ -2478,7 +2478,7 @@ function printDropdownQuickadd() "title" => "NewSupplierOrderShort@orders", "name" => "SupplierOrder@orders", "picto" => "supplier_order", - "activation" => (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->commande->creer) || (!empty($conf->supplier_order->enabled) && $user->rights->supplier_order->creer), // vs hooking + "activation" => (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "commande", "write")) || (!empty($conf->supplier_order->enabled) && $user->hasRight("supplier_invoice", "write")), // vs hooking "position" => 80, ), array( @@ -2486,7 +2486,7 @@ function printDropdownQuickadd() "title" => "NewBill@bills", "name" => "SupplierBill@bills", "picto" => "supplier_invoice", - "activation" => (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->facture->creer) || (!empty($conf->supplier_invoice->enabled) && $user->rights->supplier_invoice->creer), // vs hooking + "activation" => (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "write")) || (!empty($conf->supplier_invoice->enabled) && $user->hasRight("supplier_invoice", "write")), // vs hooking "position" => 90, ), array( @@ -2494,7 +2494,7 @@ function printDropdownQuickadd() "title" => "NewProduct@products", "name" => "Product@products", "picto" => "object_product", - "activation" => !empty($conf->product->enabled) && $user->rights->produit->creer, // vs hooking + "activation" => !empty($conf->product->enabled) && $user->hasRight("produit", "write"), // vs hooking "position" => 100, ), array( @@ -2502,7 +2502,7 @@ function printDropdownQuickadd() "title" => "NewService@products", "name" => "Service@products", "picto" => "object_service", - "activation" => !empty($conf->service->enabled) && $user->rights->service->creer, // vs hooking + "activation" => !empty($conf->service->enabled) && $user->hasRight("service", "write"), // vs hooking "position" => 110, ), array( @@ -2510,7 +2510,7 @@ function printDropdownQuickadd() "title" => "AddUser@users", "name" => "User@users", "picto" => "user", - "activation" => $user->rights->user->user->creer, // vs hooking + "activation" => $user->hasRight("user", "user", "write"), // vs hooking "position" => 500, ), ), diff --git a/htdocs/user/card.php b/htdocs/user/card.php index 5f8a4be0446..8e375933a91 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -76,15 +76,15 @@ $dateendvalidity = dol_mktime(0, 0, 0, GETPOST('dateendvaliditymonth', 'int'), G $dateofbirth = dol_mktime(0, 0, 0, GETPOST('dateofbirthmonth', 'int'), GETPOST('dateofbirthday', 'int'), GETPOST('dateofbirthyear', 'int')); // Define value to know what current user can do on users -$canadduser = (!empty($user->admin) || $user->rights->user->user->creer); -$canreaduser = (!empty($user->admin) || $user->rights->user->user->lire); -$canedituser = (!empty($user->admin) || $user->rights->user->user->creer); -$candisableuser = (!empty($user->admin) || $user->rights->user->user->supprimer); +$canadduser = (!empty($user->admin) || $user->hasRight("user", "user", "write")); +$canreaduser = (!empty($user->admin) || $user->hasRight("user", "user", "read")); +$canedituser = (!empty($user->admin) || $user->hasRight("user", "user", "write")); +$candisableuser = (!empty($user->admin) || $user->hasRight("user", "user", "delete")); $canreadgroup = $canreaduser; $caneditgroup = $canedituser; if (!empty($conf->global->MAIN_USE_ADVANCED_PERMS)) { - $canreadgroup = (!empty($user->admin) || $user->rights->user->group_advance->read); - $caneditgroup = (!empty($user->admin) || $user->rights->user->group_advance->write); + $canreadgroup = (!empty($user->admin) || $user->hasRight("user", "group_advance", "read")); + $caneditgroup = (!empty($user->admin) || $user->hasRight("user", "group_advance", "write")); } $childids = $user->getAllChildIds(1); // For later, test on salary visibility @@ -92,8 +92,8 @@ $childids = $user->getAllChildIds(1); // For later, test on salary visibility // Define value to know what current user can do on properties of edited user if ($id > 0) { // $user is the current logged user, $id is the user we want to edit - $caneditfield = ((($user->id == $id) && $user->rights->user->self->creer) || (($user->id != $id) && $user->rights->user->user->creer)); - $caneditpassword = ((($user->id == $id) && $user->rights->user->self->password) || (($user->id != $id) && $user->rights->user->user->password)); + $caneditfield = ((($user->id == $id) && $user->hasRight("user", "self", "write")) || (($user->id != $id) && $user->hasRight("user", "user", "write"))); + $caneditpassword = ((($user->id == $id) && $user->hasRight("user", "self", "password")) || (($user->id != $id) && $user->hasRight("user", "user", "password"))); } // Security check @@ -712,7 +712,7 @@ if (empty($reshook)) { // Actions to build doc $upload_dir = $conf->user->dir_output; - $permissiontoadd = $user->rights->user->user->creer; + $permissiontoadd = $user->hasRight("user", "user", "write"); include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php'; } @@ -1165,7 +1165,7 @@ if ($action == 'create' || $action == 'adduserldap') { } // Categories - if (!empty($conf->categorie->enabled) && !empty($user->rights->categorie->lire)) { + if (!empty($conf->categorie->enabled) && !empty($user->hasRight("categorie", "read"))) { print '
'; - if ((!empty($conf->salaries->enabled) && !empty($user->rights->salaries->read) && in_array($id, $childids)) - || (!empty($conf->salaries->enabled) && !empty($user->rights->salaries->readall)) - || (!empty($conf->hrm->enabled) && !empty($user->rights->hrm->employee->read))) { + if ((!empty($conf->salaries->enabled) && !empty($user->hasRight("salaries", "read")) && in_array($id, $childids)) + || (!empty($conf->salaries->enabled) && !empty($user->hasRight("salaries", "readall"))) + || (!empty($conf->hrm->enabled) && !empty($user->hasRight("hrm", "employee", "read")))) { $langs->load("salaries"); // THM @@ -1365,7 +1365,7 @@ if ($action == 'create' || $action == 'adduserldap') { $title = $langs->trans("User"); $linkback = ''; - if ($user->rights->user->user->lire || $user->admin) { + if ($user->hasRight("user", "user", "read") || $user->admin) { $linkback = ''.$langs->trans("BackToList").''; } } @@ -1417,7 +1417,7 @@ if ($action == 'create' || $action == 'adduserldap') { $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; - dol_banner_tab($object, 'id', $linkback, $user->rights->user->user->lire || $user->admin, 'rowid', 'ref', $morehtmlref); + dol_banner_tab($object, 'id', $linkback, $user->hasRight("user", "user", "read") || $user->admin, 'rowid', 'ref', $morehtmlref); print '
'; print '
'; @@ -1541,8 +1541,8 @@ if ($action == 'create' || $action == 'adduserldap') { // Sensitive salary/value information if ((empty($user->socid) && in_array($id, $childids)) // A user can always see salary/value information for its subordinates - || (!empty($conf->salaries->enabled) && !empty($user->rights->salaries->readall)) - || (!empty($conf->hrm->enabled) && !empty($user->rights->hrm->employee->read))) { + || (!empty($conf->salaries->enabled) && !empty($user->hasRight("salaries", "readall"))) + || (!empty($conf->hrm->enabled) && !empty($user->hasRight("hrm", "employee", "read")))) { $langs->load("salaries"); // Salary @@ -1625,7 +1625,7 @@ if ($action == 'create' || $action == 'adduserldap') { } // Categories - if (!empty($conf->categorie->enabled) && !empty($user->rights->categorie->lire)) { + if (!empty($conf->categorie->enabled) && !empty($user->hasRight("categorie", "read"))) { print '
'; print ''."\n"; // API key - if (!empty($conf->api->enabled) && ($user->id == $id || $user->admin || $user->rights->api->apikey->generate)) { + if (!empty($conf->api->enabled) && ($user->id == $id || $user->admin || $user->hasRight("api", "apikey", "generate"))) { print ''; print '\n"; // API key - if (!empty($conf->api->enabled) && ($user->id == $id || $user->admin || $user->rights->api->apikey->generate)) { + if (!empty($conf->api->enabled) && ($user->id == $id || $user->admin || $user->hasRight("api", "apikey", "generate"))) { print ''; print ''; // Categories - if (!empty($conf->categorie->enabled) && !empty($user->rights->categorie->lire)) { + if (!empty($conf->categorie->enabled) && !empty($user->hasRight("categorie", "read"))) { print ''; print ''; - $editenabled = (($action == 'edit') && !empty($user->rights->user->user->creer)); + $editenabled = (($action == 'edit') && !empty($user->hasRight("user", "user", "write"))); // Note print ''; @@ -171,7 +171,7 @@ if ($id) { print '
'; - if ($user->rights->user->user->creer && $action != 'edit') { + if ($user->hasRight("user", "user", "write") && $action != 'edit') { print ''.$langs->trans('Modify').""; } diff --git a/htdocs/user/param_ihm.php b/htdocs/user/param_ihm.php index 4c138bfde6e..6a5eea96490 100644 --- a/htdocs/user/param_ihm.php +++ b/htdocs/user/param_ihm.php @@ -32,7 +32,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; $langs->loadLangs(array('companies', 'products', 'admin', 'users', 'languages', 'projects', 'members')); // Defini si peux lire/modifier permisssions -$canreaduser = ($user->admin || $user->rights->user->user->lire); +$canreaduser = ($user->admin || $user->hasRight("user", "user", "read")); $id = GETPOST('id', 'int'); $action = GETPOST('action', 'aZ09'); @@ -40,8 +40,8 @@ $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'use if ($id) { // $user est le user qui edite, $id est l'id de l'utilisateur edite - $caneditfield = ((($user->id == $id) && $user->rights->user->self->creer) - || (($user->id != $id) && $user->rights->user->user->creer)); + $caneditfield = ((($user->id == $id) && $user->hasRight("user", "self", "write")) + || (($user->id != $id) && $user->hasRight("user", "user", "write"))); } // Security check @@ -49,7 +49,7 @@ $socid = 0; if ($user->socid > 0) { $socid = $user->socid; } -$feature2 = (($socid && $user->rights->user->self->creer) ? '' : 'user'); +$feature2 = (($socid && $user->hasRight("user", "self", "write")) ? '' : 'user'); $result = restrictedArea($user, 'user', $id, 'user&user', $feature2); if ($user->id <> $id && !$canreaduser) { @@ -231,11 +231,11 @@ if ($action == 'edit') { $linkback = ''; - if ($user->rights->user->user->lire || $user->admin) { + if ($user->hasRight("user", "user", "read") || $user->admin) { $linkback = ''.$langs->trans("BackToList").''; } - dol_banner_tab($object, 'id', $linkback, $user->rights->user->user->lire || $user->admin); + dol_banner_tab($object, 'id', $linkback, $user->hasRight("user", "user", "read") || $user->admin); print '
'; @@ -346,7 +346,7 @@ if ($action == 'edit') { $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; - dol_banner_tab($object, 'id', $linkback, $user->rights->user->user->lire || $user->admin, 'rowid', 'ref', $morehtmlref); + dol_banner_tab($object, 'id', $linkback, $user->hasRight("user", "user", "read") || $user->admin, 'rowid', 'ref', $morehtmlref); print '
'; diff --git a/htdocs/user/perms.php b/htdocs/user/perms.php index 47d68703d69..bfc234abce1 100644 --- a/htdocs/user/perms.php +++ b/htdocs/user/perms.php @@ -50,13 +50,13 @@ if (!isset($id) || empty($id)) { } // Define if user can read permissions -$canreaduser = ($user->admin || $user->rights->user->user->lire); +$canreaduser = ($user->admin || $user->hasRight("user", "user", "read")); // Define if user can modify other users and permissions -$caneditperms = ($user->admin || $user->rights->user->user->creer); +$caneditperms = ($user->admin || $user->hasRight("user", "user", "write")); // Advanced permissions if (!empty($conf->global->MAIN_USE_ADVANCED_PERMS)) { - $canreaduser = ($user->admin || ($user->rights->user->user->lire && $user->rights->user->user_advance->readperms)); - $caneditselfperms = ($user->id == $id && $user->rights->user->self_advance->writeperms); + $canreaduser = ($user->admin || ($user->hasRight("user", "user", "read") && $user->hasRight("user", "user_advance", "readperms"))); + $caneditselfperms = ($user->id == $id && $user->hasRight("user", "self_advance", "writeperms")); $caneditperms = (($caneditperms || $caneditselfperms) ? 1 : 0); } @@ -65,9 +65,9 @@ $socid = 0; if (isset($user->socid) && $user->socid > 0) { $socid = $user->socid; } -$feature2 = (($socid && $user->rights->user->self->creer) ? '' : 'user'); +$feature2 = (($socid && $user->hasRight("user", "self", "write")) ? '' : 'user'); // A user can always read its own card if not advanced perms enabled, or if he has advanced perms, except for admin -if ($user->id == $id && (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->user->self_advance->readperms) && empty($user->admin))) { +if ($user->id == $id && (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->hasRight("user", "self_advance", "readperms")) && empty($user->admin))) { accessforbidden(); } @@ -249,7 +249,7 @@ if ($result) { $linkback = ''; -if ($user->rights->user->user->lire || $user->admin) { +if ($user->hasRight("user", "user", "read") || $user->admin) { $linkback = ''.$langs->trans("BackToList").''; } @@ -257,7 +257,7 @@ $morehtmlref = 'trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; -dol_banner_tab($object, 'id', $linkback, $user->rights->user->user->lire || $user->admin, 'rowid', 'ref', $morehtmlref); +dol_banner_tab($object, 'id', $linkback, $user->hasRight("user", "user", "read") || $user->admin, 'rowid', 'ref', $morehtmlref); print '
'; From 8dcceeb127a061957be783bfc196c08b01257c64 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Fri, 29 Jul 2022 18:12:17 +0200 Subject: [PATCH 362/826] FIX setup intent stripe Klarna not supported --- htdocs/stripe/class/stripe.class.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/htdocs/stripe/class/stripe.class.php b/htdocs/stripe/class/stripe.class.php index 00d3c4a0d94..5ec149ba07f 100644 --- a/htdocs/stripe/class/stripe.class.php +++ b/htdocs/stripe/class/stripe.class.php @@ -643,9 +643,6 @@ class Stripe extends CommonObject if (!empty($conf->global->STRIPE_BANCONTACT)) { $paymentmethodtypes[] = "bancontact"; } - if (!empty($conf->global->STRIPE_KLARNA)) { - $paymentmethodtypes[] = "klarna"; - } if (!empty($conf->global->STRIPE_IDEAL)) { $paymentmethodtypes[] = "ideal"; } From 454fb6b0f5f709cec4b77b5005a16a627a891029 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Sun, 31 Jul 2022 13:10:38 +0200 Subject: [PATCH 363/826] new: Add IMAP port setting on email collector module --- htdocs/emailcollector/class/emailcollector.class.php | 5 +++-- htdocs/install/mysql/migration/16.0.0-17.0.0.sql | 1 + .../mysql/tables/llx_emailcollector_emailcollector.sql | 1 + htdocs/langs/en_US/admin.lang | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index 9a60624e9d2..11d2dcfeb46 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -115,7 +115,8 @@ class EmailCollector extends CommonObject 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'visible'=>1, 'enabled'=>1, 'position'=>30, 'notnull'=>-1, 'searchall'=>1, 'help'=>'Example: My Email collector', 'csslist'=>'tdoverflowmax150'), 'description' => array('type'=>'text', 'label'=>'Description', 'visible'=>-1, 'enabled'=>1, 'position'=>60, 'notnull'=>-1, 'csslist'=>'small'), 'host' => array('type'=>'varchar(255)', 'label'=>'EMailHost', 'visible'=>1, 'enabled'=>1, 'position'=>90, 'notnull'=>1, 'searchall'=>1, 'comment'=>"IMAP server", 'help'=>'Example: imap.gmail.com', 'csslist'=>'tdoverflow125'), - 'hostcharset' => array('type'=>'varchar(16)', 'label'=>'HostCharset', 'visible'=>-1, 'enabled'=>1, 'position'=>91, 'notnull'=>0, 'searchall'=>0, 'comment'=>"IMAP server charset", 'help'=>'Example: "UTF-8" (May be "US-ASCII" with some Office365)'), + 'port' => array('type'=>'varchar(10)', 'label'=>'EMailHostPort', 'visible'=>1, 'enabled'=>1, 'position'=>91, 'notnull'=>1, 'searchall'=>0, 'comment'=>"IMAP server port", 'help'=>'Example: 993', 'csslist'=>'tdoverflow125', 'default'=>'993'), + 'hostcharset' => array('type'=>'varchar(16)', 'label'=>'HostCharset', 'visible'=>-1, 'enabled'=>1, 'position'=>92, 'notnull'=>0, 'searchall'=>0, 'comment'=>"IMAP server charset", 'help'=>'Example: "UTF-8" (May be "US-ASCII" with some Office365)', 'default'=>'UTF-8'), 'login' => array('type'=>'varchar(128)', 'label'=>'Login', 'visible'=>1, 'enabled'=>1, 'position'=>101, 'notnull'=>-1, 'index'=>1, 'comment'=>"IMAP login", 'help'=>'Example: myaccount@gmail.com'), 'password' => array('type'=>'password', 'label'=>'Password', 'visible'=>-1, 'enabled'=>1, 'position'=>102, 'notnull'=>-1, 'comment'=>"IMAP password", 'help'=>'WithGMailYouCanCreateADedicatedPassword'), 'source_directory' => array('type'=>'varchar(255)', 'label'=>'MailboxSourceDirectory', 'visible'=>-1, 'enabled'=>1, 'position'=>103, 'notnull'=>1, 'default' => 'Inbox', 'help'=>'Example: INBOX'), @@ -746,7 +747,7 @@ class EmailCollector extends CommonObject $flags .= '/authuser='.$partofauth[0].'/user='.$partofauth[1]; } - $connectstringserver = '{'.$this->host.':993'.$flags.'}'; + $connectstringserver = '{'.$this->host.':'.$this->port.$flags.'}'; return $connectstringserver; } diff --git a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql index 24b4e20a7b7..8394ae97478 100644 --- a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql +++ b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql @@ -64,3 +64,4 @@ ALTER TABLE llx_ticket ADD COLUMN ip varchar(250); ALTER TABLE llx_societe ADD last_main_doc VARCHAR(255) NULL AFTER model_pdf; +ALTER TABLE llx_emailcollector_emailcollector ADD COLUMN port varchar(10) DEFAULT '993'; diff --git a/htdocs/install/mysql/tables/llx_emailcollector_emailcollector.sql b/htdocs/install/mysql/tables/llx_emailcollector_emailcollector.sql index b62a9b6ba7f..3580f1659b1 100644 --- a/htdocs/install/mysql/tables/llx_emailcollector_emailcollector.sql +++ b/htdocs/install/mysql/tables/llx_emailcollector_emailcollector.sql @@ -22,6 +22,7 @@ CREATE TABLE llx_emailcollector_emailcollector( label varchar(255), description text, host varchar(255), + port varchar(10) DEFAULT '993', hostcharset varchar(16) DEFAULT 'UTF-8', login varchar(128), password varchar(128), diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index c1f01ae85d9..7148e19fb48 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -2064,6 +2064,7 @@ EmailCollectors=Email collectors EmailCollectorDescription=Add a scheduled job and a setup page to scan regularly email boxes (using IMAP protocol) and record emails received into your application, at the right place and/or create some records automatically (like leads). NewEmailCollector=New Email Collector EMailHost=Host of email IMAP server +EMailHostPort=Port of email IMAP server MailboxSourceDirectory=Mailbox source directory MailboxTargetDirectory=Mailbox target directory EmailcollectorOperations=Operations to do by collector From 93031773868b62ef9b8593b5a4d15f3ae6f06d17 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 31 Jul 2022 19:12:42 +0200 Subject: [PATCH 364/826] Fix regression --- htdocs/compta/bank/releve.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/htdocs/compta/bank/releve.php b/htdocs/compta/bank/releve.php index 2dbaaa07373..c08336841e2 100644 --- a/htdocs/compta/bank/releve.php +++ b/htdocs/compta/bank/releve.php @@ -387,6 +387,10 @@ if (empty($numref)) { * Show list of record into a bank statement */ + $title = $langs->trans("FinancialAccount").' - '.$langs->trans("AccountStatements"); + $helpurl = ""; + llxHeader('', $title, $helpurl); + // Onglets $head = account_statement_prepare_head($object, $numref); print dol_get_fiche_head($head, 'statement', $langs->trans("AccountStatement"), -1, 'account'); From 1fbd4b1c2dad208b38002d6ea02c955d69f63fba Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 31 Jul 2022 20:12:22 +0200 Subject: [PATCH 365/826] Clean code --- htdocs/modulebuilder/template/myobject_list.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/htdocs/modulebuilder/template/myobject_list.php b/htdocs/modulebuilder/template/myobject_list.php index 32bf5ae3200..380eab1ab6b 100644 --- a/htdocs/modulebuilder/template/myobject_list.php +++ b/htdocs/modulebuilder/template/myobject_list.php @@ -53,7 +53,8 @@ if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) { // Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME $tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { - $i--; $j--; + $i--; + $j--; } if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; @@ -88,9 +89,6 @@ require_once __DIR__.'/class/myobject.class.php'; // Load translation files required by the page $langs->loadLangs(array("mymodule@mymodule", "other")); -$id = GETPOST('id', 'int'); -$ref = GETPOST('ref', 'alpha'); - $action = GETPOST('action', 'aZ09') ?GETPOST('action', 'aZ09') : 'view'; // The action 'add', 'create', 'edit', 'update', 'view', ... $massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists) $show_files = GETPOST('show_files', 'int'); // Show files area generated by bulk actions ? @@ -102,6 +100,9 @@ $backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page $optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print') $mode = GETPOST('mode', 'aZ'); +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); + // Load variable for pagination $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; $sortfield = GETPOST('sortfield', 'aZ09comma'); From 9286f84b47fc1b0b24f958fe65082ef2e7997b22 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 31 Jul 2022 21:06:08 +0200 Subject: [PATCH 366/826] Fix php8 --- htdocs/core/class/commonobject.class.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 2d393ab9dc3..aa85c0aa5c2 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -744,6 +744,7 @@ abstract class CommonObject public function setUpperOrLowerCase() { global $conf; + if (!empty($conf->global->MAIN_FIRST_TO_UPPER)) { $this->lastname = dol_ucwords(dol_strtolower($this->lastname)); $this->firstname = dol_ucwords(dol_strtolower($this->firstname)); @@ -759,8 +760,12 @@ abstract class CommonObject $this->address = dol_strtoupper($this->address); $this->town = dol_strtoupper($this->town); } - $this->email = dol_strtolower($this->email); - $this->personal_email = dol_strtolower($this->personal_email); + if (isset($this->email)) { + $this->email = dol_strtolower($this->email); + } + if (isset($this->personal_email)) { + $this->personal_email = dol_strtolower($this->personal_email); + } } /** From 628a368686c466acd5d770e5fa77a1c2c945f71e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 31 Jul 2022 21:25:24 +0200 Subject: [PATCH 367/826] Add column position for llx_bank --- htdocs/install/mysql/migration/16.0.0-17.0.0.sql | 2 ++ htdocs/install/mysql/tables/llx_bank.sql | 1 + 2 files changed, 3 insertions(+) diff --git a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql index 24b4e20a7b7..78f71563a45 100644 --- a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql +++ b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql @@ -64,3 +64,5 @@ ALTER TABLE llx_ticket ADD COLUMN ip varchar(250); ALTER TABLE llx_societe ADD last_main_doc VARCHAR(255) NULL AFTER model_pdf; +ALTER TABLE llx_bank ADD COLUMN position integer DEFAULT 0; + diff --git a/htdocs/install/mysql/tables/llx_bank.sql b/htdocs/install/mysql/tables/llx_bank.sql index d0a8e34790b..9a1b12d5754 100644 --- a/htdocs/install/mysql/tables/llx_bank.sql +++ b/htdocs/install/mysql/tables/llx_bank.sql @@ -37,6 +37,7 @@ create table llx_bank rappro tinyint default 0, note text, fk_bordereau integer DEFAULT 0, + position integer DEFAULT 0, banque varchar(255), -- banque pour les cheques emetteur varchar(255), -- emetteur du cheque author varchar(40), -- a supprimer apres migration From 7dfeae694f2d4b1a5f2b816ad3d57d9ec2fc7659 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 31 Jul 2022 22:22:46 +0200 Subject: [PATCH 368/826] CSS amount --- htdocs/compta/facture/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index bdc6a102147..7b7d8c61c1d 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -2083,7 +2083,7 @@ if ($resql) { // Amount HT if (!empty($arrayfields['f.total_ht']['checked'])) { - print '
\n"; + print '\n"; if (!$i) { $totalarray['nbfield']++; } From 6b5fac432fdeb53593f6b16dee4551cb5f3504b0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 1 Aug 2022 03:46:15 +0200 Subject: [PATCH 369/826] Add doc --- htdocs/core/lib/functions.lib.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index b286adae481..c3cd8922955 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -9141,6 +9141,7 @@ function printCommonFooter($zone = 'private') print "\n"; if (!empty($conf->use_javascript_ajax)) { + print "\n\n"; print ''; diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index 3886651e8d5..078d485a5c9 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -543,6 +543,7 @@ fieldset { border: 1px solid #AAAAAA !important; padding-inline-start: 2em; padding-inline-end: 2em; + min-inline-size: auto; } .legendforfieldsetstep { padding-bottom: 10px; } input#onlinepaymenturl, input#directdownloadlink { diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 6e423228df1..ca485fb0d5f 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -725,6 +725,7 @@ fieldset { border: 1px solid #AAAAAA !important; padding-inline-start: 2em; padding-inline-end: 2em; + min-inline-size: auto; } .legendforfieldsetstep { padding-bottom: 10px; } input#onlinepaymenturl, input#directdownloadlink { From 064c95baef12a3ac5b4b353b503c84d2b467b738 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 3 Aug 2022 18:18:17 +0200 Subject: [PATCH 422/826] CSS --- htdocs/admin/tools/dolibarr_export.php | 12 +++++++----- htdocs/theme/eldy/global.inc.php | 1 + htdocs/theme/md/style.css.php | 1 + 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/htdocs/admin/tools/dolibarr_export.php b/htdocs/admin/tools/dolibarr_export.php index 1a68b17c3e0..588cc5ed866 100644 --- a/htdocs/admin/tools/dolibarr_export.php +++ b/htdocs/admin/tools/dolibarr_export.php @@ -168,9 +168,10 @@ print ''; print ''; -print ' + + + + + + + + + + + + + diff --git a/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/fonts/glyphicons-halflings-regular.eot b/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/fonts/glyphicons-halflings-regular.eot new file mode 100644 index 0000000000000000000000000000000000000000..b93a4953fff68df523aa7656497ee339d6026d64 GIT binary patch literal 20127 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/fonts/glyphicons-halflings-regular.ttf b/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/fonts/glyphicons-halflings-regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..1413fc609ab6f21774de0cb7e01360095584f65b GIT binary patch literal 45404 zcmd?Sd0-pWwLh*qi$?oCk~i6sWlOeWJC3|4juU5JNSu9hSVACzERcmjLV&P^utNzg zIE4Kr1=5g!SxTX#Ern9_%4&01rlrW`Z!56xXTGQR4C z3vR~wXq>NDx$c~e?;ia3YjJ*$!C>69a?2$lLyhpI!CFfJsP=|`8@K0|bbMpWwVUEygg0=0x_)HeHpGSJagJNLA3c!$EuOV>j$wi! zbo{vZ(s8tl>@!?}dmNHXo)ABy7ohD7_1G-P@SdJWT8*oeyBVYVW9*vn}&VI4q++W;Z+uz=QTK}^C75!`aFYCX# zf7fC2;o`%!huaTNJAB&VWrx=szU=VLhwnbT`vc<#<`4WI6n_x@AofA~2d90o?1L3w z9!I|#P*NQ)$#9aASijuw>JRld^-t)Zhmy|i-`Iam|IWkguaMR%lhi4p~cX-9& zjfbx}yz}s`4-6>D^+6FzihR)Y!GsUy=_MWi_v7y#KmYi-{iZ+s@ekkq!@Wxz!~BQwiI&ti z>hC&iBe2m(dpNVvSbZe3DVgl(dxHt-k@{xv;&`^c8GJY%&^LpM;}7)B;5Qg5J^E${ z7z~k8eWOucjX6)7q1a%EVtmnND8cclz8R1=X4W@D8IDeUGXxEWe&p>Z*voO0u_2!! zj3dT(Ki+4E;uykKi*yr?w6!BW2FD55PD6SMj`OfBLwXL5EA-9KjpMo4*5Eqs^>4&> z8PezAcn!9jk-h-Oo!E9EjX8W6@EkTHeI<@AY{f|5fMW<-Ez-z)xCvW3()Z#x0oydB zzm4MzY^NdpIF9qMp-jU;99LjlgY@@s+=z`}_%V*xV7nRV*Kwrx-i`FzI0BZ#yOI8# z!SDeNA5b6u9!Imj89v0(g$;dT_y|Yz!3V`i{{_dez8U@##|X9A};s^7vEd!3AcdyVlhVk$v?$O442KIM1-wX^R{U7`JW&lPr3N(%kXfXT_`7w^? z=#ntx`tTF|N$UT?pELvw7T*2;=Q-x@KmDUIbLyXZ>f5=y7z1DT<7>Bp0k;eItHF?1 zErzhlD2B$Tm|^7DrxnTYm-tgg`Mt4Eivp5{r$o9e)8(fXBO4g|G^6Xy?y$SM*&V52 z6SR*%`%DZC^w(gOWQL?6DRoI*hBNT)xW9sxvmi@!vI^!mI$3kvAMmR_q#SGn3zRb_ zGe$=;Tv3dXN~9XuIHow*NEU4y&u}FcZEZoSlXb9IBOA}!@J3uovp}yerhPMaiI8|SDhvWVr z^BE&yx6e3&RYqIg;mYVZ*3#A-cDJ;#ms4txEmwm@g^s`BB}KmSr7K+ruIoKs=s|gOXP|2 zb1!)87h9?(+1^QRWb(Vo8+@G=o24gyuzF3ytfsKjTHZJ}o{YznGcTDm!s)DRnmOX} z3pPL4wExoN$kyc2>#J`k+<67sy-VsfbQ-1u+HkyFR?9G`9r6g4*8!(!c65Be-5hUg zZHY$M0k(Yd+DT1*8)G(q)1&tDl=g9H7!bZTOvEEFnBOk_K=DXF(d4JOaH zI}*A3jGmy{gR>s}EQzyJa_q_?TYPNXRU1O;fcV_&TQZhd{@*8Tgpraf~nT0BYktu*n{a~ub^UUqQPyr~yBY{k2O zgV)honv{B_CqY|*S~3up%Wn%7i*_>Lu|%5~j)}rQLT1ZN?5%QN`LTJ}vA!EE=1`So z!$$Mv?6T)xk)H8JTrZ~m)oNXxS}pwPd#);<*>zWsYoL6iK!gRSBB{JCgB28C#E{T? z5VOCMW^;h~eMke(w6vLlKvm!!TyIf;k*RtK)|Q>_@nY#J%=h%aVb)?Ni_By)XNxY)E3`|}_u}fn+Kp^3p4RbhFUBRtGsDyx9Eolg77iWN z2iH-}CiM!pfYDIn7;i#Ui1KG01{3D<{e}uWTdlX4Vr*nsb^>l0%{O?0L9tP|KGw8w z+T5F}md>3qDZQ_IVkQ|BzuN08uN?SsVt$~wcHO4pB9~ykFTJO3g<4X({-Tm1w{Ufo zI03<6KK`ZjqVyQ(>{_aMxu7Zm^ck&~)Q84MOsQ-XS~{6j>0lTl@lMtfWjj;PT{nlZ zIn0YL?kK7CYJa)(8?unZ)j8L(O}%$5S#lTcq{rr5_gqqtZ@*0Yw4}OdjL*kBv+>+@ z&*24U=y{Nl58qJyW1vTwqsvs=VRAzojm&V zEn6=WzdL1y+^}%Vg!ap>x%%nFi=V#wn# zUuheBR@*KS)5Mn0`f=3fMwR|#-rPMQJg(fW*5e`7xO&^UUH{L(U8D$JtI!ac!g(Ze89<`UiO@L+)^D zjPk2_Ie0p~4|LiI?-+pHXuRaZKG$%zVT0jn!yTvvM^jlcp`|VSHRt-G@_&~<4&qW@ z?b#zIN)G(}L|60jer*P7#KCu*Af;{mpWWvYK$@Squ|n-Vtfgr@ZOmR5Xpl;0q~VILmjk$$mgp+`<2jP z@+nW5Oap%fF4nFwnVwR7rpFaOdmnfB$-rkO6T3#w^|*rft~acgCP|ZkgA6PHD#Of| zY%E!3tXtsWS`udLsE7cSE8g@p$ceu*tI71V31uA7jwmXUCT7+Cu3uv|W>ZwD{&O4Nfjjvl43N#A$|FWxId! z%=X!HSiQ-#4nS&smww~iXRn<-`&zc)nR~js?|Ei-cei$^$KsqtxNDZvl1oavXK#Pz zT&%Wln^Y5M95w=vJxj0a-ko_iQt(LTX_5x#*QfQLtPil;kkR|kz}`*xHiLWr35ajx zHRL-QQv$|PK-$ges|NHw8k6v?&d;{A$*q15hz9{}-`e6ys1EQ1oNNKDFGQ0xA!x^( zkG*-ueZT(GukSnK&Bs=4+w|(kuWs5V_2#3`!;f}q?>xU5IgoMl^DNf+Xd<=sl2XvkqviJ>d?+G@Z5nxxd5Sqd$*ENUB_mb8Z+7CyyU zA6mDQ&e+S~w49csl*UePzY;^K)Fbs^%?7;+hFc(xz#mWoek4_&QvmT7Fe)*{h-9R4 zqyXuN5{)HdQ6yVi#tRUO#M%;pL>rQxN~6yoZ)*{{!?jU)RD*oOxDoTjVh6iNmhWNC zB5_{R=o{qvxEvi(khbRS`FOXmOO|&Dj$&~>*oo)bZz%lPhEA@ zQ;;w5eu5^%i;)w?T&*=UaK?*|U3~{0tC`rvfEsRPgR~16;~{_S2&=E{fE2=c>{+y} zx1*NTv-*zO^px5TA|B```#NetKg`19O!BK*-#~wDM@KEllk^nfQ2quy25G%)l72<> zzL$^{DDM#jKt?<>m;!?E2p0l12`j+QJjr{Lx*47Nq(v6i3M&*P{jkZB{xR?NOSPN% zU>I+~d_ny=pX??qjF*E78>}Mgts@_yn`)C`wN-He_!OyE+gRI?-a>Om>Vh~3OX5+& z6MX*d1`SkdXwvb7KH&=31RCC|&H!aA1g_=ZY0hP)-Wm6?A7SG0*|$mC7N^SSBh@MG z9?V0tv_sE>X==yV{)^LsygK2=$Mo_0N!JCOU?r}rmWdHD%$h~~G3;bt`lH& zAuOOZ=G1Mih**0>lB5x+r)X^8mz!0K{SScj4|a=s^VhUEp#2M=^#WRqe?T&H9GnWa zYOq{+gBn9Q0e0*Zu>C(BAX=I-Af9wIFhCW6_>TsIH$d>|{fIrs&BX?2G>GvFc=<8` zVJ`#^knMU~65dWGgXcht`Kb>{V2oo%<{NK|iH+R^|Gx%q+env#Js*(EBT3V0=w4F@W+oLFsA)l7Qy8mx_;6Vrk;F2RjKFvmeq} zro&>@b^(?f))OoQ#^#s)tRL>b0gzhRYRG}EU%wr9GjQ#~Rpo|RSkeik^p9x2+=rUr}vfnQoeFAlv=oX%YqbLpvyvcZ3l$B z5bo;hDd(fjT;9o7g9xUg3|#?wU2#BJ0G&W1#wn?mfNR{O7bq747tc~mM%m%t+7YN}^tMa24O4@w<|$lk@pGx!;%pKiq&mZB z?3h<&w>un8r?Xua6(@Txu~Za9tI@|C4#!dmHMzDF_-_~Jolztm=e)@vG11bZQAs!tFvd9{C;oxC7VfWq377Y(LR^X_TyX9bn$)I765l=rJ%9uXcjggX*r?u zk|0!db_*1$&i8>d&G3C}A`{Fun_1J;Vx0gk7P_}8KBZDowr*8$@X?W6v^LYmNWI)lN92yQ;tDpN zOUdS-W4JZUjwF-X#w0r;97;i(l}ZZT$DRd4u#?pf^e2yaFo zbm>I@5}#8FjsmigM8w_f#m4fEP~r~_?OWB%SGWcn$ThnJ@Y`ZI-O&Qs#Y14To( zWAl>9Gw7#}eT(!c%D0m>5D8**a@h;sLW=6_AsT5v1Sd_T-C4pgu_kvc?7+X&n_fct znkHy(_LExh=N%o3I-q#f$F4QJpy>jZBW zRF7?EhqTGk)w&Koi}QQY3sVh?@e-Z3C9)P!(hMhxmXLC zF_+ZSTQU`Gqx@o(~B$dbr zHlEUKoK&`2gl>zKXlEi8w6}`X3kh3as1~sX5@^`X_nYl}hlbpeeVlj#2sv)CIMe%b zBs7f|37f8qq}gA~Is9gj&=te^wN8ma?;vF)7gce;&sZ64!7LqpR!fy)?4cEZposQ8 zf;rZF7Q>YMF1~eQ|Z*!5j0DuA=`~VG$Gg6B?Om1 z6fM@`Ck-K*k(eJ)Kvysb8sccsFf@7~3vfnC=<$q+VNv)FyVh6ZsWw}*vs>%k3$)9| zR9ek-@pA23qswe1io)(Vz!vS1o*XEN*LhVYOq#T`;rDkgt86T@O`23xW~;W_#ZS|x zvwx-XMb7_!hIte-#JNpFxskMMpo2OYhHRr0Yn8d^(jh3-+!CNs0K2B!1dL$9UuAD= zQ%7Ae(Y@}%Cd~!`h|wAdm$2WoZ(iA1(a_-1?znZ%8h72o&Mm*4x8Ta<4++;Yr6|}u zW8$p&izhdqF=m8$)HyS2J6cKyo;Yvb>DTfx4`4R{ zPSODe9E|uflE<`xTO=r>u~u=NuyB&H!(2a8vwh!jP!yfE3N>IiO1jI>7e&3rR#RO3_}G23W?gwDHgSgekzQ^PU&G5z&}V5GO? zfg#*72*$DP1T8i`S7=P;bQ8lYF9_@8^C(|;9v8ZaK2GnWz4$Th2a0$)XTiaxNWfdq z;yNi9veH!j)ba$9pke8`y2^63BP zIyYKj^7;2don3se!P&%I2jzFf|LA&tQ=NDs{r9fIi-F{-yiG-}@2`VR^-LIFN8BC4 z&?*IvLiGHH5>NY(Z^CL_A;yISNdq58}=u~9!Ia7 zm7MkDiK~lsfLpvmPMo!0$keA$`%Tm`>Fx9JpG^EfEb(;}%5}B4Dw!O3BCkf$$W-dF z$BupUPgLpHvr<<+QcNX*w@+Rz&VQz)Uh!j4|DYeKm5IC05T$KqVV3Y|MSXom+Jn8c zgUEaFW1McGi^44xoG*b0JWE4T`vka7qTo#dcS4RauUpE{O!ZQ?r=-MlY#;VBzhHGU zS@kCaZ*H73XX6~HtHd*4qr2h}Pf0Re@!WOyvres_9l2!AhPiV$@O2sX>$21)-3i+_ z*sHO4Ika^!&2utZ@5%VbpH(m2wE3qOPn-I5Tbnt&yn9{k*eMr3^u6zG-~PSr(w$p> zw)x^a*8Ru$PE+{&)%VQUvAKKiWiwvc{`|GqK2K|ZMy^Tv3g|zENL86z7i<c zW`W>zV1u}X%P;Ajn+>A)2iXZbJ5YB_r>K-h5g^N=LkN^h0Y6dPFfSBh(L`G$D%7c` z&0RXDv$}c7#w*7!x^LUes_|V*=bd&aP+KFi((tG*gakSR+FA26%{QJdB5G1F=UuU&koU*^zQA=cEN9}Vd?OEh| zgzbFf1?@LlPkcXH$;YZe`WEJ3si6&R2MRb}LYK&zK9WRD=kY-JMPUurX-t4(Wy{%` zZ@0WM2+IqPa9D(^*+MXw2NWwSX-_WdF0nMWpEhAyotIgqu5Y$wA=zfuXJ0Y2lL3#ji26-P3Z?-&0^KBc*`T$+8+cqp`%g0WB zTH9L)FZ&t073H4?t=(U6{8B+uRW_J_n*vW|p`DugT^3xe8Tomh^d}0k^G7$3wLgP& zn)vTWiMA&=bR8lX9H=uh4G04R6>C&Zjnx_f@MMY!6HK5v$T%vaFm;E8q=`w2Y}ucJ zkz~dKGqv9$E80NTtnx|Rf_)|3wxpnY6nh3U9<)fv2-vhQ6v=WhKO@~@X57N-`7Ppc zF;I7)eL?RN23FmGh0s;Z#+p)}-TgTJE%&>{W+}C`^-sy{gTm<$>rR z-X7F%MB9Sf%6o7A%ZHReD4R;imU6<9h81{%avv}hqugeaf=~^3A=x(Om6Lku-Pn9i zC;LP%Q7Xw*0`Kg1)X~nAsUfdV%HWrpr8dZRpd-#%)c#Fu^mqo|^b{9Mam`^Zw_@j@ zR&ZdBr3?@<@%4Z-%LT&RLgDUFs4a(CTah_5x4X`xDRugi#vI-cw*^{ncwMtA4NKjByYBza)Y$hozZCpuxL{IP&=tw6ZO52WY3|iwGf&IJCn+u(>icK zZB1~bWXCmwAUz|^<&ysd#*!DSp8}DLNbl5lRFat4NkvItxy;9tpp9~|@ z;JctShv^Iq4(z+y7^j&I?GCdKMVg&jCwtCkc4*@O7HY*veGDBtAIn*JgD$QftP}8= zxFAdF=(S>Ra6(4slk#h%b?EOU-96TIX$Jbfl*_7IY-|R%H zF8u|~hYS-YwWt5+^!uGcnKL~jM;)ObZ#q68ZkA?}CzV-%6_vPIdzh_wHT_$mM%vws9lxUj;E@#1UX?WO2R^41(X!nk$+2oJGr!sgcbn1f^yl1 z#pbPB&Bf;1&2+?};Jg5qgD1{4_|%X#s48rOLE!vx3@ktstyBsDQWwDz4GYlcgu$UJ zp|z_32yN72T*oT$SF8<}>e;FN^X&vWNCz>b2W0rwK#<1#kbV)Cf`vN-F$&knLo5T& z8!sO-*^x4=kJ$L&*h%rQ@49l?7_9IG99~xJDDil00<${~D&;kiqRQqeW5*22A`8I2 z(^@`qZoF7_`CO_e;8#qF!&g>UY;wD5MxWU>azoo=E{kW(GU#pbOi%XAn%?W{b>-bTt&2?G=E&BnK9m0zs{qr$*&g8afR_x`B~o zd#dxPpaap;I=>1j8=9Oj)i}s@V}oXhP*{R|@DAQXzQJekJnmuQ;vL90_)H_nD1g6e zS1H#dzg)U&6$fz0g%|jxDdz|FQN{KJ&Yx0vfuzAFewJjv`pdMRpY-wU`-Y6WQnJ(@ zGVb!-8DRJZvHnRFiR3PG3Tu^nCn(CcZHh7hQvyd7i6Q3&ot86XI{jo%WZqCPcTR0< zMRg$ZE=PQx66ovJDvI_JChN~k@L^Pyxv#?X^<)-TS5gk`M~d<~j%!UOWG;ZMi1af< z+86U0=sm!qAVJAIqqU`Qs1uJhQJA&n@9F1PUrYuW!-~IT>l$I!#5dBaiAK}RUufjg{$#GdQBkxF1=KU2E@N=i^;xgG2Y4|{H>s` z$t`k8c-8`fS7Yfb1FM#)vPKVE4Uf(Pk&%HLe z%^4L>@Z^9Z{ZOX<^e)~adVRkKJDanJ6VBC_m@6qUq_WF@Epw>AYqf%r6qDzQ~AEJ!jtUvLp^CcqZ^G-;Kz3T;O4WG45Z zFhrluCxlY`M+OKr2SeI697btH7Kj`O>A!+2DTEQ=48cR>Gg2^5uqp(+y5Sl09MRl* zp|28!v*wvMd_~e2DdKDMMQ|({HMn3D%%ATEecGG8V9>`JeL)T0KG}=}6K8NiSN5W< z79-ZdYWRUb`T}(b{RjN8>?M~opnSRl$$^gT`B27kMym5LNHu-k;A;VF8R(HtDYJHS zU7;L{a@`>jd0svOYKbwzq+pWSC(C~SPgG~nWR3pBA8@OICK$Cy#U`kS$I;?|^-SBC zBFkoO8Z^%8Fc-@X!KebF2Ob3%`8zlVHj6H;^(m7J35(_bS;cZPd}TY~qixY{MhykQ zV&7u7s%E=?i`}Ax-7dB0ih47w*7!@GBt<*7ImM|_mYS|9_K7CH+i}?*#o~a&tF-?C zlynEu1DmiAbGurEX2Flfy$wEVk7AU;`k#=IQE*6DMWafTL|9-vT0qs{A3mmZGzOyN zcM9#Rgo7WgB_ujU+?Q@Ql?V-!E=jbypS+*chI&zA+C_3_@aJal}!Q54?qsL0In({Ly zjH;e+_SK8yi0NQB%TO+Dl77jp#2pMGtwsgaC>K!)NimXG3;m7y`W+&<(ZaV>N*K$j zLL~I+6ouPk6_(iO>61cIsinx`5}DcKSaHjYkkMuDoVl>mKO<4$F<>YJ5J9A2Vl}#BP7+u~L8C6~D zsk`pZ$9Bz3teQS1Wb|8&c2SZ;qo<#F&gS;j`!~!ADr(jJXMtcDJ9cVi>&p3~{bqaP zgo%s8i+8V{UrYTc9)HiUR_c?cfx{Yan2#%PqJ{%?Wux4J;T$#cumM0{Es3@$>}DJg zqe*c8##t;X(4$?A`ve)e@YU3d2Balcivot{1(ahlE5qg@S-h(mPNH&`pBX$_~HdG48~)$x5p z{>ghzqqn_t8~pY<5?-To>cy^6o~mifr;KWvx_oMtXOw$$d6jddXG)V@a#lL4o%N@A zNJlQAz6R8{7jax-kQsH6JU_u*En%k^NHlvBB!$JAK!cYmS)HkLAkm0*9G3!vwMIWv zo#)+EamIJHEUV|$d|<)2iJ`lqBQLx;HgD}c3mRu{iK23C>G{0Mp1K)bt6OU?xC4!_ zZLqpFzeu&+>O1F>%g-%U^~yRg(-wSp@vmD-PT#bCWy!%&H;qT7rfuRCEgw67V!Qob z&tvPU@*4*$YF#2_>M0(75QxqrJr3Tvh~iDeFhxl=MzV@(psx%G8|I{~9;tv#BBE`l z3)_98eZqFNwEF1h)uqhBmT~mSmT8k$7vSHdR97K~kM)P9PuZdS;|Op4A?O<*%!?h` zn`}r_j%xvffs46x2hCWuo0BfIQWCw9aKkH==#B(TJ%p}p-RuIVzsRlaPL_Co{&R0h zQrqn=g1PGjQg3&sc2IlKG0Io#v%@p>tFwF)RG0ahYs@Zng6}M*d}Xua)+h&?$`%rb z;>M=iMh5eIHuJ5c$aC`y@CYjbFsJnSPH&}LQz4}za9YjDuao>Z^EdL@%saRm&LGQWXs*;FzwN#pH&j~SLhDZ+QzhplV_ij(NyMl z;v|}amvxRddO81LJFa~2QFUs z+Lk zZck)}9uK^buJNMo4G(rSdX{57(7&n=Q6$QZ@lIO9#<3pA2ceDpO_340B*pHlh_y{>i&c1?vdpN1j>3UN-;;Yq?P+V5oY`4Z(|P8SwWq<)n`W@AwcQ?E9 zd5j8>FT^m=MHEWfN9jS}UHHsU`&SScib$qd0i=ky0>4dz5ADy70AeIuSzw#gHhQ_c zOp1!v6qU)@8MY+ zMNIID?(CysRc2uZQ$l*QZVY)$X?@4$VT^>djbugLQJdm^P>?51#lXBkdXglYm|4{L zL%Sr?2f`J+xrcN@=0tiJt(<-=+v>tHy{XaGj7^cA6felUn_KPa?V4ebfq7~4i~GKE zpm)e@1=E;PP%?`vK6KVPKXjUXyLS1^NbnQ&?z>epHCd+J$ktT1G&L~T)nQeExe;0Z zlei}<_ni ztFo}j7nBl$)s_3odmdafVieFxc)m!wM+U`2u%yhJ90giFcU1`dR6BBTKc2cQ*d zm-{?M&%(={xYHy?VCx!ogr|4g5;V{2q(L?QzJGsirn~kWHU`l`rHiIrc-Nan!hR7zaLsPr4uR zG{En&gaRK&B@lyWV@yfFpD_^&z>84~_0Rd!v(Nr%PJhFF_ci3D#ixf|(r@$igZiWw za*qbXIJ_Hm4)TaQ=zW^g)FC6uvyO~Hg-#Z5Vsrybz6uOTF>Rq1($JS`imyNB7myWWpxYL(t7`H8*voI3Qz6mvm z$JxtArLJ(1wlCO_te?L{>8YPzQ})xJlvc5wv8p7Z=HviPYB#^#_vGO#*`<0r%MR#u zN_mV4vaBb2RwtoOYCw)X^>r{2a0kK|WyEYoBjGxcObFl&P*??)WEWKU*V~zG5o=s@ z;rc~uuQQf9wf)MYWsWgPR!wKGt6q;^8!cD_vxrG8GMoFGOVV=(J3w6Xk;}i)9(7*U zwR4VkP_5Zx7wqn8%M8uDj4f1aP+vh1Wue&ry@h|wuN(D2W;v6b1^ z`)7XBZ385zg;}&Pt@?dunQ=RduGRJn^9HLU&HaeUE_cA1{+oSIjmj3z+1YiOGiu-H zf8u-oVnG%KfhB8H?cg%@#V5n+L$MO2F4>XoBjBeX>css^h}Omu#)ExTfUE^07KOQS znMfQY2wz?!7!{*C^)aZ^UhMZf=TJNDv8VrrW;JJ9`=|L0`w9DE8MS>+o{f#{7}B4P z{I34>342vLsP}o=ny1eZkEabr@niT5J2AhByUz&i3Ck0H*H`LRHz;>3C_ru!X+EhJ z6(+(lI#4c`2{`q0o9aZhI|jRjBZOV~IA_km7ItNtUa(Wsr*Hmb;b4=;R(gF@GmsRI`pF+0tmq0zy~wnoJD(LSEwHjTOt4xb0XB-+ z&4RO{Snw4G%gS9w#uSUK$Zbb#=jxEl;}6&!b-rSY$0M4pftat-$Q)*y!bpx)R%P>8 zrB&`YEX2%+s#lFCIV;cUFUTIR$Gn2%F(3yLeiG8eG8&)+cpBlzx4)sK?>uIlH+$?2 z9q9wk5zY-xr_fzFSGxYp^KSY0s%1BhsI>ai2VAc8&JiwQ>3RRk?ITx!t~r45qsMnj zkX4bl06ojFCMq<9l*4NHMAtIxDJOX)H=K*$NkkNG<^nl46 zHWH1GXb?Og1f0S+8-((5yaeegCT62&4N*pNQY;%asz9r9Lfr;@Bl${1@a4QAvMLbV6JDp>8SO^q1)#(o%k!QiRSd0eTmzC< zNIFWY5?)+JTl1Roi=nS4%@5iF+%XztpR^BSuM~DX9q`;Mv=+$M+GgE$_>o+~$#?*y zAcD4nd~L~EsAjXV-+li6Lua4;(EFdi|M2qV53`^4|7gR8AJI;0Xb6QGLaYl1zr&eu zH_vFUt+Ouf4SXA~ z&Hh8K@ms^`(hJfdicecj>J^Aqd00^ccqN!-f-!=N7C1?`4J+`_f^nV!B3Q^|fuU)7 z1NDNT04hd4QqE+qBP+>ZE7{v;n3OGN`->|lHjNL5w40pePJ?^Y6bFk@^k%^5CXZ<+4qbOplxpe)l7c6m%o-l1oWmCx%c6@rx85hi(F=v(2 zJ$jN>?yPgU#DnbDXPkHLeQwED5)W5sH#-eS z%#^4dxiVs{+q(Yd^ShMN3GH)!h!@W&N`$L!SbElXCuvnqh{U7lcCvHI#{ZjwnKvu~ zAeo7Pqot+Ohm{8|RJsTr3J4GjCy5UTo_u_~p)MS&Z5UrUc|+;Mc(YS+ju|m3Y_Dvt zonVtpBWlM718YwaN3a3wUNqX;7TqvAFnVUoD5v5WTh~}r)KoLUDw%8Rrqso~bJqd> z_T!&Rmr6ebpV^4|knJZ%qmzL;OvG3~A*loGY7?YS%hS{2R0%NQ@fRoEK52Aiu%gj( z_7~a}eQUh8PnyI^J!>pxB(x7FeINHHC4zLDT`&C*XUpp@s0_B^!k5Uu)^j_uuu^T> z8WW!QK0SgwFHTA%M!L`bl3hHjPp)|wL5Var_*A1-H8LV?uY5&ou{hRjj>#X@rxV>5%-9hbP+v?$4}3EfoRH;l_wSiz{&1<+`Y5%o%q~4rdpRF0jOsCoLnWY5x?V)0ga>CDo`NpqS) z@x`mh1QGkx;f)p-n^*g5M^zRTHz%b2IkLBY{F+HsjrFC9_H(=9Z5W&Eymh~A_FUJ} znhTc9KG((OnjFO=+q>JQZJbeOoUM77M{)$)qQMcxK9f;=L;IOv_J>*~w^YOW744QZ zoG;!b9VD3ww}OX<8sZ0F##8hvfDP{hpa3HjaLsKbLJ8 z0WpY2E!w?&cWi7&N%bOMZD~o7QT*$xCRJ@{t31~qx~+0yYrLXubXh2{_L699Nl_pn z6)9eu+uUTUdjHXYs#pX^L)AIb!FjjNsTp7C399w&B{Q4q%yKfmy}T2uQdU|1EpNcY zDk~(h#AdxybjfzB+mg6rdU9mDZ^V>|U13Dl$Gj+pAL}lR2a1u!SJXU_YqP9N{ose4 zk+$v}BIHX60WSGVWv;S%zvHOWdDP(-ceo(<8`y@Goy%4wDu>57QZNJc)f>Ls+}9h7 z^N=#3q3|l?aG8K#HwiW2^PJu{v|x5;awYfahC?>_af3$LmMc4%N~JwVlRZa4c+eW2 zE!zosAjOv&UeCeu;Bn5OQUC=jtZjF;NDk9$fGbxf3d29SUBekX1!a$Vmq_VK*MHQ4)eB!dQrHH)LVYNF%-t8!d`@!cb z2CsKs3|!}T^7fSZm?0dJ^JE`ZGxA&a!jC<>6_y67On0M)hd$m*RAzo_qM?aeqkm`* zXpDYcc_>TFZYaC3JV>{>mp(5H^efu!Waa7hGTAts29jjuVd1vI*fEeB?A&uG<8dLZ z(j6;-%vJ7R0U9}XkH)1g>&uptXPHBEA*7PSO2TZ+dbhVxspNW~ZQT3fApz}2 z_@0-lZODcd>dLrYp!mHn4k>>7kibI!Em+Vh*;z}l?0qro=aJt68joCr5Jo(Vk<@i) z5BCKb4p6Gdr9=JSf(2Mgr=_6}%4?SwhV+JZj3Ox^_^OrQk$B^v?eNz}d^xRaz&~ zKVnlLnK#8^y=If2f1zmb~^5lPLe?%l}>?~wN4IN((2~U{e9fKhLMtYFj)I$(y zgnKv?R+ZpxA$f)Q2l=aqE6EPTK=i0sY&MDFJp!vQayyvzh4wee<}kybNthRlX>SHh z7S}9he^EBOqzBCww^duHu!u+dnf9veG{HjW!}aT7aJqzze9K6-Z~8pZAgdm1n~aDs z8_s7?WXMPJ3EPJHi}NL&d;lZP8hDhAXf5Hd!x|^kEHu`6QukXrVdLnq5zbI~oPo?7 z2Cbu8U?$K!Z4_yNM1a(bL!GRe!@{Qom+DxjrJ!B99qu5b*Ma%^&-=6UEbC+S2zX&= zQ!%bgJTvmv^2}hhvNQg!l=kbapAgM^hruE3k@jTxsG(B6d=4thBC*4tzVpCYXFc$a zeqgVB^zua)y-YjpiibCCdU%txXYeNFnXcbNj*D?~)5AGjL+!!ij_4{5EWKGav0^={~M^q}baAFOPzxfUM>`KPf|G z&hsaR*7(M6KzTj8Z?;45zX@L#xU{4n$9Q_<-ac(y4g~S|Hyp^-<*d8+P4NHe?~vfm z@y309=`lGdvN8*jw-CL<;o#DKc-%lb0i9a3%{v&2X($|Qxv(_*()&=xD=5oBg=$B0 zU?41h9)JKvP0yR{KsHoC>&`(Uz>?_`tlLjw1&5tPH3FoB%}j;yffm$$s$C=RHi`I3*m@%CPqWnP@B~%DEe;7ZT{9!IMTo1hT3Q347HJ&!)BM2 z3~aClf>aFh0_9||4G}(Npu`9xYY1*SD|M~9!CCFn{-J$u2&Dg*=5$_nozpoD2nxqq zB!--eA8UWZlcEDp4r#vhZ6|vq^9sFvRnA9HpHch5Mq4*T)oGbruj!U8Lx_G%Lby}o zTQ-_4A7b)5A42vA0U}hUJq6&wQ0J%$`w#ph!EGmW96)@{AUx>q6E>-r^Emk!iCR+X zdIaNH`$}7%57D1FyTccs3}Aq0<0Ei{`=S7*>pyg=Kv3nrqblqZcpsCWSQl^uMSsdj zYzh73?6th$c~CI0>%5@!Ej`o)Xm38u0fp9=HE@Sa6l2oX9^^4|Aq%GA z3(AbFR9gA_2T2i%Ck5V2Q2WW-(a&(j#@l6wE4Z`xg#S za#-UWUpU2U!TmIo`CN0JwG^>{+V#9;zvx;ztc$}@NlcyJr?q(Y`UdW6qhq!aWyB5xV1#Jb{I-ghFNO0 zFU~+QgPs{FY1AbiU&S$QSix>*rqYVma<-~s%ALhFyVhAYepId1 zs!gOB&weC18yhE-v6ltKZMV|>JwTX+X)Y_EI(Ff^3$WTD|Ea-1HlP;6L~&40Q&5{0 z$e$2KhUgH8ucMJxJV#M%cs!d~#hR^nRwk|uuCSf6irJCkSyI<%CR==tftx6d%;?ef zYIcjZrP@APzbtOeUe>m-TW}c-ugh+U*RbL1eIY{?>@8aW9bb1NGRy@MTse@>= za%;5=U}X%K2tKTYe9gjMcBvX%qrC&uZ`d(t)g)X8snf?vBe3H%dG=bl^rv8Z@YN$gd9yveHY0@Wt0$s zh^7jCp(q+6XDoekb;=%y=Wr8%6;z0ANH5dDR_VudDG|&_lYykJaiR+(y{zpR=qL3|2e${8 z2V;?jgHj7}Kl(d8C9xWRjhpf_)KOXl+@c4wrHy zL3#9U(`=N59og2KqVh>nK~g9>fX*PI0`>i;;b6KF|8zg+k2hViCt}4dfMdvb1NJ-Rfa7vL2;lPK{Lq*u`JT>S zoM_bZ_?UY6oV6Ja14X^;LqJPl+w?vf*C!nGK;uU^0GRN|UeFF@;H(Hgp8x^|;ygh? zIZx3DuO(lD01ksanR@Mn#lti=p28RTNYY6yK={RMFiVd~k8!@a&^jicZ&rxD3CCI! zVb=fI?;c#f{K4Pp2lnb8iF2mig)|6JEmU86Y%l}m>(VnI*Bj`a6qk8QL&~PFDxI8b z2mcsQBe9$q`Q$LfG2wdvK`M1}7?SwLAV&)nO;kAk`SAz%x9CDVHVbUd$O(*aI@D|s zLxJW7W(QeGpQY<$dSD6U$ja(;Hb3{Zx@)*fIQaW{8<$KJ&fS0caI2Py^clOq9@Irt z7th7F?7W`j{&UmM==Lo~T&^R7A?G=K_e-zfTX|)i`pLitlNE(~tq*}sS1x2}Jlul6 z5+r#4SpQu8h{ntIv#qCVH`uG~+I8l+7ZG&d`Dm!+(rZQDV*1LS^WfH%-!5aTAxry~ z4xl&rot5ct{xQ$w$MtVTUi6tBFSJWq2Rj@?HAX1H$eL*fk{Hq;E`x|hghRkipYNyt zKCO=*KSziiVk|+)qQCGrTYH9X!Z0$k{Nde~0Wl`P{}ca%nv<6fnYw^~9dYxTnTZB&&962jX0DM&wy&8fdxX8xeHSe=UU&Mq zRTaUKnQO|A>E#|PUo+F=Q@dMdt`P*6e92za(TH{5C*2I2S~p?~O@hYiT>1(n^Lqqn zqewq3ctAA%0E)r53*P-a8Ak32mGtUG`L^WVcm`QovX`ecB4E9X60wrA(6NZ7z~*_DV_e z8$I*eZ8m=WtChE{#QzeyHpZ%7GwFHlwo2*tAuloI-j2exx3#x7EL^&D;Re|Kj-XT- zt908^soV2`7s+Hha!d^#J+B)0-`{qIF_x=B811SZlbUe%kvPce^xu7?LY|C z@f1gRPha1jq|=f}Se)}v-7MWH9)YAs*FJ&v3ZT9TSi?e#jarin0tjPNmxZNU_JFJG z+tZi!q)JP|4pQ)?l8$hRaPeoKf!3>MM-bp06RodLa*wD=g3)@pYJ^*YrwSIO!SaZo zDTb!G9d!hb%Y0QdYxqNSCT5o0I!GDD$Z@N!8J3eI@@0AiJmD7brkvF!pJGg_AiJ1I zO^^cKe`w$DsO|1#^_|`6XTfw6E3SJ(agG*G9qj?JiqFSL|6tSD6vUwK?Cwr~gg)Do zp@$D~7~66-=p4`!!UzJDKAymb!!R(}%O?Uel|rMH>OpRGINALtg%gpg`=}M^Q#V5( zMgJY&gF)+;`e38QHI*c%B}m94o&tOfae;og&!J2;6ENW}QeL73jatbI1*9X~y=$Dm%6FwDcnCyMRL}zo`0=y7=}*Uw zo3!qZncAL{HCgY!+}eKr{P8o27ye+;qJP;kOB%RpSesGoHLT6tcYp*6v~Z9NCyb6m zP#qds0jyqXX46qMNhXDn3pyIxw2f_z;L_X9EIB}AhyC`FYI}G3$WnW>#NMy{0aw}nB%1=Z4&*(FaCn5QG(zvdG^pQRU25;{wwG4h z@kuLO0F->{@g2!;NNd!PfqM-;@F0;&wK}0fT9UrH}(8A5I zt33(+&U;CLN|8+71@g z(s!f-kZZZILUG$QXm9iYiE*>2w;gpM>lgM{R9vT3q>qI{ELO2hJHVi`)*jzOk$r)9 zq}$VrE0$GUCm6A3H5J-=Z9i*biw8ng zi<1nM0lo^KqRY@Asucc#DMmWsnCS;5uPR)GL3pL=-IqSd>4&D&NKSGHH?pG;=Xo`w zw~VV9ddkwbp~m>9G0*b?j7-0fOwR?*U#BE#n7A=_fDS>`fwatxQ+`FzhBGQUAyIRZ??eJt46vHBlR>9m!vfb6I)8!v6TmtZ%G6&E|1e zOtx5xy%yOSu+<9Ul5w5N=&~4Oph?I=ZKLX5DXO(*&Po>5KjbY7s@tp$8(fO|`Xy}Y z;NmMypLoG7r#Xz4aHz7n)MYZ7Z1v;DFHLNV{)to;(;TJ=bbMgud96xRMME#0d$z-S z-r1ROBbW^&YdQWA>U|Y>{whex#~K!ZgEEk=LYG8Wqo28NFv)!t!~}quaAt}I^y-m| z8~E{9H2VnyVxb_wCZ7v%y(B@VrM6lzk~|ywCi3HeiSV`TF>j+Ijd|p*kyn;=mqtf8&DK^|*f+y$38+9!sis9N=S)nINm9=CJ<;Y z!t&C>MIeyou4XLM*ywT_JuOXR>VkpFwuT9j5>667A=CU*{TBrMTgb4HuW&!%Yt`;#md7-`R`ouOi$rEd!ErI zo#>qggAcx?C7`rQ2;)~PYCw%CkS(@EJHZ|!!lhi@Dp$*n^mgrrImsS~(ioGak>3)w zvop0lq@IISuA0Ou*#1JkG{U>xSQV1e}c)!d$L1plFX5XDXX5N7Ns{kT{y5|6MfhBD+esT)e7&CgSW8FxsXTAY=}?0A!j_V9 zJ;IJ~d%av<@=fNPJ9)T3qE78kaz64E>dJaYab5uaU`n~Zdp2h{8DV%SKE5G^$LfuOTRRjB;TnT(Jk$r{Pfe4CO!SM_7d)I zquW~FVCpSycJ~c*B*V8?Qqo=GwU8CkmmLFugfHQ7;A{yCy1OL-+X=twLYg9|H=~8H znnN@|tCs^ZLlCBl5wHvYF}2vo>a6%mUWpTds_mt*@wMN4-r`%NTA%+$(`m6{MNpi@ zMx)8f>U4hd!row@gM&PVo&Hx+lV@$j9yWTjTue zG9n0DP<*HUmJ7ZZWwI2x+{t3QEfr6?T}2iXl=6e0b~)J>X3`!fXd9+2wc1%cj&F@Z zgYR|r5Xd5jy9;YW&=4{-0rJ*L5CgDPj9^3%bp-`HkyBs`j1iTUGD4?WilZ6RO8mIE z+~Joc?GID6K96dyuv(dWREK9Os~%?$$FxswxQsoOi8M?RnL%B~Lyk&(-09D0M?^Jy zWjP)n(b)TF<-|CG%!Vz?8Fu&6iU<>oG#kGcrcrrBlfZMVl0wOJvsq%RL9To%iCW@)#& zZAJWhgzYAq)#NTNb~3GBcD%ZZOc43!YWSyA7TD6xkk)n^FaRAz73b}%9d&YisBic(?mv=Iq^r%Ug zzHq-rRrhfOOF+yR=AN!a9*Rd#sM9ONt5h~w)yMP7Dl9lfpi$H0%GPW^lS4~~?vI8Z z%^ToK#NOe0ExmUsb`lLO$W*}yXNOxPe@zD*90uTDULnH6C?InP3J=jYEO2d)&e|mP z1DSd0QOZeuLWo*NqZzopA+LXy9)fJC00NSX=_4Mi1Z)YyZVC>C!g}cY(Amaj%QN+bev|Xxd2OPD zk!dfkY6k!(sDBvsFC2r^?}hb81(WG5Lt9|riT`2?P;B%jaf5UX<~OJ;uAL$=Ien+V zC!V8u0v?CUa)4*Q+Q_u zkx{q;NjLcvyMuU*{+uDsCQ4U{JLowYby-tn@hatL zy}X>9y08#}oytdn^qfFesF)Tt(2!XGw#r%?7&zzFFh2U;#U9XBO8W--#gOpfbJ`Ey z|M8FCKlWQrOJwE;@Sm02l9OBr7N}go4V8ur)}M@m2uWjggb)DC4s`I4d7_8O&E(j; z?3$9~R$QDxNM^rNh9Y;6P7w+bo2q}NEd6f&_raor-v`UCaTM3TT8HK2-$|n{N@U>_ zL-`P7EXoEU5JRMa)?tNUEe8XFis+w8g9k(QQ)%?&Oac}S`2V$b?%`DwXBgja&&fR@ zH_XidF$p1wA)J|Wk1;?lCl?fgc)=TB3>Y8;BoMqHwJqhL)Tgydv9(?(TBX)fq%=~C zmLj!iX-kn7QA(9snzk0LRf<%SzO&~IhLor6A3f*U^UcoAygRe!H#@UCv$JUP&vPxs zeDj$1%#<2T1!e|!7xI+~_VXLl5|jHqvOhU7ZDUGee;HnkcPP=_k_FFxPjXg*9KyI+ zIh0@+s)1JDSuKMeaDZ3|<_*J8{TUFDLl|mXmY8B>Wj_?4mC#=XjsCKPEO=p0c&t&Z zd1%kHxR#o9S*C?du*}tEHfAC7WetnvS}`<%j=o7YVna)6pw(xzkUi7f#$|^y4WQ{7 zu@@lu=j6xr*11VEIY+`B{tgd(c3zO8%nGk0U^%ec6h)G_`ki|XQXr!?NsQkxzV6Bn1ea9L+@ z(Zr7CU_oXaW>VOdfzENm+FlFQ7Se0ROrNdw(QLvb6{f}HRQ{$Je>(c&rws#{dFI^r zZ4^(`J*G0~Pu_+p5AAh>RRpkcbaS2a?Fe&JqxDTp`dIW9;DL%0wxX5;`KxyA4F{(~_`93>NF@bj4LF!NC&D6Zm+Di$Q-tb2*Q z&csGmXyqA%Z9s(AxNO3@Ij=WGt=UG6J7F;r*uqdQa z?7j!nV{8eQE-cwY7L(3AEXF3&V*9{DpSYdyCjRhv#&2johwf{r+k`QB81%!aRVN<& z@b*N^xiw_lU>H~@4MWzgHxSOGVfnD|iC7=hf0%CPm_@@4^t-nj#GHMug&S|FJtr?i z^JVrobltd(-?Ll>)6>jwgX=dUy+^n_ifzM>3)an3iOzpG9Tu;+96TP<0Jm_PIqof3 zMn=~M!#Ky{CTN_2f7Y-i#|gW~32RCWKA4-J9sS&>kYpTOx#xVNLCo)A$LUme^fVNH z@^S7VU^UJ0YR8?Oy$^IYuG*bm|g;@aX~i60%`7XLy*AYpYvZ^F^U(!|RW z*C!rJ@+7TGdL=nNd1gv^%B+;Fcr$y)i0!GRsZXRHPs>QVGVR{9r_#&Qd(wL|5;H;> zD>HUw=4CF++&{7$<8G@j*nGjhEO%BQYfjeItp4mPvY*JYb1HKd!{HJ9*)(3%BR%{Pp?AM&*yHAJsW({ivOzj*qS!-7|XEn6@zo z3L*tBT%<4RxoAh>q{0n_JBmgW6&8hx?kL(_^k%VL>?xjAyrKBmSl`$=V|SK}ELl}@ zd|d0eo#RfG`bw9SK3%r4Y+rdvc}w}~ixV%tqawbdqvE-WcgE+BUpxMT%F@btm76MG zn=oQRWWuTm+a{dy)Oc2V4yX(@M{QAkx>(QB59*`dLT`Pz3Lsj9iB=HSHAiCq()ns|Cr)1*c605Cx}3V&x}Lg?b+6Q?)z7Kl zQh&1Hx`y6JY-Cwvd*ozeps}a1xAA0CR+Da;+O(i)P1C;SjOI}Dtmf6tPqo-Bl`U78 zv$kYgPntPp@G)n1an9tEoL*Vumu9`>_@I(;+5+fBa-*?fEx=mTEjZ7wq}#@Gd5_cW z!mP{N=yqEntDo)|>oy6{9cu+-3*GTnmb^`O0^FzRPO^&aG`f@F_R*aQ_e{F+_9%NW z4KG_B`@X3EVV9L>?_RNDMddA>w=e0KfAiw5?#i1NFT%Zz#nuv(&!yIU>lVxmzYKQ` zzJ*0w9<&L4aJ6A;0j|_~i>+y(q-=;2Xxhx2v%CYY^{} z^J@LO()eLo|7!{ghQ+(u$wxO*xY#)cL(|miH2_ck2yN{mu4O9=hBW*pM_()-_YdH#Ru{JtwJ^R2}3?!>>m1pohh zrn(!xCjE0Q&EH1QK?zA%sxVh&H99cObJUY$veZhQ)MLu-h%`!*G)s$2k;~+A z)Kk->Ri?`oGDEJEtI*wijm(s5f$W78FH{+qBxiU{~kq((J3uK{m z$|C8K#j-?hm8H@x%VfFqpnvu@xn1s%J7uNZC9C99a<_b1J|mx%)$%!6gPU|~<@2&m zz99GDp`|a%m*iggvfL;4%X;~WY>)@!tMWB@P`)k?$;0x9JSrRI8?s3rlgH(o@`OAo zn{f*gZ#t2u6K??hx|aElOM`Xd0t+SAIUEHvFw%?Wsm$s zUXq{6UU?a>Nc@@Xlb_2k9M1Ctr<#+O?yd}rv z_wu&=_t$!Yngd@N_AUj}T; z#*Ce|%XZr_sQcsWcsl{pCnnj+c8ZNIMmx<;w=-g$Q>BU;9k;w|zQ;4!W32Xg2Cd?{ zvmO3kuKQ^Hv;o>6ZHP8ZJ2`4~Bx?N;cf<0fi=!*G^^WzbTF3e$b&d^qqB{>nqLG81 zs94bBh%|Vj+hLu=!8(b9brJ>ZBns9^6s(gdSVyP9qnu2_I{Sg8j-rloG6{d`De5We zDe5WeY3ga}Y3ga}Y3ga}Y3ga}Y3ga}d8y~6o|k%F>UpW>rJk31Ug~+N=cS&HdOqs; zsOO`ek9t1p`Kafko{xGy>iMbXr=FjBxZMYc8a#gL`Kjlpo}YSt>iMY`pk9DF0qO*( z6QE9jIsxhgs1u-0kUBx8D@eT{^@7w3QZGooAoYUO3sNscy%6<6)C*BBM7L`dk$Xk%6}eZQXgo#!75P`>Uy*-B{uTLGUy*-B{uTLGUy*-B{uTLG))v8{5gt_uj9!t5)^yb-JtjRGrhi zYInOUNJxNyf_yKX01)K=WP|Si>HqEj|B{eUl?MR<)%<1&{(~)D+NPwKxWqT-@~snp zg9KCz1VTZDiS?UH`PRk1VPM{29cgT9=D?!Wc_@}qzggFv;gb@2cJQAYWWtpEZ7?y@jSVqjx${B5UV@SO|wH<<0; z{><1KdVI%Ki}>~<`46C0AggwUwx-|QcU;iiZ{NZu`ur>hd*|Hb(|6veERqxu=b@5Bab=rqptGxd{QJg!4*-i_$sES~)AB46}Fjg|ea#e@?J}z%CUJ zOsLWRQR1#ng^sD)A4FDuY!iUhzlgfJh(J@BRqd&P#v2B`+saBx>m+M&q7vk-75$NH%T5pi%m z5FX?`2-5l53=a&GkC9^NZCLpN5(DMKMwwab$FDIs?q>4!!xBS}75gX_5;(luk;3Vl zLCLd5a_8`Iyz}K}+#RMwu6DVk3O_-}n>aE!4NaD*sQn`GxY?cHe!Bl9n?u&g6?aKm z-P8z&;Q3gr;h`YIxX%z^o&GZZg1=>_+hP2$$-DnL_?7?3^!WAsY4I7|@K;aL<>OTK zByfjl2PA$T83*LM9(;espx-qB%wv7H2i6CFsfAg<9V>Pj*OpwX)l?^mQfr$*OPPS$ z=`mzTYs{*(UW^ij1U8UfXjNoY7GK*+YHht(2oKE&tfZuvAyoN(;_OF>-J6AMmS5fB z^sY6wea&&${+!}@R1f$5oC-2J>J-A${@r(dRzc`wnK>a7~8{Y-scc|ETOI8 zjtNY%Y2!PI;8-@a=O}+{ap1Ewk0@T`C`q!|=KceX9gK8wtOtIC96}-^7)v23Mu;MH zhKyLGOQMujfRG$p(s`(2*nP4EH7*J57^=|%t(#PwCcW7U%e=8Jb>p6~>RAlY4a*ts=pl}_J{->@kKzxH|8XQ5{t=E zV&o`$D#ZHdv&iZWFa)(~oBh-Osl{~CS0hfM7?PyWUWsr5oYlsyC1cwULoQ4|Y5RHA2*rN+EnFPnu z`Y_&Yz*#550YJwDy@brZU>0pWV^RxRjL221@2ABq)AtA%Cz?+FG(}Yh?^v)1Lnh%D zeM{{3&-4#F9rZhS@DT0E(WRkrG!jC#5?OFjZv*xQjUP~XsaxL2rqRKvPW$zHqHr8Urp2Z)L z+)EvQeoeJ8c6A#Iy9>3lxiH3=@86uiTbnnJJJoypZ7gco_*HvKOH97B? zWiwp>+r}*Zf9b3ImxwvjL~h~j<<3shN8$k-$V1p|96I!=N6VBqmb==Bec|*;HUg?) z4!5#R*(#Fe)w%+RH#y{8&%%!|fQ5JcFzUE;-yVYR^&Ek55AXb{^w|@j|&G z|6C-+*On%j;W|f8mj?;679?!qY86c{(s1-PI2Wahoclf%1*8%JAvRh1(0)5Vu37Iz z`JY?RW@qKr+FMmBC{TC7k@}fv-k8t6iO}4K-i3WkF!Lc=D`nuD)v#Na zA|R*no51fkUN3^rmI;tty#IK284*2Zu!kG13!$OlxJAt@zLU`kvsazO25TpJLbK&;M8kw*0)*14kpf*)3;GiDh;C(F}$- z1;!=OBkW#ctacN=je*Pr)lnGzX=OwgNZjTpVbFxqb;8kTc@X&L2XR0A7oc!Mf2?u9 zcctQLCCr+tYipa_k=;1ETIpHt!Jeo;iy^xqBES^Ct6-+wHi%2g&)?7N^Yy zUrMIu){Jk)luDa@7We5U!$$3XFNbyRT!YPIbMKj5$IEpTX1IOtVP~(UPO2-+9ZFi6 z-$3<|{Xb#@tABt0M0s1TVCWKwveDy^S!!@4$s|DAqhsEv--Z}Dl)t%0G>U#ycJ7cy z^8%;|pg32=7~MJmqlC-x07Sd!2YX^|2D`?y;-$a!rZ3R5ia{v1QI_^>gi(HSS_e%2 zUbdg^zjMBBiLr8eSI^BqXM6HKKg#@-w`a**w(}RMe%XWl3MipvBODo*hi?+ykYq)z ziqy4goZw0@VIUY65+L7DaM5q=KWFd$;W3S!Zi>sOzpEF#(*3V-27N;^pDRoMh~(ZD zJLZXIam0lM7U#)119Hm947W)p3$%V`0Tv+*n=&ybF&}h~FA}7hEpA&1Y!BiYIb~~D z$TSo9#3ee02e^%*@4|*+=Nq6&JG5>zX4k5f?)z*#pI-G(+j|jye%13CUdcSP;rNlY z#Q!X%zHf|V)GWIcEz-=fW6AahfxI~y7w7i|PK6H@@twdgH>D_R@>&OtKl}%MuAQ7I zcpFmV^~w~8$4@zzh~P~+?B~%L@EM3x(^KXJSgc6I=;)B6 zpRco2LKIlURPE*XUmZ^|1vb?w*ZfF}EXvY13I4af+()bAI5V?BRbFp`Sb{8GRJHd* z4S2s%4A)6Uc=PK%4@PbJ<{1R6+2THMk0c+kif**#ZGE)w6WsqH z`r^DL&r8|OEAumm^qyrryd(HQ9olv$ltnVGB{aY?_76Uk%6p;e)2DTvF(;t=Q+|8b zqfT(u5@BP);6;jmRAEV057E*2d^wx@*aL1GqWU|$6h5%O@cQtVtC^isd%gD7PZ_Io z_BDP5w(2*)Mu&JxS@X%%ByH_@+l>y07jIc~!@;Raw)q_;9oy@*U#mCnc7%t85qa4? z%_Vr5tkN^}(^>`EFhag;!MpRh!&bKnveQZAJ4)gEJo1@wHtT$Gs6IpznN$Lk-$NcM z3ReVC&qcXvfGX$I0nfkS$a|Pm%x+lq{WweNc;K>a1M@EAVWs2IBcQPiEJNt}+Ea8~WiapASoMvo(&PdUO}AfC~>ZGzqWjd)4no( ziLi#e3lOU~sI*XPH&n&J0cWfoh*}eWEEZW%vX?YK!$?w}htY|GALx3;YZoo=JCF4@ zdiaA-uq!*L5;Yg)z-_`MciiIwDAAR3-snC4V+KA>&V%Ak;p{1u>{Lw$NFj)Yn0Ms2*kxUZ)OTddbiJM}PK!DM}Ot zczn?EZXhx3wyu6i{QMz_Ht%b?K&-@5r;8b076YDir`KXF0&2i9NQ~#JYaq*}Ylb}^ z<{{6xy&;dQ;|@k_(31PDr!}}W$zF7Jv@f%um0M$#=8ygpu%j(VU-d5JtQwT714#f0z+Cm$F9JjGr_G!~NS@L9P;C1? z;Ij2YVYuv}tzU+HugU=f9b1Wbx3418+xj$RKD;$gf$0j_A&c;-OhoF*z@DhEW@d9o zbQBjqEQnn2aG?N9{bmD^A#Um6SDKsm0g{g_<4^dJjg_l_HXdDMk!p`oFv8+@_v_9> zq;#WkQ!GNGfLT7f8m60H@$tu?p;o_It#TApmE`xnZr|_|cb3XXE)N^buLE`9R=Qbg zXJu}6r07me2HU<)S7m?@GzrQDTE3UH?FXM7V+-lT#l}P(U>Fvnyw8T7RTeP`R579m zj=Y>qDw1h-;|mX-)cSXCc$?hr;43LQt)7z$1QG^pyclQ1Bd!jbzsVEgIg~u9b38;> zfsRa%U`l%did6HzPRd;TK{_EW;n^Ivp-%pu0%9G-z@Au{Ry+EqEcqW=z-#6;-!{WA z;l+xC6Zke>dl+(R1q7B^Hu~HmrG~Kt575mzve>x*cL-shl+zqp6yuGX)DDGm`cid! znlnZY=+a5*xQ=$qM}5$N+o!^(TqTFHDdyCcL8NM4VY@2gnNXF|D?5a558Lb*Yfm4) z_;0%2EF7k{)i(tTvS`l5he^KvW%l&-suPwpIlWB_Za1Hfa$@J!emrcyPpTKKM@NqL z?X_SqHt#DucWm<3Lp}W|&YyQE27zbGP55=HtZmB(k*WZA79f##?TweCt{%5yuc+Kx zgfSrIZI*Y57FOD9l@H0nzqOu|Bhrm&^m_RK6^Z<^N($=DDxyyPLA z+J)E(gs9AfaO`5qk$IGGY+_*tEk0n_wrM}n4G#So>8Dw6#K7tx@g;U`8hN_R;^Uw9JLRUgOQ?PTMr4YD5H7=ryv)bPtl=<&4&% z*w6k|D-%Tg*F~sh0Ns(h&mOQ_Qf{`#_XU44(VDY8b})RFpLykg10uxUztD>gswTH} z&&xgt>zc(+=GdM2gIQ%3V4AGxPFW0*l0YsbA|nFZpN~ih4u-P!{39d@_MN)DC%d1w z7>SaUs-g@Hp7xqZ3Tn)e z7x^sC`xJ{V<3YrmbB{h9i5rdancCEyL=9ZOJXoVHo@$$-%ZaNm-75Z-Ry9Z%!^+STWyv~To>{^T&MW0-;$3yc9L2mhq z;ZbQ5LGNM+aN628)Cs16>p55^T^*8$Dw&ss_~4G5Go63gW^CY+0+Z07f2WB4Dh0^q z-|6QgV8__5>~&z1gq0FxDWr`OzmR}3aJmCA^d_eufde7;d|OCrKdnaM>4(M%4V`PxpCJc~UhEuddx9)@)9qe_|i z)0EA%&P@_&9&o#9eqZCUCbh?`j!zgih5sJ%c4(7_#|Xt#r7MVL&Q+^PQEg3MBW;4T zG^4-*8L%s|A}R%*eGdx&i}B1He(mLygTmIAc^G(9Si zK7e{Ngoq>r-r-zhyygK)*9cj8_%g z)`>ANlipCdzw(raeqP-+ldhyUv_VOht+!w*>Sh+Z7(7(l=9~_Vk ztsM|g1xW`?)?|@m2jyAgC_IB`Mtz(O`mwgP15`lPb2V+VihV#29>y=H6ujE#rdnK` zH`EaHzABs~teIrh`ScxMz}FC**_Ii?^EbL(n90b(F0r0PMQ70UkL}tv;*4~bKCiYm zqngRuGy`^c_*M6{*_~%7FmOMquOEZXAg1^kM`)0ZrFqgC>C%RJvQSo_OAA(WF3{euE}GaeA?tu5kF@#62mM$a051I zNhE>u>!gFE8g#Jj95BqHQS%|>DOj71MZ?EYfM+MiJcX?>*}vKfGaBfQFZ3f^Q-R1# znhyK1*RvO@nHb|^i4Ep_0s{lZwCNa;Ix<{E5cUReguJf+72QRZIc%`9-Vy)D zWKhb?FbluyDTgT^naN%l2|rm}oO6D0=3kfXO2L{tqj(kDqjbl(pYz9DykeZlk4iW5 zER`)vqJxx(NOa;so@buE!389-YLbEi@6rZG0#GBsC+Z0fzT6+d7deYVU;dy!rPXiE zmu73@Jr&~K{-9MVQD}&`)e>yLNWr>Yh8CXae9XqfvVQ&eC_;#zpoaMxZ0GpZz7xjx z`t_Q-F?u=vrRPaj3r<9&t6K=+egimiJ8D4gh-rUYvaVy zG($v+3zk5sMuOhjxkH7bQ}(5{PD3Mg?!@8PkK&w>n7tO8FmAmoF30_#^B~c(Q_`4L zYWOoDVSnK|1=p{+@`Fk^Qb81Xf89_S`RSTzv(a4ID%71nll%{Wad$!CKfeTKkyC?n zCkMKHU#*nz_(tO$M)UP&ZfJ#*q(0Gr!E(l5(ce<3xut+_i8XrK8?Xr7_oeHz(bZ?~8q5q~$Rah{5@@7SMN zx9PnJ-5?^xeW2m?yC_7A#WK*B@oIy*Y@iC1n7lYKj&m7vV;KP4TVll=II)$39dOJ^czLRU>L> z68P*PFMN+WXxdAu=Hyt3g$l(GTeTVOZYw3KY|W0Fk-$S_`@9`K=60)bEy?Z%tT+Iq z7f>%M9P)FGg3EY$ood+v$pdsXvG? zd2q3abeu-}LfAQWY@=*+#`CX8RChoA`=1!hS1x5dOF)rGjX4KFg!iPHZE2E=rv|A} zro(8h38LLFljl^>?nJkc+wdY&MOOlVa@6>vBki#gKhNVv+%Add{g6#-@Z$k*ps}0Y zQ=8$)+Nm||)mVz^aa4b-Vpg=1daRaOU)8@BY4jS>=5n#6abG@(F2`=k-eQ9@u# zxfNFHv=z2w@{p1dzSOgHokX1AUGT0DY4jQI@YMw)EWQ~q5wmR$KQ}Y;(HPMSQCwzu zdli|G?bj(>++CP)yQ4s6YfpDc3KqPmquQSxg%*EnTWumWugbDW5ef%8j-rT#3rJu? z)5n;4b2c*;2LIW%LmvUu6t1~di~}0&Svy}QX#ER|hDFZwl!~zUP&}B1oKAxIzt~so zb!GaJYOb#&qRUjEI1xe_`@7qv_-LggQ$JE8+{ryT4%ldwC5ete+{G3C#g@^oxfY3#F zcLlj(l2G8>tC<5XWV|6_DZQZ7ow?MD8EZ9mM2oV~WoV-uoExmbwpzc6eMV}%J_{3l zW(4t2a-o}XRlU|NSiYn!*nR(Sc>*@TuU*(S77gfCi7+WR%2b;4#RiyxWR3(u5BIdf zo@#g4wQjtG3T$PqdX$2z8Zi|QP~I^*9iC+(!;?qkyk&Q7v>DLJGjS44q|%yBz}}>i z&Ve%^6>xY<=Pi9WlwpWB%K10Iz`*#gS^YqMeV9$4qFchMFO}(%y}xs2Hn_E}s4=*3 z+lAeCKtS}9E{l(P=PBI;rsYVG-gw}-_x;KwUefIB@V%RLA&}WU2XCL_?hZHoR<7ED zY}4#P_MmX(_G_lqfp=+iX|!*)RdLCr-1w`4rB_@bI&Uz# z!>9C3&LdoB$r+O#n);WTPi;V52OhNeKfW6_NLnw zpFTuLC^@aPy~ZGUPZr;)=-p|b$-R8htO)JXy{ecE5a|b{{&0O%H2rN&9(VHxmvNly zbY?sVk}@^{aw)%#J}|UW=ucLWs%%j)^n7S%8D1Woi$UT}VuU6@Sd6zc2+t_2IMBxd zb4R#ykMr8s5gKy=v+opw6;4R&&46$V+OOpDZwp3iR0Osqpjx))joB*iX+diVl?E~Q zc|$qmb#T#7Kcal042LUNAoPTPUxF-iGFw>ZFnUqU@y$&s8%h-HGD`EoNBbe#S>Y-4 zlkeAP>62k~-N zHQqXXyN67hGD6CxQIq_zoepU&j0 zYO&}<4cS^2sp!;5))(aAD!KmUED#QGr48DVlwbyft31WlS2yU<1>#VMp?>D1BCFfB z_JJ-kxTB{OLI}5XcPHXUo}x~->VP%of!G_N-(3Snvq`*gX3u0GR&}*fFwHo3-vIw0 zeiWskq3ZT9hTg^je{sC^@+z3FAd}KNhbpE5RO+lsLgv$;1igG7pRwI|;BO7o($2>mS(E z$CO@qYf5i=Zh6-xB=U8@mR7Yjk%OUp;_MMBfe_v1A(Hqk6!D})x%JNl838^ZA13Xu zz}LyD@X2;5o1P61Rc$%jcUnJ>`;6r{h5yrEbnbM$$ntA@P2IS1PyW^RyG0$S2tUlh z8?E(McS?7}X3nAAJs2u_n{^05)*D7 zW{Y>o99!I9&KQdzgtG(k@BT|J*;{Pt*b|?A_})e98pXCbMWbhBZ$t&YbNQOwN^=F) z_yIb_az2Pyya2530n@Y@s>s>n?L79;U-O9oPY$==~f1gXro5Y z*3~JaenSl_I}1*&dpYD?i8s<7w%~sEojqq~iFnaYyLgM#so%_ZZ^WTV0`R*H@{m2+ zja4MX^|#>xS9YQo{@F1I)!%RhM{4ZUapHTKgLZLcn$ehRq(emb8 z9<&Nx*RLcS#)SdTxcURrJhxPM2IBP%I zf1bWu&uRf{60-?Gclb5(IFI*!%tU*7d`i!l@>TaHzYQqH4_Y*6!Wy0d-B#Lz7Rg3l zqKsvXUk9@6iKV6#!bDy5n&j9MYpcKm!vG7z*2&4G*Yl}iccl*@WqKZWQSJCgQSj+d ze&}E1mAs^hP}>`{BJ6lv*>0-ft<;P@`u&VFI~P3qRtufE11+|#Y6|RJccqo27Wzr}Tp|DH z`G4^v)_8}R24X3}=6X&@Uqu;hKEQV^-)VKnBzI*|Iskecw~l?+R|WKO*~(1LrpdJ? z0!JKnCe<|m*WR>m+Qm+NKNH<_yefIml z+x32qzkNRrhR^IhT#yCiYU{3oq196nC3ePkB)f%7X1G^Ibog$ZnYu4(HyHUiFB`6x zo$ty-8pknmO|B9|(5TzoHG|%>s#7)CM(i=M7Nl=@GyDi-*ng6ahK(&-_4h(lyUN-oOa$` zo+P;C4d@m^p9J4c~rbi$rq9nhGxayFjhg+Rqa{l#`Y z!(P6K7fK3T;y!VZhGiC#)|pl$QX?a)a9$(4l(usVSH>2&5pIu5ALn*CqBt)9$yAl; z-{fOmgu><7YJ5k>*0Q~>lq72!XFX6P5Z{vW&zLsraKq5H%Z26}$OKDMv=sim;K?vsoVs(JNbgTU8-M%+ zN(+7Xl}`BDl=KDkUHM9fLlV)gN&PqbyX)$86!Wv!y+r*~kAyjFUKPDWL3A)m$@ir9 zjJ;uQV9#3$*`Dqo1Cy5*;^8DQcid^Td=CivAP+D;gl4b7*xa9IQ-R|lY5tIpiM~9- z%Hm9*vDV@_1FfiR|Kqh_5Ml0sm?abD>@peo(cnhiSWs$uy&$RYcd+m`6%X9FN%?w}s~Q=3!pJzbN~iJ}bbM*PPi@!E0eN zhKcuT=kAsz8TQo76CMO+FW#hr6da({mqpGK2K4T|xv9SNIXZ}a=4_K5pbz1HE6T}9 zbApW~m0C`q)S^F}B9Kw5!eT)Bj_h9vlCX8%VRvMOg8PJ*>PU>%yt-hyGOhjg!2pZR4{ z=VR_*?Hw|aai##~+^H>3p$W@6Zi`o4^iO2Iy=FPdEAI58Ebc~*%1#sh8KzUKOVHs( z<3$LMSCFP|!>fmF^oESZR|c|2JI3|gucuLq4R(||_!8L@gHU8hUQZKn2S#z@EVf3? zTroZd&}JK(mJLe>#x8xL)jfx$6`okcHP?8i%dW?F%nZh=VJ)32CmY;^y5C1^?V0;M z<3!e8GZcPej-h&-Osc>6PU2f4x=XhA*<_K*D6U6R)4xbEx~{3*ldB#N+7QEXD^v=I z+i^L+V7_2ld}O2b-(#bmv*PyZI4|U#Q5|22a(-VLOTZc3!9ns1RI-? zA<~h|tPH0y*bO1#EMrsWN>4yJM7vqFZr?uw$H8*PhiHRQg1U9YoscX-G|gck+SSRX!(e7@~eeUEw+POsT;=W9J&=EV`cUc{PIg_#TQVGnZsQbCs7#Q-)v#BicxLw#Fb?#)8TYbu zN)5R=MI1i7FHhF|X}xEl=sW~`-kf;fOR^h1yjthSw?%#F{HqrY2$q>7!nbw~nZ8q9 zh{vY! z%i=H!!P&wh z7_E%pB7l5)*VU>_O-S~d5Z!+;f{pQ4e86*&);?G<9*Q$JEJ!ZxY;Oj5&@^eg0Zs!iLCAR`2K?MSFzjX;kHD6)^`&=EZOIdW>L#O`J zf~$M4}JiV}v6B-e{NUBGFgj-*H%NG zfY0X(@|S8?V)drF;2OQcpDl2LV=~=%gGx?_$fbSsi@%J~taHcMTLLpjNF8FkjnjyM zW;4sSf6RHaa~LijL#EJ0W2m!BmQP(f=%Km_N@hsBFw%q#7{Er?y1V~UEPEih87B`~ zv$jE%>Ug9&=o+sZVZL7^+sp)PSrS;ZIJac4S-M>#V;T--4FXZ*>CI7w%583<{>tb6 zOZ8gZ#B0jplyTbzto2VOs)s9U%trre`m=RlKf{I_Nwdxn(xNG%zaVNurEYiMV3*g| z``3;{j7`UyfFrjlEbIJN{0db|r>|LA@=vX9CHFZYiexnkn$b%8Rvw0TZOQIXa;oTI zv@j;ZP+#~|!J(aBz9S{wL7W%Dr1H)G-XUNt9-lP?ijJ-XEj1e*CI~-Xz@4(Xg;UoG z{uzBf-U+(SHe}6oG%;A*93Zb=oE>uTb^%qsL>|bQf?7_6=KIiPU`I|r;YcZ!YG7y~ zQu@UldAwz$^|uoz3mz1;An-WVBtefSh-pv<`n&TU3oM!hrEI?l@v8A4#^$4t&~T32 zl*J=1q~h+60sNc43>0aVvhzyfjshgPYZoQ(OOh>LbUIoblb@1z~zp?))n?^)q6WGuDh}gMUaA9|X z3qq-XlcNldy5==T4rq*~g@XVY!9sYZjo#R7 zr{n)r5^S{9+$+8l7IVB*3_k5%-TBY@C%`P@&tZf>82sm#nfw7L%92>nN$663yW!yt zhS>EfLcE_Z)gv-Y^h1;xj(<4nD4GY{C-nWUgQc9cMmH{qpa!uEznrGF^?bbJHApScQ$j>$JZHAX80DdXu z--AMgrA0$Otdd#N9#!cg2Z~N8&lj1d+wDh+^ZObWJ$J)_h(&2#msu>q0B$DEERy{1 zCJN{7M@%#E@8pda`@u!v@{gcT3bA*>g*xYLXlbb&o@1vX*x+l}Voys6o~^_7>#GB| z*r!R%kA9k%J`?m>1tMHB9x$ZRe0$r~ui}X}jOC)9LH=Po*2SLdtf3^4?VKnu2ox&mV~0oDgi` z;9d}P$g~9%ThTK8s}5ow2V4?(-lU*ed8ro|}mU}pk% z;bqB0bx3AOk<0Joeh}Vl@_7Po&C`Cg>>gff>e7fu41U3Ic{JQu1W%+!Gvz3GDO2ixKd;KF6UEw8F_cDAh08gB>@ zaRH2Q96sBJ>`4aXvrF0xPtIWoA1pPsRQtU~xDtnEfTJnl{A9u5pR^K8=UdNq%T8F$)FbN> zgK+_(BF#D>R>kK!M#OT~=@@}3yAYqm33?{Bv?2iBr|-aRK0@uapzuXI)wE0=R@m^7 zQ`wLBn(M*wg!mgmQT1d!@3<2z>~rmDW)KG0*B4>_R6LjiI0^9QT8gtDDT|Lclxppm z+OeL6H3QpearJAB%1ellZ6d*)wBQ(hPbE=%?y6i^uf%`RXm*JW*WQ%>&J+=V(=qf{ zri~yItvTZbII+7S0>4Q0U9@>HnMP$X>8TqAfD(vAh};2P{QK)ik`a6$W$nG<{bR2Ufd!^iE z#1K58$gW!xpeYHeehuhQCXZ9p%N8m zB+l~T_u-Ycr!U>!?xu!!*6rNxq37{`DhMMfY6NpD3Jw zkYQDstvt30Hc_SaZuuMP2YrdW@HsPMbf^Y9lI<9$bnMil2X7`Ba-DGLbzgqP>mxwe zf1&JkDH54D3nLar2KjJ3z`*R+rUABq4;>>4Kjc2iQEj7pVLcZYZ~pteAG4rm1{>PQy=!QiV5G|tVk)53 zP?Azw+N)Yq3zZ`dW7Q9Bq@Y*jSK0<1f`HM;_>GH57pf_S%Ounz_yhTY8lplQSM`xx zU{r-Deqs+*I~sLI$Oq`>i`J1kJ(+yNOYy$_>R3Jfi680<|^u#J@aY%Q>O zqfI~sCbk#3--^zMkV&Yj0D(R^rK}+_npgPr_4^kYuG=pO%$C_7v{s@-{M-P@RL3^<`kO@b=YdKMuccfO1ZW# zeRYE%D~CMAgPlo?T!O6?b|pOZv{iMWb;sN=jF%=?$Iz_5zH?K;aFGU^8l7u%zHgiy z%)~y|k;Es-7YX69AMj^epGX#&^c@pp+lc}kKc`5CjPN4Z$$e58$Yn*J?81%`0~A)D zPg-db*pj-t4-G9>ImW4IMi*v#9z^9VD9h@9t;3jMAUVxt=oor+16yHf{lT|G4 zya6{4#BxFw!!~UTRwXXawKU4iz$$GMY6=Z8VM{2@0{=5A0+A#p6$aT3ubRyWMWPq9 zCEH5(Il0v4e4=Yxg(tDglfYAy!UpC>&^4=x7#6_S&Ktds)a8^`^tp6RnRd{KImB^o z2n=t#>iKx<*evmvoE{+fH#@WXGWs$)Uxrtf?r>AaxV0?kf0o@oDboJ6z0cgP@A$;k>SK1UqC?Q_ zk_I?j74;}uNXhOf_5ZxQSgB4otDEb9JJrX1kq`-o%T>g%M5~xXf!2_4P~K64tKgXq z&KHZ0@!cPvUJG4kw-0;tPo$zJrU-Nop>Uo65Pm|yaNvKjhi7V1g98;^N1~V3% zTR>yWa+X2FJ_wpPwz3i^6AGwOa_VMS-&`*KoKgF2&oR10Jn6{!pvVG@n=Jk@vjNuY zL~P7aDGhg~O9G^!bHi$8?G9v9Gp0cmekYkK;(q=47;~gI>h-kx-ceM{ml$#8KI$4ltyjaqP zki^cyDERloAb)dcDBU4na9C(pfD{P@eBGA}0|Rb)p{ISqi60=^FUEdF!ok{Gs;vb) zfj9(#1QA64w*ud^YsN5&PeiI>c`VioE8h)e}W%S9NMA55Gs zrWL6l+@3CKd@8(UQLTwe12SGWMqRn+j)QZRj*g)Xua)%ayzpqs{pD(WWESJYL3{M$ z%qkpM`jFoqLYVv6{IbCkL?fEiJj$VG=$taup&RL9e{s(Sgse2xVJlw0h74EXJKt2eX|dxz{->0)3W`JN7Bv!rLvRZc z0tAOZ2yVe4g9iq826qXAg`f!*+}(o1;1FDb>kKexumFS40KvK0yH1_@Z=LgWZ+}(Y zwYsa;OLz6tTA%gS=>8$=Z7pLh>|K2QElL)E=Q*(n*H`8R`8={-@4mTD-SWBOYRxV? zmF(-rJB8^Wlp?319rTrh^?QEP?|Msxrv?WbJ-+id+V#F2Y4(JPJ6U9bv+U1cIIH^W z)lg$_=g^Ma>2~Pyd_YOAv29Cb-U6DJO?NxnW7~QP*SmYi*vdUVuW#LWQ_u0`hymZi zaQS3Nb^4`ro$>0G%zbXmr5|D|iq0R<;S@?kr0j5Ruq87-Z1>crx%EzVZ9#U;{?}ti zW2W%*9MQg3Nbh%Ti6LhDd|-aFSgXoPG`mHlUU1iCHr>ru>DX?W_#13(`u*!Plu2OP z6jk=2>BC0l)aw;HCmxoYD1i4b%m$1`DYC_^L~ zIEAnFcHvad=-aO3(_MI=9#`z6-9*_!&$?<%meb5;jGd5Qp=MGf z6BD{%`L#TAOq%z%@*ib95Ey7NbUF=BlszVk3Iu3imD&*91N-ij%hW?W@~2TtdHTfP z#n0@Xd7X8Dyu36n{k#PwQ~T~X7mAO^cNV+z<HO@3X-# z_@rAn$k~(l@kciCC;&Qd*fWRI>=;fL{UPlciNDWyj$bX<#r^(r;EE8wwUVQm&7~QY zCXRj!**r^xybAEPq>h3W$uvI1j=yNIyzkE_D7fpGw)OV{U*Uwm{xB;mEg2(|y|ICd zMdQVqzMb-=XM6|E-a9kNh)^9lY`-DjhhHD1w5lufRcy+QLgJ47!fFne86#F; zX{ufroVBEZJOY?rDo!;Te6aOZ^1SO!dYRxQ*2njyA~dCWawn)>!*k7~>8Ikt&e*0>>V5ZbO|*1+2LFOqVe zXHb!aMk03^h%&9L8GMy7UDI2Kev>V@(R}*Iu6x+!Hn4~D@wj`P%#Hdbf(lK{+DD7f zJ&(v*mhn_e(R$^5L#bM^^Q@-!*b!l|+Xrb(q*MRFJYnrE7*xko!SJOy9LngR2|q5k zY`Ioiu+YBfzF{Labszk-E#*BYQk>$()=xWEGZRKwY)*UxP}0dGuPLZOkNJDI9Hy zFjfwiK6RjhH#rHW#B0(MW}i%V`943<6@Z*Nd^JEP5uZonXm=u%AM>{H^U@&Jy*i0s za_Da^xI6pMtXzHc{e~_ZcnKP*;=YL2Z^RmzDl{dJTk7*}E_h*NvgnhnxVKB59Duh~ zqouS_WoOR*{UvUw_K#OWz;gMracr%8>QQ&V*jv!8)ho;U8}9~8EU{N<=Z_gR%IpMT zbkePUG_afm=#|iIfFmdqkpLMGxY5D$`?I}&T7>TexU@v zkBx09kG)O;09ckj#(_Uov6vv{{HOcr-%H#DUQ@*GzF8Zh{iSM13%fuB%>wjdU@3Nf zlnYE!GTyNrqes|;nLFXfWU*Wg-9wmr=NBd$nCk+H?iwNvcd0Wab^3CT9a`>3V~oWI z9=_H+N-Q=MQ(io4u4mpdQ;k&5FXnKV5M7R`@WJ9h(GrAirO#XXOU{qQpk^B^Vd=Dt{wiqT zg-#j9J~@o%H2;W9mg)o6@*Vo;BSs2*4HAHpDk02mndAsov08R_48zJZ@J)s7+hyCo zy*0L#y)?AqZt-wX%+_Vx`8*A95OLHvs1$k~{h-_N_vov_gHJE=`X>L?5K+ zD?u59=mjtImMvd1GsDytuYp{IyUkW&?h zF>$#`n$~bZ)KN0B$XGeMYh&`;g8 zo_2-koaO6+8O!+L>SpIQbG(i;QW9UJi{Ecewlo?s&D!^>i$|#jaW}#HJuxt|W48=? zb^Y&O$a1s5ddr8DIt!sD!t=y1g(d4GR(s;s-HfV$GXl&m;+sAAxB^rk(3_NjE$p#L z*t4em?tA0d+XwRxN^OQwzbDZMuSE0J1)Ky{mq)^t4bnSl*)s>zNM@mMdtd78&ebHN z`!(|lE5q-p+TsRaNnMXwALaN5QIZ2IUi^Z22tsN5>nvIO+YU}Q*xh6}ee6@rR~<&1 z(PB4z>9ZBUMXZwSMmd9-aKKsmJeJq^G|#JclOh*xf0?^e0(`40nsg1z)(48;4}B_( zGwPI)yo|{oX{dVDL-5-aMGr;~vU1cPtJP5JM(sswz&Q`e<@0?y{YhsO9YK8EYJA;L z>7oG_Mts+(wCBC*Md82#XdKw&J*IizR?9k^rf1r{Ot-&>V^ke{9nI9zavlcNkIJtN z7T>?o|4rENk-?|lewZ(EfdR;%BUrzKJ^UkCpsM)EA9QHBVV8trT&*O(9?FO{MLTFL z=5P0H+T6C^jAuX0k4U;~GM!x`!X2N~3_n?qXY$HI>x@(DHEy&Q3ucT1R6fj28wX!I zC=&d$@bJ_v^%?W2Ngl}e8ww`b%BrN-PzGH;$@B2Ky1?%GMkm#~Okj(-Admyy;qya| zOi73kr_pwt?5Nj3p=&H>81!w#>Agj z(QXx{j0r=pTl>micAI_5vUw<3`Sht?Z}-j2Wx~F8DKCUQrsXl2?W8hur42(F_ zsSJ)_36&x6A|YkY6c<2a94SXbv~d>4CC4nkDPvf9Z5Fys^6^5r0j5=E>Cgy_Dk@tS z%?c}9!qB?t6t8(XMH%le8UeNWp@Nsma~Ql+^3Bo%_npMryeQJz4V=BAqE~T?dejng z3ge{fjCHoNAfYBvsfq;G%VL|j7t z`X0sy1EEgpyD;)tS1x+fnv-?C@glP0{RCW}Ma?3qpoq_&IJAYOy3G#s`rsh5=3>`K zkj``=;|*x5HSjZC zXNvPLh372q;=+6ja|SC!R-`JcL}}wwskajjTUGTpL(1zkN-p?BA2lmf+J3WsB7!k`0Brx8^cLTF9h)r+LZ$vsZo}`OpOs)?c6$hclR!R#MAeh|_DY|9r zy+_3c%IO9h9X?ksp?an&>Lw;QeQ`T-Ku6HaK~H?E9-Z5$cZu{YU;1+-6B$|JD;%!^ zt(4l>F8}a-UkC4YtOxFHckhl4VKr6P$P_O*U!)IDory%}Wz`YeFx6TO{y2Y${SBm?H9cTWV=WWJ z`_*CGso!ZN>l@~_jkeXtV}fczfA{TUkyeD>)i3|NFGcCsBmK3HXp&ol_@GVs7PIpfULy!hi zs+%KYgS%(n7_z_}6)hblk~W#LZ@&2)fwm6xkFP%&Ju|MFWbNiTwy{{g-pV1RK`L&=RE2D z4|g;~vd8xd|teYS%w!IlT4W$&FTrk-hcTADX!P?*f1YWEIRwq$Ys%^(Z9w&HT$>} zsMD#6Df=uJrX!JHP7<>Or;e_Cf=}`!`qR=i8fBj)$6Lxx{HRzd8Tnzd0p>kSps{OG zKJkml>bUj8$u|F=``l(-aMxWBC@CGZ#FXClQZ<4|&%jN}Tkg#q8z)=>Ly{$i0`rjU zvt|QddO&i=91e?h3>s~i;+6{ z8X4i6a1wDLrSuE#W(zhan+U*Zq+8p3a))JFVF4ffaV51K^YgTso~3;Y*NmM; zx8T?y-N0uyWY(8=me-HUC9xtABvX5~%yg+Cp&XF$Bq=OcK6T*D7eZ2EmIoCFWm{$S z1PNw8HDpe5hHeCusN8kdeb&f2#=3M^A~7YwJ7FRrhq*)PG9x?JIAaC{MV}5}g#7R$-Ly%)4=IUkRCGOR|XTMjn&okRmFjaO^YF5^* z@)#MCBOBezD)*xQNxydlUyN?dW{fS(s-T`gv*0BEnk}`BdmrbmPO8q8y(X$AA}*RH%I7Av!~84pudHb&%Q5-j zt?=6x(iR?<^_7X0v6Ys#VAL}dKk^hcjI=|EY;kPcZ_w<*H`_*|N7SacaM1ERD@6ab zg`!iTm7$URV+lpW_{V$ruR&A>jrX68k4x2wo$45}&wf7o<|o(@B!u-L@bKyQBAGwy z4#}UrRAu>^>Vb6k2-th^>WjvP;Nl|i3WrjWv3ISkj{m{eAcQIW^_ndxSX@|8T(ASJ z?_$fcP2u*6uOBk-{d>^ z0vWlfGQMvysI%R=iE|A+!!Nw?C917EU*_$`;;)px?s83CRd3i_jBN)k#nR5t$dJ(+ z_sP;wG@Ad)^(3LRj7q}0b2O(b`|i0~5SYb%Sjk^*5ISZ-Ab+}DGu$-X1n^TF1Ndw_ zF|e*1)cI2%`TR&AW~XpqpFb!=3cHbS>np9hYD_Mr5}y5Y`SY^r7isA2Q4(z zazRQEqWDKT2zIEbjSYdCPi1ZOGz80Nsl}gxO^DWMY0AV<2K&OL{&^6#@L1?lXu#6xSMh%3^5c*}oM6DQGY#(a^@z<&D zF(43I9e&5`h|A$5!+UFuOH0>F3$shBV4`0#M4RSB8=6F0ZgIbq<2LQ$Hh^(kAJu=! zt8ZGXTacD{(3W{V1$j_{Jc)Ka7t6u}ho`4kF+4@t_0!mCBn z)}o%eA}L)_L?=jw6BIfll7tb3n}?*yLt&XADa=rW>qz=_6s9ziOd5sXjil>FVFx3r zf>Feewk0v#W9>Gp4GacTRr>Sd2T6dWi-{YX`v!D)kCWzG5xQB=?es5ON(%nkwUhNl zV>@xkWWWv*N+{e$(SrExvN6BXzU(Hxlx27{VYHf+LpIbTO+Yu(ltMk<;)3A(LU@ytVYFkYvTa79idMtUFhfxx?P!)2F`prNWW#Fub#l>N2s@nh&n_ zA4{#}|AIs9|A4P0ZF%fy=hDN!t#ifH<)4u2kirK~JUpjQ-J+~cXOZI&dIts;P}UeXslP6zKvpEKSN-$y>kJ^nw2tC9bv zo(|lT@?vZ!{_l|d^8Yh)eEBh*5ABh+Lzjw+?V)o z#P-W7361>E(Y4;@`sv;VKn G`u_lkUM?>H literal 0 HcmV?d00001 diff --git a/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/fonts/glyphicons-halflings-regular.woff2 b/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/fonts/glyphicons-halflings-regular.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..64539b54c3751a6d9adb44c8e3a45ba5a73b77f0 GIT binary patch literal 18028 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 literal 0 HcmV?d00001 diff --git a/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/js/bootstrap.min.js b/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/js/bootstrap.min.js new file mode 100644 index 00000000000..c8f82e592a1 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/js/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v3.3.4 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.4",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a(f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.4",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active"));a&&this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),c.preventDefault()}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.4",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));return a>this.$items.length-1||0>a?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.4",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){b&&3===b.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=c(d),f={relatedTarget:this};e.hasClass("open")&&(e.trigger(b=a.Event("hide.bs.dropdown",f)),b.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger("hidden.bs.dropdown",f)))}))}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.4",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(this.options.viewport.selector||this.options.viewport),this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c&&c.$tip&&c.$tip.is(":visible")?void(c.hoverState="in"):(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.options.container?a(this.options.container):this.$element.parent(),p=this.getPosition(o);h="bottom"==h&&k.bottom+m>p.bottom?"top":"top"==h&&k.top-mp.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.width&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type)})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;(e||!/destroy|hide/.test(b))&&(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.4",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.4",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.4",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return c>e?"top":!1;if("bottom"==this.affixed)return null!=c?e+this.unpin<=f.top?!1:"bottom":a-d>=e+g?!1:"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&c>=e?"top":null!=d&&i+j>=a-d?"bottom":!1},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=a(document.body).height();"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); \ No newline at end of file diff --git a/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/js/d3.min.js b/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/js/d3.min.js new file mode 100644 index 00000000000..34d5513ebfe --- /dev/null +++ b/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/js/d3.min.js @@ -0,0 +1,5 @@ +!function(){function n(n){return n&&(n.ownerDocument||n.document||n).documentElement}function t(n){return n&&(n.ownerDocument&&n.ownerDocument.defaultView||n.document&&n||n.defaultView)}function e(n,t){return t>n?-1:n>t?1:n>=t?0:0/0}function r(n){return null===n?0/0:+n}function u(n){return!isNaN(n)}function i(n){return{left:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n(t[i],e)<0?r=i+1:u=i}return r},right:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n(t[i],e)>0?u=i:r=i+1}return r}}}function o(n){return n.length}function a(n){for(var t=1;n*t%1;)t*=10;return t}function c(n,t){for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}function l(){this._=Object.create(null)}function s(n){return(n+="")===pa||n[0]===va?va+n:n}function f(n){return(n+="")[0]===va?n.slice(1):n}function h(n){return s(n)in this._}function g(n){return(n=s(n))in this._&&delete this._[n]}function p(){var n=[];for(var t in this._)n.push(f(t));return n}function v(){var n=0;for(var t in this._)++n;return n}function d(){for(var n in this._)return!1;return!0}function m(){this._=Object.create(null)}function y(n){return n}function M(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function x(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.slice(1);for(var e=0,r=da.length;r>e;++e){var u=da[e]+t;if(u in n)return u}}function b(){}function _(){}function w(n){function t(){for(var t,r=e,u=-1,i=r.length;++ue;e++)for(var u,i=n[e],o=0,a=i.length;a>o;o++)(u=i[o])&&t(u,o,e);return n}function Z(n){return ya(n,Sa),n}function V(n){var t,e;return function(r,u,i){var o,a=n[i].update,c=a.length;for(i!=e&&(e=i,t=0),u>=t&&(t=u+1);!(o=a[t])&&++t0&&(n=n.slice(0,a));var l=ka.get(n);return l&&(n=l,c=B),a?t?u:r:t?b:i}function $(n,t){return function(e){var r=ta.event;ta.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{ta.event=r}}}function B(n,t){var e=$(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function W(e){var r=".dragsuppress-"+ ++Aa,u="click"+r,i=ta.select(t(e)).on("touchmove"+r,S).on("dragstart"+r,S).on("selectstart"+r,S);if(null==Ea&&(Ea="onselectstart"in e?!1:x(e.style,"userSelect")),Ea){var o=n(e).style,a=o[Ea];o[Ea]="none"}return function(n){if(i.on(r,null),Ea&&(o[Ea]=a),n){var t=function(){i.on(u,null)};i.on(u,function(){S(),t()},!0),setTimeout(t,0)}}}function J(n,e){e.changedTouches&&(e=e.changedTouches[0]);var r=n.ownerSVGElement||n;if(r.createSVGPoint){var u=r.createSVGPoint();if(0>Na){var i=t(n);if(i.scrollX||i.scrollY){r=ta.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var o=r[0][0].getScreenCTM();Na=!(o.f||o.e),r.remove()}}return Na?(u.x=e.pageX,u.y=e.pageY):(u.x=e.clientX,u.y=e.clientY),u=u.matrixTransform(n.getScreenCTM().inverse()),[u.x,u.y]}var a=n.getBoundingClientRect();return[e.clientX-a.left-n.clientLeft,e.clientY-a.top-n.clientTop]}function G(){return ta.event.changedTouches[0].identifier}function K(n){return n>0?1:0>n?-1:0}function Q(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function nt(n){return n>1?0:-1>n?qa:Math.acos(n)}function tt(n){return n>1?Ra:-1>n?-Ra:Math.asin(n)}function et(n){return((n=Math.exp(n))-1/n)/2}function rt(n){return((n=Math.exp(n))+1/n)/2}function ut(n){return((n=Math.exp(2*n))-1)/(n+1)}function it(n){return(n=Math.sin(n/2))*n}function ot(){}function at(n,t,e){return this instanceof at?(this.h=+n,this.s=+t,void(this.l=+e)):arguments.length<2?n instanceof at?new at(n.h,n.s,n.l):bt(""+n,_t,at):new at(n,t,e)}function ct(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?i+(o-i)*n/60:180>n?o:240>n?i+(o-i)*(240-n)/60:i}function u(n){return Math.round(255*r(n))}var i,o;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,o=.5>=e?e*(1+t):e+t-e*t,i=2*e-o,new mt(u(n+120),u(n),u(n-120))}function lt(n,t,e){return this instanceof lt?(this.h=+n,this.c=+t,void(this.l=+e)):arguments.length<2?n instanceof lt?new lt(n.h,n.c,n.l):n instanceof ft?gt(n.l,n.a,n.b):gt((n=wt((n=ta.rgb(n)).r,n.g,n.b)).l,n.a,n.b):new lt(n,t,e)}function st(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),new ft(e,Math.cos(n*=Da)*t,Math.sin(n)*t)}function ft(n,t,e){return this instanceof ft?(this.l=+n,this.a=+t,void(this.b=+e)):arguments.length<2?n instanceof ft?new ft(n.l,n.a,n.b):n instanceof lt?st(n.h,n.c,n.l):wt((n=mt(n)).r,n.g,n.b):new ft(n,t,e)}function ht(n,t,e){var r=(n+16)/116,u=r+t/500,i=r-e/200;return u=pt(u)*Xa,r=pt(r)*$a,i=pt(i)*Ba,new mt(dt(3.2404542*u-1.5371385*r-.4985314*i),dt(-.969266*u+1.8760108*r+.041556*i),dt(.0556434*u-.2040259*r+1.0572252*i))}function gt(n,t,e){return n>0?new lt(Math.atan2(e,t)*Pa,Math.sqrt(t*t+e*e),n):new lt(0/0,0/0,n)}function pt(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function vt(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function dt(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function mt(n,t,e){return this instanceof mt?(this.r=~~n,this.g=~~t,void(this.b=~~e)):arguments.length<2?n instanceof mt?new mt(n.r,n.g,n.b):bt(""+n,mt,ct):new mt(n,t,e)}function yt(n){return new mt(n>>16,n>>8&255,255&n)}function Mt(n){return yt(n)+""}function xt(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function bt(n,t,e){var r,u,i,o=0,a=0,c=0;if(r=/([a-z]+)\((.*)\)/i.exec(n))switch(u=r[2].split(","),r[1]){case"hsl":return e(parseFloat(u[0]),parseFloat(u[1])/100,parseFloat(u[2])/100);case"rgb":return t(kt(u[0]),kt(u[1]),kt(u[2]))}return(i=Ga.get(n.toLowerCase()))?t(i.r,i.g,i.b):(null==n||"#"!==n.charAt(0)||isNaN(i=parseInt(n.slice(1),16))||(4===n.length?(o=(3840&i)>>4,o=o>>4|o,a=240&i,a=a>>4|a,c=15&i,c=c<<4|c):7===n.length&&(o=(16711680&i)>>16,a=(65280&i)>>8,c=255&i)),t(o,a,c))}function _t(n,t,e){var r,u,i=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-i,c=(o+i)/2;return a?(u=.5>c?a/(o+i):a/(2-o-i),r=n==o?(t-e)/a+(e>t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=0/0,u=c>0&&1>c?0:r),new at(r,u,c)}function wt(n,t,e){n=St(n),t=St(t),e=St(e);var r=vt((.4124564*n+.3575761*t+.1804375*e)/Xa),u=vt((.2126729*n+.7151522*t+.072175*e)/$a),i=vt((.0193339*n+.119192*t+.9503041*e)/Ba);return ft(116*u-16,500*(r-u),200*(u-i))}function St(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function kt(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function Et(n){return"function"==typeof n?n:function(){return n}}function At(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),Nt(t,e,n,r)}}function Nt(n,t,e,r){function u(){var n,t=c.status;if(!t&&zt(c)||t>=200&&300>t||304===t){try{n=e.call(i,c)}catch(r){return void o.error.call(i,r)}o.load.call(i,n)}else o.error.call(i,c)}var i={},o=ta.dispatch("beforesend","progress","load","error"),a={},c=new XMLHttpRequest,l=null;return!this.XDomainRequest||"withCredentials"in c||!/^(http(s)?:)?\/\//.test(n)||(c=new XDomainRequest),"onload"in c?c.onload=c.onerror=u:c.onreadystatechange=function(){c.readyState>3&&u()},c.onprogress=function(n){var t=ta.event;ta.event=n;try{o.progress.call(i,c)}finally{ta.event=t}},i.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?a[n]:(null==t?delete a[n]:a[n]=t+"",i)},i.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",i):t},i.responseType=function(n){return arguments.length?(l=n,i):l},i.response=function(n){return e=n,i},["get","post"].forEach(function(n){i[n]=function(){return i.send.apply(i,[n].concat(ra(arguments)))}}),i.send=function(e,r,u){if(2===arguments.length&&"function"==typeof r&&(u=r,r=null),c.open(e,n,!0),null==t||"accept"in a||(a.accept=t+",*/*"),c.setRequestHeader)for(var s in a)c.setRequestHeader(s,a[s]);return null!=t&&c.overrideMimeType&&c.overrideMimeType(t),null!=l&&(c.responseType=l),null!=u&&i.on("error",u).on("load",function(n){u(null,n)}),o.beforesend.call(i,c),c.send(null==r?null:r),i},i.abort=function(){return c.abort(),i},ta.rebind(i,o,"on"),null==r?i:i.get(Ct(r))}function Ct(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function zt(n){var t=n.responseType;return t&&"text"!==t?n.response:n.responseText}function qt(){var n=Lt(),t=Tt()-n;t>24?(isFinite(t)&&(clearTimeout(tc),tc=setTimeout(qt,t)),nc=0):(nc=1,rc(qt))}function Lt(){var n=Date.now();for(ec=Ka;ec;)n>=ec.t&&(ec.f=ec.c(n-ec.t)),ec=ec.n;return n}function Tt(){for(var n,t=Ka,e=1/0;t;)t.f?t=n?n.n=t.n:Ka=t.n:(t.t8?function(n){return n/e}:function(n){return n*e},symbol:n}}function Pt(n){var t=n.decimal,e=n.thousands,r=n.grouping,u=n.currency,i=r&&e?function(n,t){for(var u=n.length,i=[],o=0,a=r[0],c=0;u>0&&a>0&&(c+a+1>t&&(a=Math.max(1,t-c)),i.push(n.substring(u-=a,u+a)),!((c+=a+1)>t));)a=r[o=(o+1)%r.length];return i.reverse().join(e)}:y;return function(n){var e=ic.exec(n),r=e[1]||" ",o=e[2]||">",a=e[3]||"-",c=e[4]||"",l=e[5],s=+e[6],f=e[7],h=e[8],g=e[9],p=1,v="",d="",m=!1,y=!0;switch(h&&(h=+h.substring(1)),(l||"0"===r&&"="===o)&&(l=r="0",o="="),g){case"n":f=!0,g="g";break;case"%":p=100,d="%",g="f";break;case"p":p=100,d="%",g="r";break;case"b":case"o":case"x":case"X":"#"===c&&(v="0"+g.toLowerCase());case"c":y=!1;case"d":m=!0,h=0;break;case"s":p=-1,g="r"}"$"===c&&(v=u[0],d=u[1]),"r"!=g||h||(g="g"),null!=h&&("g"==g?h=Math.max(1,Math.min(21,h)):("e"==g||"f"==g)&&(h=Math.max(0,Math.min(20,h)))),g=oc.get(g)||Ut;var M=l&&f;return function(n){var e=d;if(m&&n%1)return"";var u=0>n||0===n&&0>1/n?(n=-n,"-"):"-"===a?"":a;if(0>p){var c=ta.formatPrefix(n,h);n=c.scale(n),e=c.symbol+d}else n*=p;n=g(n,h);var x,b,_=n.lastIndexOf(".");if(0>_){var w=y?n.lastIndexOf("e"):-1;0>w?(x=n,b=""):(x=n.substring(0,w),b=n.substring(w))}else x=n.substring(0,_),b=t+n.substring(_+1);!l&&f&&(x=i(x,1/0));var S=v.length+x.length+b.length+(M?0:u.length),k=s>S?new Array(S=s-S+1).join(r):"";return M&&(x=i(k+x,k.length?s-b.length:1/0)),u+=v,n=x+b,("<"===o?u+n+k:">"===o?k+u+n:"^"===o?k.substring(0,S>>=1)+u+n+k.substring(S):u+(M?n:k+n))+e}}}function Ut(n){return n+""}function jt(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function Ft(n,t,e){function r(t){var e=n(t),r=i(e,1);return r-t>t-e?e:r}function u(e){return t(e=n(new cc(e-1)),1),e}function i(n,e){return t(n=new cc(+n),e),n}function o(n,r,i){var o=u(n),a=[];if(i>1)for(;r>o;)e(o)%i||a.push(new Date(+o)),t(o,1);else for(;r>o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{cc=jt;var r=new jt;return r._=n,o(r,t,e)}finally{cc=Date}}n.floor=n,n.round=r,n.ceil=u,n.offset=i,n.range=o;var c=n.utc=Ht(n);return c.floor=c,c.round=Ht(r),c.ceil=Ht(u),c.offset=Ht(i),c.range=a,n}function Ht(n){return function(t,e){try{cc=jt;var r=new jt;return r._=t,n(r,e)._}finally{cc=Date}}}function Ot(n){function t(n){function t(t){for(var e,u,i,o=[],a=-1,c=0;++aa;){if(r>=l)return-1;if(u=t.charCodeAt(a++),37===u){if(o=t.charAt(a++),i=C[o in sc?t.charAt(a++):o],!i||(r=i(n,e,r))<0)return-1}else if(u!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){_.lastIndex=0;var r=_.exec(t.slice(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){x.lastIndex=0;var r=x.exec(t.slice(e));return r?(n.w=b.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){E.lastIndex=0;var r=E.exec(t.slice(e));return r?(n.m=A.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,e){S.lastIndex=0;var r=S.exec(t.slice(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,r){return e(n,N.c.toString(),t,r)}function c(n,t,r){return e(n,N.x.toString(),t,r)}function l(n,t,r){return e(n,N.X.toString(),t,r)}function s(n,t,e){var r=M.get(t.slice(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var f=n.dateTime,h=n.date,g=n.time,p=n.periods,v=n.days,d=n.shortDays,m=n.months,y=n.shortMonths;t.utc=function(n){function e(n){try{cc=jt;var t=new cc;return t._=n,r(t)}finally{cc=Date}}var r=t(n);return e.parse=function(n){try{cc=jt;var t=r.parse(n);return t&&t._}finally{cc=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=ae;var M=ta.map(),x=Yt(v),b=Zt(v),_=Yt(d),w=Zt(d),S=Yt(m),k=Zt(m),E=Yt(y),A=Zt(y);p.forEach(function(n,t){M.set(n.toLowerCase(),t)});var N={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return y[n.getMonth()]},B:function(n){return m[n.getMonth()]},c:t(f),d:function(n,t){return It(n.getDate(),t,2)},e:function(n,t){return It(n.getDate(),t,2)},H:function(n,t){return It(n.getHours(),t,2)},I:function(n,t){return It(n.getHours()%12||12,t,2)},j:function(n,t){return It(1+ac.dayOfYear(n),t,3)},L:function(n,t){return It(n.getMilliseconds(),t,3)},m:function(n,t){return It(n.getMonth()+1,t,2)},M:function(n,t){return It(n.getMinutes(),t,2)},p:function(n){return p[+(n.getHours()>=12)]},S:function(n,t){return It(n.getSeconds(),t,2)},U:function(n,t){return It(ac.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return It(ac.mondayOfYear(n),t,2)},x:t(h),X:t(g),y:function(n,t){return It(n.getFullYear()%100,t,2)},Y:function(n,t){return It(n.getFullYear()%1e4,t,4)},Z:ie,"%":function(){return"%"}},C={a:r,A:u,b:i,B:o,c:a,d:Qt,e:Qt,H:te,I:te,j:ne,L:ue,m:Kt,M:ee,p:s,S:re,U:Xt,w:Vt,W:$t,x:c,X:l,y:Wt,Y:Bt,Z:Jt,"%":oe};return t}function It(n,t,e){var r=0>n?"-":"",u=(r?-n:n)+"",i=u.length;return r+(e>i?new Array(e-i+1).join(t)+u:u)}function Yt(n){return new RegExp("^(?:"+n.map(ta.requote).join("|")+")","i")}function Zt(n){for(var t=new l,e=-1,r=n.length;++e68?1900:2e3)}function Kt(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function Qt(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function ne(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function te(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function ee(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function re(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function ue(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function ie(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=ga(t)/60|0,u=ga(t)%60;return e+It(r,"0",2)+It(u,"0",2)}function oe(n,t,e){hc.lastIndex=0;var r=hc.exec(t.slice(e,e+1));return r?e+r[0].length:-1}function ae(n){for(var t=n.length,e=-1;++e=0?1:-1,a=o*e,c=Math.cos(t),l=Math.sin(t),s=i*l,f=u*c+s*Math.cos(a),h=s*o*Math.sin(a);yc.add(Math.atan2(h,f)),r=n,u=c,i=l}var t,e,r,u,i;Mc.point=function(o,a){Mc.point=n,r=(t=o)*Da,u=Math.cos(a=(e=a)*Da/2+qa/4),i=Math.sin(a)},Mc.lineEnd=function(){n(t,e)}}function pe(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function ve(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function de(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function me(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function ye(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function Me(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function xe(n){return[Math.atan2(n[1],n[0]),tt(n[2])]}function be(n,t){return ga(n[0]-t[0])a;++a)u.point((e=n[a])[0],e[1]);return void u.lineEnd()}var c=new qe(e,n,null,!0),l=new qe(e,null,c,!1);c.o=l,i.push(c),o.push(l),c=new qe(r,n,null,!1),l=new qe(r,null,c,!0),c.o=l,i.push(c),o.push(l)}}),o.sort(t),ze(i),ze(o),i.length){for(var a=0,c=e,l=o.length;l>a;++a)o[a].e=c=!c;for(var s,f,h=i[0];;){for(var g=h,p=!0;g.v;)if((g=g.n)===h)return;s=g.z,u.lineStart();do{if(g.v=g.o.v=!0,g.e){if(p)for(var a=0,l=s.length;l>a;++a)u.point((f=s[a])[0],f[1]);else r(g.x,g.n.x,1,u);g=g.n}else{if(p){s=g.p.z;for(var a=s.length-1;a>=0;--a)u.point((f=s[a])[0],f[1])}else r(g.x,g.p.x,-1,u);g=g.p}g=g.o,s=g.z,p=!p}while(!g.v);u.lineEnd()}}}function ze(n){if(t=n.length){for(var t,e,r=0,u=n[0];++r0){for(b||(i.polygonStart(),b=!0),i.lineStart();++o1&&2&t&&e.push(e.pop().concat(e.shift())),g.push(e.filter(Te))}var g,p,v,d=t(i),m=u.invert(r[0],r[1]),y={point:o,lineStart:c,lineEnd:l,polygonStart:function(){y.point=s,y.lineStart=f,y.lineEnd=h,g=[],p=[]},polygonEnd:function(){y.point=o,y.lineStart=c,y.lineEnd=l,g=ta.merge(g);var n=Fe(m,p);g.length?(b||(i.polygonStart(),b=!0),Ce(g,De,n,e,i)):n&&(b||(i.polygonStart(),b=!0),i.lineStart(),e(null,null,1,i),i.lineEnd()),b&&(i.polygonEnd(),b=!1),g=p=null},sphere:function(){i.polygonStart(),i.lineStart(),e(null,null,1,i),i.lineEnd(),i.polygonEnd()}},M=Re(),x=t(M),b=!1;return y}}function Te(n){return n.length>1}function Re(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:b,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function De(n,t){return((n=n.x)[0]<0?n[1]-Ra-Ca:Ra-n[1])-((t=t.x)[0]<0?t[1]-Ra-Ca:Ra-t[1])}function Pe(n){var t,e=0/0,r=0/0,u=0/0;return{lineStart:function(){n.lineStart(),t=1},point:function(i,o){var a=i>0?qa:-qa,c=ga(i-e);ga(c-qa)0?Ra:-Ra),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(i,r),t=0):u!==a&&c>=qa&&(ga(e-u)Ca?Math.atan((Math.sin(t)*(i=Math.cos(r))*Math.sin(e)-Math.sin(r)*(u=Math.cos(t))*Math.sin(n))/(u*i*o)):(t+r)/2}function je(n,t,e,r){var u;if(null==n)u=e*Ra,r.point(-qa,u),r.point(0,u),r.point(qa,u),r.point(qa,0),r.point(qa,-u),r.point(0,-u),r.point(-qa,-u),r.point(-qa,0),r.point(-qa,u);else if(ga(n[0]-t[0])>Ca){var i=n[0]a;++a){var l=t[a],s=l.length;if(s)for(var f=l[0],h=f[0],g=f[1]/2+qa/4,p=Math.sin(g),v=Math.cos(g),d=1;;){d===s&&(d=0),n=l[d];var m=n[0],y=n[1]/2+qa/4,M=Math.sin(y),x=Math.cos(y),b=m-h,_=b>=0?1:-1,w=_*b,S=w>qa,k=p*M;if(yc.add(Math.atan2(k*_*Math.sin(w),v*x+k*Math.cos(w))),i+=S?b+_*La:b,S^h>=e^m>=e){var E=de(pe(f),pe(n));Me(E);var A=de(u,E);Me(A);var N=(S^b>=0?-1:1)*tt(A[2]);(r>N||r===N&&(E[0]||E[1]))&&(o+=S^b>=0?1:-1)}if(!d++)break;h=m,p=M,v=x,f=n}}return(-Ca>i||Ca>i&&0>yc)^1&o}function He(n){function t(n,t){return Math.cos(n)*Math.cos(t)>i}function e(n){var e,i,c,l,s;return{lineStart:function(){l=c=!1,s=1},point:function(f,h){var g,p=[f,h],v=t(f,h),d=o?v?0:u(f,h):v?u(f+(0>f?qa:-qa),h):0;if(!e&&(l=c=v)&&n.lineStart(),v!==c&&(g=r(e,p),(be(e,g)||be(p,g))&&(p[0]+=Ca,p[1]+=Ca,v=t(p[0],p[1]))),v!==c)s=0,v?(n.lineStart(),g=r(p,e),n.point(g[0],g[1])):(g=r(e,p),n.point(g[0],g[1]),n.lineEnd()),e=g;else if(a&&e&&o^v){var m;d&i||!(m=r(p,e,!0))||(s=0,o?(n.lineStart(),n.point(m[0][0],m[0][1]),n.point(m[1][0],m[1][1]),n.lineEnd()):(n.point(m[1][0],m[1][1]),n.lineEnd(),n.lineStart(),n.point(m[0][0],m[0][1])))}!v||e&&be(e,p)||n.point(p[0],p[1]),e=p,c=v,i=d},lineEnd:function(){c&&n.lineEnd(),e=null},clean:function(){return s|(l&&c)<<1}}}function r(n,t,e){var r=pe(n),u=pe(t),o=[1,0,0],a=de(r,u),c=ve(a,a),l=a[0],s=c-l*l;if(!s)return!e&&n;var f=i*c/s,h=-i*l/s,g=de(o,a),p=ye(o,f),v=ye(a,h);me(p,v);var d=g,m=ve(p,d),y=ve(d,d),M=m*m-y*(ve(p,p)-1);if(!(0>M)){var x=Math.sqrt(M),b=ye(d,(-m-x)/y);if(me(b,p),b=xe(b),!e)return b;var _,w=n[0],S=t[0],k=n[1],E=t[1];w>S&&(_=w,w=S,S=_);var A=S-w,N=ga(A-qa)A;if(!N&&k>E&&(_=k,k=E,E=_),C?N?k+E>0^b[1]<(ga(b[0]-w)qa^(w<=b[0]&&b[0]<=S)){var z=ye(d,(-m+x)/y);return me(z,p),[b,xe(z)]}}}function u(t,e){var r=o?n:qa-n,u=0;return-r>t?u|=1:t>r&&(u|=2),-r>e?u|=4:e>r&&(u|=8),u}var i=Math.cos(n),o=i>0,a=ga(i)>Ca,c=gr(n,6*Da);return Le(t,e,c,o?[0,-n]:[-qa,n-qa])}function Oe(n,t,e,r){return function(u){var i,o=u.a,a=u.b,c=o.x,l=o.y,s=a.x,f=a.y,h=0,g=1,p=s-c,v=f-l;if(i=n-c,p||!(i>0)){if(i/=p,0>p){if(h>i)return;g>i&&(g=i)}else if(p>0){if(i>g)return;i>h&&(h=i)}if(i=e-c,p||!(0>i)){if(i/=p,0>p){if(i>g)return;i>h&&(h=i)}else if(p>0){if(h>i)return;g>i&&(g=i)}if(i=t-l,v||!(i>0)){if(i/=v,0>v){if(h>i)return;g>i&&(g=i)}else if(v>0){if(i>g)return;i>h&&(h=i)}if(i=r-l,v||!(0>i)){if(i/=v,0>v){if(i>g)return;i>h&&(h=i)}else if(v>0){if(h>i)return;g>i&&(g=i)}return h>0&&(u.a={x:c+h*p,y:l+h*v}),1>g&&(u.b={x:c+g*p,y:l+g*v}),u}}}}}}function Ie(n,t,e,r){function u(r,u){return ga(r[0]-n)0?0:3:ga(r[0]-e)0?2:1:ga(r[1]-t)0?1:0:u>0?3:2}function i(n,t){return o(n.x,t.x)}function o(n,t){var e=u(n,1),r=u(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(a){function c(n){for(var t=0,e=d.length,r=n[1],u=0;e>u;++u)for(var i,o=1,a=d[u],c=a.length,l=a[0];c>o;++o)i=a[o],l[1]<=r?i[1]>r&&Q(l,i,n)>0&&++t:i[1]<=r&&Q(l,i,n)<0&&--t,l=i;return 0!==t}function l(i,a,c,l){var s=0,f=0;if(null==i||(s=u(i,c))!==(f=u(a,c))||o(i,a)<0^c>0){do l.point(0===s||3===s?n:e,s>1?r:t);while((s=(s+c+4)%4)!==f)}else l.point(a[0],a[1])}function s(u,i){return u>=n&&e>=u&&i>=t&&r>=i}function f(n,t){s(n,t)&&a.point(n,t)}function h(){C.point=p,d&&d.push(m=[]),S=!0,w=!1,b=_=0/0}function g(){v&&(p(y,M),x&&w&&A.rejoin(),v.push(A.buffer())),C.point=f,w&&a.lineEnd()}function p(n,t){n=Math.max(-Tc,Math.min(Tc,n)),t=Math.max(-Tc,Math.min(Tc,t));var e=s(n,t);if(d&&m.push([n,t]),S)y=n,M=t,x=e,S=!1,e&&(a.lineStart(),a.point(n,t));else if(e&&w)a.point(n,t);else{var r={a:{x:b,y:_},b:{x:n,y:t}};N(r)?(w||(a.lineStart(),a.point(r.a.x,r.a.y)),a.point(r.b.x,r.b.y),e||a.lineEnd(),k=!1):e&&(a.lineStart(),a.point(n,t),k=!1)}b=n,_=t,w=e}var v,d,m,y,M,x,b,_,w,S,k,E=a,A=Re(),N=Oe(n,t,e,r),C={point:f,lineStart:h,lineEnd:g,polygonStart:function(){a=A,v=[],d=[],k=!0},polygonEnd:function(){a=E,v=ta.merge(v);var t=c([n,r]),e=k&&t,u=v.length;(e||u)&&(a.polygonStart(),e&&(a.lineStart(),l(null,null,1,a),a.lineEnd()),u&&Ce(v,i,t,l,a),a.polygonEnd()),v=d=m=null}};return C}}function Ye(n){var t=0,e=qa/3,r=ir(n),u=r(t,e);return u.parallels=function(n){return arguments.length?r(t=n[0]*qa/180,e=n[1]*qa/180):[t/qa*180,e/qa*180]},u}function Ze(n,t){function e(n,t){var e=Math.sqrt(i-2*u*Math.sin(t))/u;return[e*Math.sin(n*=u),o-e*Math.cos(n)]}var r=Math.sin(n),u=(r+Math.sin(t))/2,i=1+r*(2*u-r),o=Math.sqrt(i)/u;return e.invert=function(n,t){var e=o-t;return[Math.atan2(n,e)/u,tt((i-(n*n+e*e)*u*u)/(2*u))]},e}function Ve(){function n(n,t){Dc+=u*n-r*t,r=n,u=t}var t,e,r,u;Hc.point=function(i,o){Hc.point=n,t=r=i,e=u=o},Hc.lineEnd=function(){n(t,e)}}function Xe(n,t){Pc>n&&(Pc=n),n>jc&&(jc=n),Uc>t&&(Uc=t),t>Fc&&(Fc=t)}function $e(){function n(n,t){o.push("M",n,",",t,i)}function t(n,t){o.push("M",n,",",t),a.point=e}function e(n,t){o.push("L",n,",",t)}function r(){a.point=n}function u(){o.push("Z")}var i=Be(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return i=Be(n),a},result:function(){if(o.length){var n=o.join("");return o=[],n}}};return a}function Be(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function We(n,t){_c+=n,wc+=t,++Sc}function Je(){function n(n,r){var u=n-t,i=r-e,o=Math.sqrt(u*u+i*i);kc+=o*(t+n)/2,Ec+=o*(e+r)/2,Ac+=o,We(t=n,e=r)}var t,e;Ic.point=function(r,u){Ic.point=n,We(t=r,e=u)}}function Ge(){Ic.point=We}function Ke(){function n(n,t){var e=n-r,i=t-u,o=Math.sqrt(e*e+i*i);kc+=o*(r+n)/2,Ec+=o*(u+t)/2,Ac+=o,o=u*n-r*t,Nc+=o*(r+n),Cc+=o*(u+t),zc+=3*o,We(r=n,u=t)}var t,e,r,u;Ic.point=function(i,o){Ic.point=n,We(t=r=i,e=u=o)},Ic.lineEnd=function(){n(t,e)}}function Qe(n){function t(t,e){n.moveTo(t+o,e),n.arc(t,e,o,0,La)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function u(){a.point=t}function i(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:u,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=u,a.point=t},pointRadius:function(n){return o=n,a},result:b};return a}function nr(n){function t(n){return(a?r:e)(n)}function e(t){return rr(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){M=0/0,S.point=i,t.lineStart()}function i(e,r){var i=pe([e,r]),o=n(e,r);u(M,x,y,b,_,w,M=o[0],x=o[1],y=e,b=i[0],_=i[1],w=i[2],a,t),t.point(M,x)}function o(){S.point=e,t.lineEnd()}function c(){r(),S.point=l,S.lineEnd=s}function l(n,t){i(f=n,h=t),g=M,p=x,v=b,d=_,m=w,S.point=i}function s(){u(M,x,y,b,_,w,g,p,f,v,d,m,a,t),S.lineEnd=o,o()}var f,h,g,p,v,d,m,y,M,x,b,_,w,S={point:e,lineStart:r,lineEnd:o,polygonStart:function(){t.polygonStart(),S.lineStart=c +},polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function u(t,e,r,a,c,l,s,f,h,g,p,v,d,m){var y=s-t,M=f-e,x=y*y+M*M;if(x>4*i&&d--){var b=a+g,_=c+p,w=l+v,S=Math.sqrt(b*b+_*_+w*w),k=Math.asin(w/=S),E=ga(ga(w)-1)i||ga((y*z+M*q)/x-.5)>.3||o>a*g+c*p+l*v)&&(u(t,e,r,a,c,l,N,C,E,b/=S,_/=S,w,d,m),m.point(N,C),u(N,C,E,b,_,w,s,f,h,g,p,v,d,m))}}var i=.5,o=Math.cos(30*Da),a=16;return t.precision=function(n){return arguments.length?(a=(i=n*n)>0&&16,t):Math.sqrt(i)},t}function tr(n){var t=nr(function(t,e){return n([t*Pa,e*Pa])});return function(n){return or(t(n))}}function er(n){this.stream=n}function rr(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function ur(n){return ir(function(){return n})()}function ir(n){function t(n){return n=a(n[0]*Da,n[1]*Da),[n[0]*h+c,l-n[1]*h]}function e(n){return n=a.invert((n[0]-c)/h,(l-n[1])/h),n&&[n[0]*Pa,n[1]*Pa]}function r(){a=Ae(o=lr(m,M,x),i);var n=i(v,d);return c=g-n[0]*h,l=p+n[1]*h,u()}function u(){return s&&(s.valid=!1,s=null),t}var i,o,a,c,l,s,f=nr(function(n,t){return n=i(n,t),[n[0]*h+c,l-n[1]*h]}),h=150,g=480,p=250,v=0,d=0,m=0,M=0,x=0,b=Lc,_=y,w=null,S=null;return t.stream=function(n){return s&&(s.valid=!1),s=or(b(o,f(_(n)))),s.valid=!0,s},t.clipAngle=function(n){return arguments.length?(b=null==n?(w=n,Lc):He((w=+n)*Da),u()):w},t.clipExtent=function(n){return arguments.length?(S=n,_=n?Ie(n[0][0],n[0][1],n[1][0],n[1][1]):y,u()):S},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(g=+n[0],p=+n[1],r()):[g,p]},t.center=function(n){return arguments.length?(v=n[0]%360*Da,d=n[1]%360*Da,r()):[v*Pa,d*Pa]},t.rotate=function(n){return arguments.length?(m=n[0]%360*Da,M=n[1]%360*Da,x=n.length>2?n[2]%360*Da:0,r()):[m*Pa,M*Pa,x*Pa]},ta.rebind(t,f,"precision"),function(){return i=n.apply(this,arguments),t.invert=i.invert&&e,r()}}function or(n){return rr(n,function(t,e){n.point(t*Da,e*Da)})}function ar(n,t){return[n,t]}function cr(n,t){return[n>qa?n-La:-qa>n?n+La:n,t]}function lr(n,t,e){return n?t||e?Ae(fr(n),hr(t,e)):fr(n):t||e?hr(t,e):cr}function sr(n){return function(t,e){return t+=n,[t>qa?t-La:-qa>t?t+La:t,e]}}function fr(n){var t=sr(n);return t.invert=sr(-n),t}function hr(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,l=Math.sin(t),s=l*r+a*u;return[Math.atan2(c*i-s*o,a*r-l*u),tt(s*i+c*o)]}var r=Math.cos(n),u=Math.sin(n),i=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,l=Math.sin(t),s=l*i-c*o;return[Math.atan2(c*i+l*o,a*r+s*u),tt(s*r-a*u)]},e}function gr(n,t){var e=Math.cos(n),r=Math.sin(n);return function(u,i,o,a){var c=o*t;null!=u?(u=pr(e,u),i=pr(e,i),(o>0?i>u:u>i)&&(u+=o*La)):(u=n+o*La,i=n-.5*c);for(var l,s=u;o>0?s>i:i>s;s-=c)a.point((l=xe([e,-r*Math.cos(s),-r*Math.sin(s)]))[0],l[1])}}function pr(n,t){var e=pe(t);e[0]-=n,Me(e);var r=nt(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-Ca)%(2*Math.PI)}function vr(n,t,e){var r=ta.range(n,t-Ca,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function dr(n,t,e){var r=ta.range(n,t-Ca,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function mr(n){return n.source}function yr(n){return n.target}function Mr(n,t,e,r){var u=Math.cos(t),i=Math.sin(t),o=Math.cos(r),a=Math.sin(r),c=u*Math.cos(n),l=u*Math.sin(n),s=o*Math.cos(e),f=o*Math.sin(e),h=2*Math.asin(Math.sqrt(it(r-t)+u*o*it(e-n))),g=1/Math.sin(h),p=h?function(n){var t=Math.sin(n*=h)*g,e=Math.sin(h-n)*g,r=e*c+t*s,u=e*l+t*f,o=e*i+t*a;return[Math.atan2(u,r)*Pa,Math.atan2(o,Math.sqrt(r*r+u*u))*Pa]}:function(){return[n*Pa,t*Pa]};return p.distance=h,p}function xr(){function n(n,u){var i=Math.sin(u*=Da),o=Math.cos(u),a=ga((n*=Da)-t),c=Math.cos(a);Yc+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*i-e*o*c)*a),e*i+r*o*c),t=n,e=i,r=o}var t,e,r;Zc.point=function(u,i){t=u*Da,e=Math.sin(i*=Da),r=Math.cos(i),Zc.point=n},Zc.lineEnd=function(){Zc.point=Zc.lineEnd=b}}function br(n,t){function e(t,e){var r=Math.cos(t),u=Math.cos(e),i=n(r*u);return[i*u*Math.sin(t),i*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),u=t(r),i=Math.sin(u),o=Math.cos(u);return[Math.atan2(n*i,r*o),Math.asin(r&&e*i/r)]},e}function _r(n,t){function e(n,t){o>0?-Ra+Ca>t&&(t=-Ra+Ca):t>Ra-Ca&&(t=Ra-Ca);var e=o/Math.pow(u(t),i);return[e*Math.sin(i*n),o-e*Math.cos(i*n)]}var r=Math.cos(n),u=function(n){return Math.tan(qa/4+n/2)},i=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(u(t)/u(n)),o=r*Math.pow(u(n),i)/i;return i?(e.invert=function(n,t){var e=o-t,r=K(i)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/i,2*Math.atan(Math.pow(o/r,1/i))-Ra]},e):Sr}function wr(n,t){function e(n,t){var e=i-t;return[e*Math.sin(u*n),i-e*Math.cos(u*n)]}var r=Math.cos(n),u=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),i=r/u+n;return ga(u)u;u++){for(;r>1&&Q(n[e[r-2]],n[e[r-1]],n[u])<=0;)--r;e[r++]=u}return e.slice(0,r)}function zr(n,t){return n[0]-t[0]||n[1]-t[1]}function qr(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function Lr(n,t,e,r){var u=n[0],i=e[0],o=t[0]-u,a=r[0]-i,c=n[1],l=e[1],s=t[1]-c,f=r[1]-l,h=(a*(c-l)-f*(u-i))/(f*o-a*s);return[u+h*o,c+h*s]}function Tr(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function Rr(){tu(this),this.edge=this.site=this.circle=null}function Dr(n){var t=el.pop()||new Rr;return t.site=n,t}function Pr(n){Xr(n),Qc.remove(n),el.push(n),tu(n)}function Ur(n){var t=n.circle,e=t.x,r=t.cy,u={x:e,y:r},i=n.P,o=n.N,a=[n];Pr(n);for(var c=i;c.circle&&ga(e-c.circle.x)s;++s)l=a[s],c=a[s-1],Kr(l.edge,c.site,l.site,u);c=a[0],l=a[f-1],l.edge=Jr(c.site,l.site,null,u),Vr(c),Vr(l)}function jr(n){for(var t,e,r,u,i=n.x,o=n.y,a=Qc._;a;)if(r=Fr(a,o)-i,r>Ca)a=a.L;else{if(u=i-Hr(a,o),!(u>Ca)){r>-Ca?(t=a.P,e=a):u>-Ca?(t=a,e=a.N):t=e=a;break}if(!a.R){t=a;break}a=a.R}var c=Dr(n);if(Qc.insert(t,c),t||e){if(t===e)return Xr(t),e=Dr(t.site),Qc.insert(c,e),c.edge=e.edge=Jr(t.site,c.site),Vr(t),void Vr(e);if(!e)return void(c.edge=Jr(t.site,c.site));Xr(t),Xr(e);var l=t.site,s=l.x,f=l.y,h=n.x-s,g=n.y-f,p=e.site,v=p.x-s,d=p.y-f,m=2*(h*d-g*v),y=h*h+g*g,M=v*v+d*d,x={x:(d*y-g*M)/m+s,y:(h*M-v*y)/m+f};Kr(e.edge,l,p,x),c.edge=Jr(l,n,null,x),e.edge=Jr(n,p,null,x),Vr(t),Vr(e)}}function Fr(n,t){var e=n.site,r=e.x,u=e.y,i=u-t;if(!i)return r;var o=n.P;if(!o)return-1/0;e=o.site;var a=e.x,c=e.y,l=c-t;if(!l)return a;var s=a-r,f=1/i-1/l,h=s/l;return f?(-h+Math.sqrt(h*h-2*f*(s*s/(-2*l)-c+l/2+u-i/2)))/f+r:(r+a)/2}function Hr(n,t){var e=n.N;if(e)return Fr(e,t);var r=n.site;return r.y===t?r.x:1/0}function Or(n){this.site=n,this.edges=[]}function Ir(n){for(var t,e,r,u,i,o,a,c,l,s,f=n[0][0],h=n[1][0],g=n[0][1],p=n[1][1],v=Kc,d=v.length;d--;)if(i=v[d],i&&i.prepare())for(a=i.edges,c=a.length,o=0;c>o;)s=a[o].end(),r=s.x,u=s.y,l=a[++o%c].start(),t=l.x,e=l.y,(ga(r-t)>Ca||ga(u-e)>Ca)&&(a.splice(o,0,new Qr(Gr(i.site,s,ga(r-f)Ca?{x:f,y:ga(t-f)Ca?{x:ga(e-p)Ca?{x:h,y:ga(t-h)Ca?{x:ga(e-g)=-za)){var g=c*c+l*l,p=s*s+f*f,v=(f*g-l*p)/h,d=(c*p-s*g)/h,f=d+a,m=rl.pop()||new Zr;m.arc=n,m.site=u,m.x=v+o,m.y=f+Math.sqrt(v*v+d*d),m.cy=f,n.circle=m;for(var y=null,M=tl._;M;)if(m.yd||d>=a)return;if(h>p){if(i){if(i.y>=l)return}else i={x:d,y:c};e={x:d,y:l}}else{if(i){if(i.yr||r>1)if(h>p){if(i){if(i.y>=l)return}else i={x:(c-u)/r,y:c};e={x:(l-u)/r,y:l}}else{if(i){if(i.yg){if(i){if(i.x>=a)return}else i={x:o,y:r*o+u};e={x:a,y:r*a+u}}else{if(i){if(i.xi||f>o||r>h||u>g)){if(p=n.point){var p,v=t-n.x,d=e-n.y,m=v*v+d*d;if(c>m){var y=Math.sqrt(c=m);r=t-y,u=e-y,i=t+y,o=e+y,a=p}}for(var M=n.nodes,x=.5*(s+h),b=.5*(f+g),_=t>=x,w=e>=b,S=w<<1|_,k=S+4;k>S;++S)if(n=M[3&S])switch(3&S){case 0:l(n,s,f,x,b);break;case 1:l(n,x,f,h,b);break;case 2:l(n,s,b,x,g);break;case 3:l(n,x,b,h,g)}}}(n,r,u,i,o),a}function gu(n,t){n=ta.rgb(n),t=ta.rgb(t);var e=n.r,r=n.g,u=n.b,i=t.r-e,o=t.g-r,a=t.b-u;return function(n){return"#"+xt(Math.round(e+i*n))+xt(Math.round(r+o*n))+xt(Math.round(u+a*n))}}function pu(n,t){var e,r={},u={};for(e in n)e in t?r[e]=mu(n[e],t[e]):u[e]=n[e];for(e in t)e in n||(u[e]=t[e]);return function(n){for(e in r)u[e]=r[e](n);return u}}function vu(n,t){return n=+n,t=+t,function(e){return n*(1-e)+t*e}}function du(n,t){var e,r,u,i=il.lastIndex=ol.lastIndex=0,o=-1,a=[],c=[];for(n+="",t+="";(e=il.exec(n))&&(r=ol.exec(t));)(u=r.index)>i&&(u=t.slice(i,u),a[o]?a[o]+=u:a[++o]=u),(e=e[0])===(r=r[0])?a[o]?a[o]+=r:a[++o]=r:(a[++o]=null,c.push({i:o,x:vu(e,r)})),i=ol.lastIndex;return ir;++r)a[(e=c[r]).i]=e.x(n);return a.join("")})}function mu(n,t){for(var e,r=ta.interpolators.length;--r>=0&&!(e=ta.interpolators[r](n,t)););return e}function yu(n,t){var e,r=[],u=[],i=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a>e;++e)r.push(mu(n[e],t[e]));for(;i>e;++e)u[e]=n[e];for(;o>e;++e)u[e]=t[e];return function(n){for(e=0;a>e;++e)u[e]=r[e](n);return u}}function Mu(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function xu(n){return function(t){return 1-n(1-t)}}function bu(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function _u(n){return n*n}function wu(n){return n*n*n}function Su(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function ku(n){return function(t){return Math.pow(t,n)}}function Eu(n){return 1-Math.cos(n*Ra)}function Au(n){return Math.pow(2,10*(n-1))}function Nu(n){return 1-Math.sqrt(1-n*n)}function Cu(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/La*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*La/t)}}function zu(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function qu(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Lu(n,t){n=ta.hcl(n),t=ta.hcl(t);var e=n.h,r=n.c,u=n.l,i=t.h-e,o=t.c-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.c:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return st(e+i*n,r+o*n,u+a*n)+""}}function Tu(n,t){n=ta.hsl(n),t=ta.hsl(t);var e=n.h,r=n.s,u=n.l,i=t.h-e,o=t.s-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.s:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return ct(e+i*n,r+o*n,u+a*n)+""}}function Ru(n,t){n=ta.lab(n),t=ta.lab(t);var e=n.l,r=n.a,u=n.b,i=t.l-e,o=t.a-r,a=t.b-u;return function(n){return ht(e+i*n,r+o*n,u+a*n)+""}}function Du(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function Pu(n){var t=[n.a,n.b],e=[n.c,n.d],r=ju(t),u=Uu(t,e),i=ju(Fu(e,t,-u))||0;t[0]*e[1]180?s+=360:s-l>180&&(l+=360),u.push({i:r.push(r.pop()+"rotate(",null,")")-2,x:vu(l,s)})):s&&r.push(r.pop()+"rotate("+s+")"),f!=h?u.push({i:r.push(r.pop()+"skewX(",null,")")-2,x:vu(f,h)}):h&&r.push(r.pop()+"skewX("+h+")"),g[0]!=p[0]||g[1]!=p[1]?(e=r.push(r.pop()+"scale(",null,",",null,")"),u.push({i:e-4,x:vu(g[0],p[0])},{i:e-2,x:vu(g[1],p[1])})):(1!=p[0]||1!=p[1])&&r.push(r.pop()+"scale("+p+")"),e=u.length,function(n){for(var t,i=-1;++i=0;)e.push(u[r])}function Qu(n,t){for(var e=[n],r=[];null!=(n=e.pop());)if(r.push(n),(i=n.children)&&(u=i.length))for(var u,i,o=-1;++oe;++e)(t=n[e][1])>u&&(r=e,u=t);return r}function si(n){return n.reduce(fi,0)}function fi(n,t){return n+t[1]}function hi(n,t){return gi(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function gi(n,t){for(var e=-1,r=+n[0],u=(n[1]-r)/t,i=[];++e<=t;)i[e]=u*e+r;return i}function pi(n){return[ta.min(n),ta.max(n)]}function vi(n,t){return n.value-t.value}function di(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function mi(n,t){n._pack_next=t,t._pack_prev=n}function yi(n,t){var e=t.x-n.x,r=t.y-n.y,u=n.r+t.r;return.999*u*u>e*e+r*r}function Mi(n){function t(n){s=Math.min(n.x-n.r,s),f=Math.max(n.x+n.r,f),h=Math.min(n.y-n.r,h),g=Math.max(n.y+n.r,g)}if((e=n.children)&&(l=e.length)){var e,r,u,i,o,a,c,l,s=1/0,f=-1/0,h=1/0,g=-1/0;if(e.forEach(xi),r=e[0],r.x=-r.r,r.y=0,t(r),l>1&&(u=e[1],u.x=u.r,u.y=0,t(u),l>2))for(i=e[2],wi(r,u,i),t(i),di(r,i),r._pack_prev=i,di(i,u),u=r._pack_next,o=3;l>o;o++){wi(r,u,i=e[o]);var p=0,v=1,d=1;for(a=u._pack_next;a!==u;a=a._pack_next,v++)if(yi(a,i)){p=1;break}if(1==p)for(c=r._pack_prev;c!==a._pack_prev&&!yi(c,i);c=c._pack_prev,d++);p?(d>v||v==d&&u.ro;o++)i=e[o],i.x-=m,i.y-=y,M=Math.max(M,i.r+Math.sqrt(i.x*i.x+i.y*i.y));n.r=M,e.forEach(bi)}}function xi(n){n._pack_next=n._pack_prev=n}function bi(n){delete n._pack_next,delete n._pack_prev}function _i(n,t,e,r){var u=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,u)for(var i=-1,o=u.length;++i=0;)t=u[i],t.z+=e,t.m+=e,e+=t.s+(r+=t.c)}function Ci(n,t,e){return n.a.parent===t.parent?n.a:e}function zi(n){return 1+ta.max(n,function(n){return n.y})}function qi(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function Li(n){var t=n.children;return t&&t.length?Li(t[0]):n}function Ti(n){var t,e=n.children;return e&&(t=e.length)?Ti(e[t-1]):n}function Ri(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function Di(n,t){var e=n.x+t[3],r=n.y+t[0],u=n.dx-t[1]-t[3],i=n.dy-t[0]-t[2];return 0>u&&(e+=u/2,u=0),0>i&&(r+=i/2,i=0),{x:e,y:r,dx:u,dy:i}}function Pi(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Ui(n){return n.rangeExtent?n.rangeExtent():Pi(n.range())}function ji(n,t,e,r){var u=e(n[0],n[1]),i=r(t[0],t[1]);return function(n){return i(u(n))}}function Fi(n,t){var e,r=0,u=n.length-1,i=n[r],o=n[u];return i>o&&(e=r,r=u,u=e,e=i,i=o,o=e),n[r]=t.floor(i),n[u]=t.ceil(o),n}function Hi(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:ml}function Oi(n,t,e,r){var u=[],i=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]2?Oi:ji,c=r?Iu:Ou;return o=u(n,t,c,e),a=u(t,n,c,mu),i}function i(n){return o(n)}var o,a;return i.invert=function(n){return a(n)},i.domain=function(t){return arguments.length?(n=t.map(Number),u()):n},i.range=function(n){return arguments.length?(t=n,u()):t},i.rangeRound=function(n){return i.range(n).interpolate(Du)},i.clamp=function(n){return arguments.length?(r=n,u()):r},i.interpolate=function(n){return arguments.length?(e=n,u()):e},i.ticks=function(t){return Xi(n,t)},i.tickFormat=function(t,e){return $i(n,t,e)},i.nice=function(t){return Zi(n,t),u()},i.copy=function(){return Ii(n,t,e,r)},u()}function Yi(n,t){return ta.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Zi(n,t){return Fi(n,Hi(Vi(n,t)[2]))}function Vi(n,t){null==t&&(t=10);var e=Pi(n),r=e[1]-e[0],u=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),i=t/r*u;return.15>=i?u*=10:.35>=i?u*=5:.75>=i&&(u*=2),e[0]=Math.ceil(e[0]/u)*u,e[1]=Math.floor(e[1]/u)*u+.5*u,e[2]=u,e}function Xi(n,t){return ta.range.apply(ta,Vi(n,t))}function $i(n,t,e){var r=Vi(n,t);if(e){var u=ic.exec(e);if(u.shift(),"s"===u[8]){var i=ta.formatPrefix(Math.max(ga(r[0]),ga(r[1])));return u[7]||(u[7]="."+Bi(i.scale(r[2]))),u[8]="f",e=ta.format(u.join("")),function(n){return e(i.scale(n))+i.symbol}}u[7]||(u[7]="."+Wi(u[8],r)),e=u.join("")}else e=",."+Bi(r[2])+"f";return ta.format(e)}function Bi(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function Wi(n,t){var e=Bi(t[2]);return n in yl?Math.abs(e-Bi(Math.max(ga(t[0]),ga(t[1]))))+ +("e"!==n):e-2*("%"===n)}function Ji(n,t,e,r){function u(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function i(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(u(t))}return o.invert=function(t){return i(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(u)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(u)),o):t},o.nice=function(){var t=Fi(r.map(u),e?Math:xl);return n.domain(t),r=t.map(i),o},o.ticks=function(){var n=Pi(r),o=[],a=n[0],c=n[1],l=Math.floor(u(a)),s=Math.ceil(u(c)),f=t%1?2:t;if(isFinite(s-l)){if(e){for(;s>l;l++)for(var h=1;f>h;h++)o.push(i(l)*h);o.push(i(l))}else for(o.push(i(l));l++0;h--)o.push(i(l)*h);for(l=0;o[l]c;s--);o=o.slice(l,s)}return o},o.tickFormat=function(n,t){if(!arguments.length)return Ml;arguments.length<2?t=Ml:"function"!=typeof t&&(t=ta.format(t));var r,a=Math.max(.1,n/o.ticks().length),c=e?(r=1e-12,Math.ceil):(r=-1e-12,Math.floor);return function(n){return n/i(c(u(n)+r))<=a?t(n):""}},o.copy=function(){return Ji(n.copy(),t,e,r)},Yi(o,n)}function Gi(n,t,e){function r(t){return n(u(t))}var u=Ki(t),i=Ki(1/t);return r.invert=function(t){return i(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(u)),r):e},r.ticks=function(n){return Xi(e,n)},r.tickFormat=function(n,t){return $i(e,n,t)},r.nice=function(n){return r.domain(Zi(e,n))},r.exponent=function(o){return arguments.length?(u=Ki(t=o),i=Ki(1/t),n.domain(e.map(u)),r):t},r.copy=function(){return Gi(n.copy(),t,e)},Yi(r,n)}function Ki(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function Qi(n,t){function e(e){return i[((u.get(e)||("range"===t.t?u.set(e,n.push(e)):0/0))-1)%i.length]}function r(t,e){return ta.range(n.length).map(function(n){return t+e*n})}var u,i,o;return e.domain=function(r){if(!arguments.length)return n;n=[],u=new l;for(var i,o=-1,a=r.length;++oe?[0/0,0/0]:[e>0?a[e-1]:n[0],et?0/0:t/i+n,[t,t+1/i]},r.copy=function(){return to(n,t,e)},u()}function eo(n,t){function e(e){return e>=e?t[ta.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return eo(n,t)},e}function ro(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Xi(n,t)},t.tickFormat=function(t,e){return $i(n,t,e)},t.copy=function(){return ro(n)},t}function uo(){return 0}function io(n){return n.innerRadius}function oo(n){return n.outerRadius}function ao(n){return n.startAngle}function co(n){return n.endAngle}function lo(n){return n&&n.padAngle}function so(n,t,e,r){return(n-e)*t-(t-r)*n>0?0:1}function fo(n,t,e,r,u){var i=n[0]-t[0],o=n[1]-t[1],a=(u?r:-r)/Math.sqrt(i*i+o*o),c=a*o,l=-a*i,s=n[0]+c,f=n[1]+l,h=t[0]+c,g=t[1]+l,p=(s+h)/2,v=(f+g)/2,d=h-s,m=g-f,y=d*d+m*m,M=e-r,x=s*g-h*f,b=(0>m?-1:1)*Math.sqrt(M*M*y-x*x),_=(x*m-d*b)/y,w=(-x*d-m*b)/y,S=(x*m+d*b)/y,k=(-x*d+m*b)/y,E=_-p,A=w-v,N=S-p,C=k-v;return E*E+A*A>N*N+C*C&&(_=S,w=k),[[_-c,w-l],[_*e/M,w*e/M]]}function ho(n){function t(t){function o(){l.push("M",i(n(s),a))}for(var c,l=[],s=[],f=-1,h=t.length,g=Et(e),p=Et(r);++f1&&u.push("H",r[0]),u.join("")}function mo(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t1){a=t[1],i=n[c],c++,r+="C"+(u[0]+o[0])+","+(u[1]+o[1])+","+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1];for(var l=2;l9&&(u=3*t/Math.sqrt(u),o[a]=u*e,o[a+1]=u*r));for(a=-1;++a<=c;)u=(n[Math.min(c,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),i.push([u||0,o[a]*u||0]);return i}function To(n){return n.length<3?go(n):n[0]+_o(n,Lo(n))}function Ro(n){for(var t,e,r,u=-1,i=n.length;++ur)return s();var u=i[i.active];u&&(--i.count,delete i[i.active],u.event&&u.event.interrupt.call(n,n.__data__,u.index)),i.active=r,o.event&&o.event.start.call(n,n.__data__,t),o.tween.forEach(function(e,r){(r=r.call(n,n.__data__,t))&&v.push(r)}),h=o.ease,f=o.duration,ta.timer(function(){return p.c=l(e||1)?Ne:l,1},0,a)}function l(e){if(i.active!==r)return 1;for(var u=e/f,a=h(u),c=v.length;c>0;)v[--c].call(n,a);return u>=1?(o.event&&o.event.end.call(n,n.__data__,t),s()):void 0}function s(){return--i.count?delete i[r]:delete n[e],1}var f,h,g=o.delay,p=ec,v=[];return p.t=g+a,u>=g?c(u-g):void(p.c=c)},0,a)}}function Bo(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate("+(isFinite(r)?r:e(n))+",0)"})}function Wo(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate(0,"+(isFinite(r)?r:e(n))+")"})}function Jo(n){return n.toISOString()}function Go(n,t,e){function r(t){return n(t)}function u(n,e){var r=n[1]-n[0],u=r/e,i=ta.bisect(Vl,u);return i==Vl.length?[t.year,Vi(n.map(function(n){return n/31536e6}),e)[2]]:i?t[u/Vl[i-1]1?{floor:function(t){for(;e(t=n.floor(t));)t=Ko(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=Ko(+t+1);return t}}:n))},r.ticks=function(n,t){var e=Pi(r.domain()),i=null==n?u(e,10):"number"==typeof n?u(e,n):!n.range&&[{range:n},t];return i&&(n=i[0],t=i[1]),n.range(e[0],Ko(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return Go(n.copy(),t,e)},Yi(r,n)}function Ko(n){return new Date(n)}function Qo(n){return JSON.parse(n.responseText)}function na(n){var t=ua.createRange();return t.selectNode(ua.body),t.createContextualFragment(n.responseText)}var ta={version:"3.5.5"},ea=[].slice,ra=function(n){return ea.call(n)},ua=this.document;if(ua)try{ra(ua.documentElement.childNodes)[0].nodeType}catch(ia){ra=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}if(Date.now||(Date.now=function(){return+new Date}),ua)try{ua.createElement("DIV").style.setProperty("opacity",0,"")}catch(oa){var aa=this.Element.prototype,ca=aa.setAttribute,la=aa.setAttributeNS,sa=this.CSSStyleDeclaration.prototype,fa=sa.setProperty;aa.setAttribute=function(n,t){ca.call(this,n,t+"")},aa.setAttributeNS=function(n,t,e){la.call(this,n,t,e+"")},sa.setProperty=function(n,t,e){fa.call(this,n,t+"",e)}}ta.ascending=e,ta.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:0/0},ta.min=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u=r){e=r;break}for(;++ur&&(e=r)}else{for(;++u=r){e=r;break}for(;++ur&&(e=r)}return e},ta.max=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u=r){e=r;break}for(;++ue&&(e=r)}else{for(;++u=r){e=r;break}for(;++ue&&(e=r)}return e},ta.extent=function(n,t){var e,r,u,i=-1,o=n.length;if(1===arguments.length){for(;++i=r){e=u=r;break}for(;++ir&&(e=r),r>u&&(u=r))}else{for(;++i=r){e=u=r;break}for(;++ir&&(e=r),r>u&&(u=r))}return[e,u]},ta.sum=function(n,t){var e,r=0,i=n.length,o=-1;if(1===arguments.length)for(;++o1?c/(s-1):void 0},ta.deviation=function(){var n=ta.variance.apply(this,arguments);return n?Math.sqrt(n):n};var ha=i(e);ta.bisectLeft=ha.left,ta.bisect=ta.bisectRight=ha.right,ta.bisector=function(n){return i(1===n.length?function(t,r){return e(n(t),r)}:n)},ta.shuffle=function(n,t,e){(i=arguments.length)<3&&(e=n.length,2>i&&(t=0));for(var r,u,i=e-t;i;)u=Math.random()*i--|0,r=n[i+t],n[i+t]=n[u+t],n[u+t]=r;return n},ta.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},ta.pairs=function(n){for(var t,e=0,r=n.length-1,u=n[0],i=new Array(0>r?0:r);r>e;)i[e]=[t=u,u=n[++e]];return i},ta.zip=function(){if(!(r=arguments.length))return[];for(var n=-1,t=ta.min(arguments,o),e=new Array(t);++n=0;)for(r=n[u],t=r.length;--t>=0;)e[--o]=r[t];return e};var ga=Math.abs;ta.range=function(n,t,e){if(arguments.length<3&&(e=1,arguments.length<2&&(t=n,n=0)),(t-n)/e===1/0)throw new Error("infinite range");var r,u=[],i=a(ga(e)),o=-1;if(n*=i,t*=i,e*=i,0>e)for(;(r=n+e*++o)>t;)u.push(r/i);else for(;(r=n+e*++o)=i.length)return r?r.call(u,o):e?o.sort(e):o;for(var c,s,f,h,g=-1,p=o.length,v=i[a++],d=new l;++g=i.length)return n;var r=[],u=o[e++];return n.forEach(function(n,u){r.push({key:n,values:t(u,e)})}),u?r.sort(function(n,t){return u(n.key,t.key)}):r}var e,r,u={},i=[],o=[];return u.map=function(t,e){return n(e,t,0)},u.entries=function(e){return t(n(ta.map,e,0),0)},u.key=function(n){return i.push(n),u},u.sortKeys=function(n){return o[i.length-1]=n,u},u.sortValues=function(n){return e=n,u},u.rollup=function(n){return r=n,u},u},ta.set=function(n){var t=new m;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},c(m,{has:h,add:function(n){return this._[s(n+="")]=!0,n},remove:g,values:p,size:v,empty:d,forEach:function(n){for(var t in this._)n.call(this,f(t))}}),ta.behavior={},ta.rebind=function(n,t){for(var e,r=1,u=arguments.length;++r=0&&(r=n.slice(e+1),n=n.slice(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},ta.event=null,ta.requote=function(n){return n.replace(ma,"\\$&")};var ma=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,ya={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},Ma=function(n,t){return t.querySelector(n)},xa=function(n,t){return t.querySelectorAll(n)},ba=function(n,t){var e=n.matches||n[x(n,"matchesSelector")];return(ba=function(n,t){return e.call(n,t)})(n,t)};"function"==typeof Sizzle&&(Ma=function(n,t){return Sizzle(n,t)[0]||null},xa=Sizzle,ba=Sizzle.matchesSelector),ta.selection=function(){return ta.select(ua.documentElement)};var _a=ta.selection.prototype=[];_a.select=function(n){var t,e,r,u,i=[];n=N(n);for(var o=-1,a=this.length;++o=0&&(e=n.slice(0,t),n=n.slice(t+1)),wa.hasOwnProperty(e)?{space:wa[e],local:n}:n}},_a.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=ta.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(z(t,n[t]));return this}return this.each(z(n,t))},_a.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=T(n)).length,u=-1;if(t=e.classList){for(;++uu){if("string"!=typeof n){2>u&&(e="");for(r in n)this.each(P(r,n[r],e));return this}if(2>u){var i=this.node();return t(i).getComputedStyle(i,null).getPropertyValue(n)}r=""}return this.each(P(n,e,r))},_a.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(U(t,n[t]));return this}return this.each(U(n,t))},_a.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},_a.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},_a.append=function(n){return n=j(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},_a.insert=function(n,t){return n=j(n),t=N(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},_a.remove=function(){return this.each(F)},_a.data=function(n,t){function e(n,e){var r,u,i,o=n.length,f=e.length,h=Math.min(o,f),g=new Array(f),p=new Array(f),v=new Array(o);if(t){var d,m=new l,y=new Array(o);for(r=-1;++rr;++r)p[r]=H(e[r]);for(;o>r;++r)v[r]=n[r]}p.update=g,p.parentNode=g.parentNode=v.parentNode=n.parentNode,a.push(p),c.push(g),s.push(v)}var r,u,i=-1,o=this.length;if(!arguments.length){for(n=new Array(o=(r=this[0]).length);++ii;i++){u.push(t=[]),t.parentNode=(e=this[i]).parentNode;for(var a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return A(u)},_a.order=function(){for(var n=-1,t=this.length;++n=0;)(e=r[u])&&(i&&i!==e.nextSibling&&i.parentNode.insertBefore(e,i),i=e);return this},_a.sort=function(n){n=I.apply(this,arguments);for(var t=-1,e=this.length;++tn;n++)for(var e=this[n],r=0,u=e.length;u>r;r++){var i=e[r];if(i)return i}return null},_a.size=function(){var n=0;return Y(this,function(){++n}),n};var Sa=[];ta.selection.enter=Z,ta.selection.enter.prototype=Sa,Sa.append=_a.append,Sa.empty=_a.empty,Sa.node=_a.node,Sa.call=_a.call,Sa.size=_a.size,Sa.select=function(n){for(var t,e,r,u,i,o=[],a=-1,c=this.length;++ar){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(X(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(X(n,t,e))};var ka=ta.map({mouseenter:"mouseover",mouseleave:"mouseout"});ua&&ka.forEach(function(n){"on"+n in ua&&ka.remove(n)});var Ea,Aa=0;ta.mouse=function(n){return J(n,k())};var Na=this.navigator&&/WebKit/.test(this.navigator.userAgent)?-1:0;ta.touch=function(n,t,e){if(arguments.length<3&&(e=t,t=k().changedTouches),t)for(var r,u=0,i=t.length;i>u;++u)if((r=t[u]).identifier===e)return J(n,r)},ta.behavior.drag=function(){function n(){this.on("mousedown.drag",i).on("touchstart.drag",o)}function e(n,t,e,i,o){return function(){function a(){var n,e,r=t(h,v);r&&(n=r[0]-M[0],e=r[1]-M[1],p|=n|e,M=r,g({type:"drag",x:r[0]+l[0],y:r[1]+l[1],dx:n,dy:e}))}function c(){t(h,v)&&(m.on(i+d,null).on(o+d,null),y(p&&ta.event.target===f),g({type:"dragend"}))}var l,s=this,f=ta.event.target,h=s.parentNode,g=r.of(s,arguments),p=0,v=n(),d=".drag"+(null==v?"":"-"+v),m=ta.select(e(f)).on(i+d,a).on(o+d,c),y=W(f),M=t(h,v);u?(l=u.apply(s,arguments),l=[l.x-M[0],l.y-M[1]]):l=[0,0],g({type:"dragstart"})}}var r=E(n,"drag","dragstart","dragend"),u=null,i=e(b,ta.mouse,t,"mousemove","mouseup"),o=e(G,ta.touch,y,"touchmove","touchend");return n.origin=function(t){return arguments.length?(u=t,n):u},ta.rebind(n,r,"on")},ta.touches=function(n,t){return arguments.length<2&&(t=k().touches),t?ra(t).map(function(t){var e=J(n,t);return e.identifier=t.identifier,e}):[]};var Ca=1e-6,za=Ca*Ca,qa=Math.PI,La=2*qa,Ta=La-Ca,Ra=qa/2,Da=qa/180,Pa=180/qa,Ua=Math.SQRT2,ja=2,Fa=4;ta.interpolateZoom=function(n,t){function e(n){var t=n*y;if(m){var e=rt(v),o=i/(ja*h)*(e*ut(Ua*t+v)-et(v));return[r+o*l,u+o*s,i*e/rt(Ua*t+v)]}return[r+n*l,u+n*s,i*Math.exp(Ua*t)]}var r=n[0],u=n[1],i=n[2],o=t[0],a=t[1],c=t[2],l=o-r,s=a-u,f=l*l+s*s,h=Math.sqrt(f),g=(c*c-i*i+Fa*f)/(2*i*ja*h),p=(c*c-i*i-Fa*f)/(2*c*ja*h),v=Math.log(Math.sqrt(g*g+1)-g),d=Math.log(Math.sqrt(p*p+1)-p),m=d-v,y=(m||Math.log(c/i))/Ua;return e.duration=1e3*y,e},ta.behavior.zoom=function(){function n(n){n.on(q,f).on(Oa+".zoom",g).on("dblclick.zoom",p).on(R,h)}function e(n){return[(n[0]-k.x)/k.k,(n[1]-k.y)/k.k]}function r(n){return[n[0]*k.k+k.x,n[1]*k.k+k.y]}function u(n){k.k=Math.max(N[0],Math.min(N[1],n))}function i(n,t){t=r(t),k.x+=n[0]-t[0],k.y+=n[1]-t[1]}function o(t,e,r,o){t.__chart__={x:k.x,y:k.y,k:k.k},u(Math.pow(2,o)),i(d=e,r),t=ta.select(t),C>0&&(t=t.transition().duration(C)),t.call(n.event)}function a(){b&&b.domain(x.range().map(function(n){return(n-k.x)/k.k}).map(x.invert)),w&&w.domain(_.range().map(function(n){return(n-k.y)/k.k}).map(_.invert))}function c(n){z++||n({type:"zoomstart"})}function l(n){a(),n({type:"zoom",scale:k.k,translate:[k.x,k.y]})}function s(n){--z||n({type:"zoomend"}),d=null}function f(){function n(){f=1,i(ta.mouse(u),g),l(a)}function r(){h.on(L,null).on(T,null),p(f&&ta.event.target===o),s(a)}var u=this,o=ta.event.target,a=D.of(u,arguments),f=0,h=ta.select(t(u)).on(L,n).on(T,r),g=e(ta.mouse(u)),p=W(u);Dl.call(u),c(a)}function h(){function n(){var n=ta.touches(p);return g=k.k,n.forEach(function(n){n.identifier in d&&(d[n.identifier]=e(n))}),n}function t(){var t=ta.event.target;ta.select(t).on(x,r).on(b,a),_.push(t);for(var e=ta.event.changedTouches,u=0,i=e.length;i>u;++u)d[e[u].identifier]=null;var c=n(),l=Date.now();if(1===c.length){if(500>l-M){var s=c[0];o(p,s,d[s.identifier],Math.floor(Math.log(k.k)/Math.LN2)+1),S()}M=l}else if(c.length>1){var s=c[0],f=c[1],h=s[0]-f[0],g=s[1]-f[1];m=h*h+g*g}}function r(){var n,t,e,r,o=ta.touches(p);Dl.call(p);for(var a=0,c=o.length;c>a;++a,r=null)if(e=o[a],r=d[e.identifier]){if(t)break;n=e,t=r}if(r){var s=(s=e[0]-n[0])*s+(s=e[1]-n[1])*s,f=m&&Math.sqrt(s/m);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+r[0])/2,(t[1]+r[1])/2],u(f*g)}M=null,i(n,t),l(v)}function a(){if(ta.event.touches.length){for(var t=ta.event.changedTouches,e=0,r=t.length;r>e;++e)delete d[t[e].identifier];for(var u in d)return void n()}ta.selectAll(_).on(y,null),w.on(q,f).on(R,h),E(),s(v)}var g,p=this,v=D.of(p,arguments),d={},m=0,y=".zoom-"+ta.event.changedTouches[0].identifier,x="touchmove"+y,b="touchend"+y,_=[],w=ta.select(p),E=W(p);t(),c(v),w.on(q,null).on(R,t)}function g(){var n=D.of(this,arguments);y?clearTimeout(y):(v=e(d=m||ta.mouse(this)),Dl.call(this),c(n)),y=setTimeout(function(){y=null,s(n)},50),S(),u(Math.pow(2,.002*Ha())*k.k),i(d,v),l(n)}function p(){var n=ta.mouse(this),t=Math.log(k.k)/Math.LN2;o(this,n,e(n),ta.event.shiftKey?Math.ceil(t)-1:Math.floor(t)+1)}var v,d,m,y,M,x,b,_,w,k={x:0,y:0,k:1},A=[960,500],N=Ia,C=250,z=0,q="mousedown.zoom",L="mousemove.zoom",T="mouseup.zoom",R="touchstart.zoom",D=E(n,"zoomstart","zoom","zoomend");return Oa||(Oa="onwheel"in ua?(Ha=function(){return-ta.event.deltaY*(ta.event.deltaMode?120:1)},"wheel"):"onmousewheel"in ua?(Ha=function(){return ta.event.wheelDelta},"mousewheel"):(Ha=function(){return-ta.event.detail},"MozMousePixelScroll")),n.event=function(n){n.each(function(){var n=D.of(this,arguments),t=k;Tl?ta.select(this).transition().each("start.zoom",function(){k=this.__chart__||{x:0,y:0,k:1},c(n)}).tween("zoom:zoom",function(){var e=A[0],r=A[1],u=d?d[0]:e/2,i=d?d[1]:r/2,o=ta.interpolateZoom([(u-k.x)/k.k,(i-k.y)/k.k,e/k.k],[(u-t.x)/t.k,(i-t.y)/t.k,e/t.k]);return function(t){var r=o(t),a=e/r[2];this.__chart__=k={x:u-r[0]*a,y:i-r[1]*a,k:a},l(n)}}).each("interrupt.zoom",function(){s(n)}).each("end.zoom",function(){s(n)}):(this.__chart__=k,c(n),l(n),s(n))})},n.translate=function(t){return arguments.length?(k={x:+t[0],y:+t[1],k:k.k},a(),n):[k.x,k.y]},n.scale=function(t){return arguments.length?(k={x:k.x,y:k.y,k:+t},a(),n):k.k},n.scaleExtent=function(t){return arguments.length?(N=null==t?Ia:[+t[0],+t[1]],n):N},n.center=function(t){return arguments.length?(m=t&&[+t[0],+t[1]],n):m},n.size=function(t){return arguments.length?(A=t&&[+t[0],+t[1]],n):A},n.duration=function(t){return arguments.length?(C=+t,n):C},n.x=function(t){return arguments.length?(b=t,x=t.copy(),k={x:0,y:0,k:1},n):b},n.y=function(t){return arguments.length?(w=t,_=t.copy(),k={x:0,y:0,k:1},n):w},ta.rebind(n,D,"on")};var Ha,Oa,Ia=[0,1/0];ta.color=ot,ot.prototype.toString=function(){return this.rgb()+""},ta.hsl=at;var Ya=at.prototype=new ot;Ya.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),new at(this.h,this.s,this.l/n)},Ya.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new at(this.h,this.s,n*this.l)},Ya.rgb=function(){return ct(this.h,this.s,this.l)},ta.hcl=lt;var Za=lt.prototype=new ot;Za.brighter=function(n){return new lt(this.h,this.c,Math.min(100,this.l+Va*(arguments.length?n:1)))},Za.darker=function(n){return new lt(this.h,this.c,Math.max(0,this.l-Va*(arguments.length?n:1)))},Za.rgb=function(){return st(this.h,this.c,this.l).rgb()},ta.lab=ft;var Va=18,Xa=.95047,$a=1,Ba=1.08883,Wa=ft.prototype=new ot;Wa.brighter=function(n){return new ft(Math.min(100,this.l+Va*(arguments.length?n:1)),this.a,this.b)},Wa.darker=function(n){return new ft(Math.max(0,this.l-Va*(arguments.length?n:1)),this.a,this.b)},Wa.rgb=function(){return ht(this.l,this.a,this.b)},ta.rgb=mt;var Ja=mt.prototype=new ot;Ja.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,u=30;return t||e||r?(t&&u>t&&(t=u),e&&u>e&&(e=u),r&&u>r&&(r=u),new mt(Math.min(255,t/n),Math.min(255,e/n),Math.min(255,r/n))):new mt(u,u,u)},Ja.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new mt(n*this.r,n*this.g,n*this.b)},Ja.hsl=function(){return _t(this.r,this.g,this.b)},Ja.toString=function(){return"#"+xt(this.r)+xt(this.g)+xt(this.b)};var Ga=ta.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});Ga.forEach(function(n,t){Ga.set(n,yt(t))}),ta.functor=Et,ta.xhr=At(y),ta.dsv=function(n,t){function e(n,e,i){arguments.length<3&&(i=e,e=null);var o=Nt(n,t,null==e?r:u(e),i);return o.row=function(n){return arguments.length?o.response(null==(e=n)?r:u(n)):e},o}function r(n){return e.parse(n.responseText)}function u(n){return function(t){return e.parse(t.responseText,n)}}function i(t){return t.map(o).join(n)}function o(n){return a.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var a=new RegExp('["'+n+"\n]"),c=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var u=new Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(u(n),e)}:u})},e.parseRows=function(n,t){function e(){if(s>=l)return o;if(u)return u=!1,i;var t=s;if(34===n.charCodeAt(t)){for(var e=t;e++s;){var r=n.charCodeAt(s++),a=1;if(10===r)u=!0;else if(13===r)u=!0,10===n.charCodeAt(s)&&(++s,++a);else if(r!==c)continue;return n.slice(t,s-a)}return n.slice(t)}for(var r,u,i={},o={},a=[],l=n.length,s=0,f=0;(r=e())!==o;){for(var h=[];r!==i&&r!==o;)h.push(r),r=e();t&&null==(h=t(h,f++))||a.push(h)}return a},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new m,u=[];return t.forEach(function(n){for(var t in n)r.has(t)||u.push(r.add(t))}),[u.map(o).join(n)].concat(t.map(function(t){return u.map(function(n){return o(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(i).join("\n")},e},ta.csv=ta.dsv(",","text/csv"),ta.tsv=ta.dsv(" ","text/tab-separated-values");var Ka,Qa,nc,tc,ec,rc=this[x(this,"requestAnimationFrame")]||function(n){setTimeout(n,17)};ta.timer=function(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var u=e+t,i={c:n,t:u,f:!1,n:null};Qa?Qa.n=i:Ka=i,Qa=i,nc||(tc=clearTimeout(tc),nc=1,rc(qt))},ta.timer.flush=function(){Lt(),Tt()},ta.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var uc=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(Dt);ta.formatPrefix=function(n,t){var e=0;return n&&(0>n&&(n*=-1),t&&(n=ta.round(n,Rt(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((e-1)/3)))),uc[8+e/3]};var ic=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,oc=ta.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=ta.round(n,Rt(n,t))).toFixed(Math.max(0,Math.min(20,Rt(n*(1+1e-15),t))))}}),ac=ta.time={},cc=Date;jt.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){lc.setUTCDate.apply(this._,arguments)},setDay:function(){lc.setUTCDay.apply(this._,arguments)},setFullYear:function(){lc.setUTCFullYear.apply(this._,arguments)},setHours:function(){lc.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){lc.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){lc.setUTCMinutes.apply(this._,arguments)},setMonth:function(){lc.setUTCMonth.apply(this._,arguments)},setSeconds:function(){lc.setUTCSeconds.apply(this._,arguments)},setTime:function(){lc.setTime.apply(this._,arguments)}};var lc=Date.prototype;ac.year=Ft(function(n){return n=ac.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),ac.years=ac.year.range,ac.years.utc=ac.year.utc.range,ac.day=Ft(function(n){var t=new cc(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),ac.days=ac.day.range,ac.days.utc=ac.day.utc.range,ac.dayOfYear=function(n){var t=ac.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(n,t){t=7-t;var e=ac[n]=Ft(function(n){return(n=ac.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=ac.year(n).getDay();return Math.floor((ac.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});ac[n+"s"]=e.range,ac[n+"s"].utc=e.utc.range,ac[n+"OfYear"]=function(n){var e=ac.year(n).getDay();return Math.floor((ac.dayOfYear(n)+(e+t)%7)/7)}}),ac.week=ac.sunday,ac.weeks=ac.sunday.range,ac.weeks.utc=ac.sunday.utc.range,ac.weekOfYear=ac.sundayOfYear;var sc={"-":"",_:" ",0:"0"},fc=/^\s*\d+/,hc=/^%/;ta.locale=function(n){return{numberFormat:Pt(n),timeFormat:Ot(n)}};var gc=ta.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});ta.format=gc.numberFormat,ta.geo={},ce.prototype={s:0,t:0,add:function(n){le(n,this.t,pc),le(pc.s,this.s,this),this.s?this.t+=pc.t:this.s=pc.t +},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var pc=new ce;ta.geo.stream=function(n,t){n&&vc.hasOwnProperty(n.type)?vc[n.type](n,t):se(n,t)};var vc={Feature:function(n,t){se(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,u=e.length;++rn?4*qa+n:n,Mc.lineStart=Mc.lineEnd=Mc.point=b}};ta.geo.bounds=function(){function n(n,t){M.push(x=[s=n,h=n]),f>t&&(f=t),t>g&&(g=t)}function t(t,e){var r=pe([t*Da,e*Da]);if(m){var u=de(m,r),i=[u[1],-u[0],0],o=de(i,u);Me(o),o=xe(o);var c=t-p,l=c>0?1:-1,v=o[0]*Pa*l,d=ga(c)>180;if(d^(v>l*p&&l*t>v)){var y=o[1]*Pa;y>g&&(g=y)}else if(v=(v+360)%360-180,d^(v>l*p&&l*t>v)){var y=-o[1]*Pa;f>y&&(f=y)}else f>e&&(f=e),e>g&&(g=e);d?p>t?a(s,t)>a(s,h)&&(h=t):a(t,h)>a(s,h)&&(s=t):h>=s?(s>t&&(s=t),t>h&&(h=t)):t>p?a(s,t)>a(s,h)&&(h=t):a(t,h)>a(s,h)&&(s=t)}else n(t,e);m=r,p=t}function e(){b.point=t}function r(){x[0]=s,x[1]=h,b.point=n,m=null}function u(n,e){if(m){var r=n-p;y+=ga(r)>180?r+(r>0?360:-360):r}else v=n,d=e;Mc.point(n,e),t(n,e)}function i(){Mc.lineStart()}function o(){u(v,d),Mc.lineEnd(),ga(y)>Ca&&(s=-(h=180)),x[0]=s,x[1]=h,m=null}function a(n,t){return(t-=n)<0?t+360:t}function c(n,t){return n[0]-t[0]}function l(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:nyc?(s=-(h=180),f=-(g=90)):y>Ca?g=90:-Ca>y&&(f=-90),x[0]=s,x[1]=h}};return function(n){g=h=-(s=f=1/0),M=[],ta.geo.stream(n,b);var t=M.length;if(t){M.sort(c);for(var e,r=1,u=M[0],i=[u];t>r;++r)e=M[r],l(e[0],u)||l(e[1],u)?(a(u[0],e[1])>a(u[0],u[1])&&(u[1]=e[1]),a(e[0],u[1])>a(u[0],u[1])&&(u[0]=e[0])):i.push(u=e);for(var o,e,p=-1/0,t=i.length-1,r=0,u=i[t];t>=r;u=e,++r)e=i[r],(o=a(u[1],e[0]))>p&&(p=o,s=e[0],h=u[1])}return M=x=null,1/0===s||1/0===f?[[0/0,0/0],[0/0,0/0]]:[[s,f],[h,g]]}}(),ta.geo.centroid=function(n){xc=bc=_c=wc=Sc=kc=Ec=Ac=Nc=Cc=zc=0,ta.geo.stream(n,qc);var t=Nc,e=Cc,r=zc,u=t*t+e*e+r*r;return za>u&&(t=kc,e=Ec,r=Ac,Ca>bc&&(t=_c,e=wc,r=Sc),u=t*t+e*e+r*r,za>u)?[0/0,0/0]:[Math.atan2(e,t)*Pa,tt(r/Math.sqrt(u))*Pa]};var xc,bc,_c,wc,Sc,kc,Ec,Ac,Nc,Cc,zc,qc={sphere:b,point:_e,lineStart:Se,lineEnd:ke,polygonStart:function(){qc.lineStart=Ee},polygonEnd:function(){qc.lineStart=Se}},Lc=Le(Ne,Pe,je,[-qa,-qa/2]),Tc=1e9;ta.geo.clipExtent=function(){var n,t,e,r,u,i,o={stream:function(n){return u&&(u.valid=!1),u=i(n),u.valid=!0,u},extent:function(a){return arguments.length?(i=Ie(n=+a[0][0],t=+a[0][1],e=+a[1][0],r=+a[1][1]),u&&(u.valid=!1,u=null),o):[[n,t],[e,r]]}};return o.extent([[0,0],[960,500]])},(ta.geo.conicEqualArea=function(){return Ye(Ze)}).raw=Ze,ta.geo.albers=function(){return ta.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},ta.geo.albersUsa=function(){function n(n){var i=n[0],o=n[1];return t=null,e(i,o),t||(r(i,o),t)||u(i,o),t}var t,e,r,u,i=ta.geo.albers(),o=ta.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),a=ta.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),c={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=i.scale(),e=i.translate(),r=(n[0]-e[0])/t,u=(n[1]-e[1])/t;return(u>=.12&&.234>u&&r>=-.425&&-.214>r?o:u>=.166&&.234>u&&r>=-.214&&-.115>r?a:i).invert(n)},n.stream=function(n){var t=i.stream(n),e=o.stream(n),r=a.stream(n);return{point:function(n,u){t.point(n,u),e.point(n,u),r.point(n,u)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(i.precision(t),o.precision(t),a.precision(t),n):i.precision()},n.scale=function(t){return arguments.length?(i.scale(t),o.scale(.35*t),a.scale(t),n.translate(i.translate())):i.scale()},n.translate=function(t){if(!arguments.length)return i.translate();var l=i.scale(),s=+t[0],f=+t[1];return e=i.translate(t).clipExtent([[s-.455*l,f-.238*l],[s+.455*l,f+.238*l]]).stream(c).point,r=o.translate([s-.307*l,f+.201*l]).clipExtent([[s-.425*l+Ca,f+.12*l+Ca],[s-.214*l-Ca,f+.234*l-Ca]]).stream(c).point,u=a.translate([s-.205*l,f+.212*l]).clipExtent([[s-.214*l+Ca,f+.166*l+Ca],[s-.115*l-Ca,f+.234*l-Ca]]).stream(c).point,n},n.scale(1070)};var Rc,Dc,Pc,Uc,jc,Fc,Hc={point:b,lineStart:b,lineEnd:b,polygonStart:function(){Dc=0,Hc.lineStart=Ve},polygonEnd:function(){Hc.lineStart=Hc.lineEnd=Hc.point=b,Rc+=ga(Dc/2)}},Oc={point:Xe,lineStart:b,lineEnd:b,polygonStart:b,polygonEnd:b},Ic={point:We,lineStart:Je,lineEnd:Ge,polygonStart:function(){Ic.lineStart=Ke},polygonEnd:function(){Ic.point=We,Ic.lineStart=Je,Ic.lineEnd=Ge}};ta.geo.path=function(){function n(n){return n&&("function"==typeof a&&i.pointRadius(+a.apply(this,arguments)),o&&o.valid||(o=u(i)),ta.geo.stream(n,o)),i.result()}function t(){return o=null,n}var e,r,u,i,o,a=4.5;return n.area=function(n){return Rc=0,ta.geo.stream(n,u(Hc)),Rc},n.centroid=function(n){return _c=wc=Sc=kc=Ec=Ac=Nc=Cc=zc=0,ta.geo.stream(n,u(Ic)),zc?[Nc/zc,Cc/zc]:Ac?[kc/Ac,Ec/Ac]:Sc?[_c/Sc,wc/Sc]:[0/0,0/0]},n.bounds=function(n){return jc=Fc=-(Pc=Uc=1/0),ta.geo.stream(n,u(Oc)),[[Pc,Uc],[jc,Fc]]},n.projection=function(n){return arguments.length?(u=(e=n)?n.stream||tr(n):y,t()):e},n.context=function(n){return arguments.length?(i=null==(r=n)?new $e:new Qe(n),"function"!=typeof a&&i.pointRadius(a),t()):r},n.pointRadius=function(t){return arguments.length?(a="function"==typeof t?t:(i.pointRadius(+t),+t),n):a},n.projection(ta.geo.albersUsa()).context(null)},ta.geo.transform=function(n){return{stream:function(t){var e=new er(t);for(var r in n)e[r]=n[r];return e}}},er.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},ta.geo.projection=ur,ta.geo.projectionMutator=ir,(ta.geo.equirectangular=function(){return ur(ar)}).raw=ar.invert=ar,ta.geo.rotation=function(n){function t(t){return t=n(t[0]*Da,t[1]*Da),t[0]*=Pa,t[1]*=Pa,t}return n=lr(n[0]%360*Da,n[1]*Da,n.length>2?n[2]*Da:0),t.invert=function(t){return t=n.invert(t[0]*Da,t[1]*Da),t[0]*=Pa,t[1]*=Pa,t},t},cr.invert=ar,ta.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=lr(-n[0]*Da,-n[1]*Da,0).invert,u=[];return e(null,null,1,{point:function(n,e){u.push(n=t(n,e)),n[0]*=Pa,n[1]*=Pa}}),{type:"Polygon",coordinates:[u]}}var t,e,r=[0,0],u=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=gr((t=+r)*Da,u*Da),n):t},n.precision=function(r){return arguments.length?(e=gr(t*Da,(u=+r)*Da),n):u},n.angle(90)},ta.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Da,u=n[1]*Da,i=t[1]*Da,o=Math.sin(r),a=Math.cos(r),c=Math.sin(u),l=Math.cos(u),s=Math.sin(i),f=Math.cos(i);return Math.atan2(Math.sqrt((e=f*o)*e+(e=l*s-c*f*a)*e),c*s+l*f*a)},ta.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return ta.range(Math.ceil(i/d)*d,u,d).map(h).concat(ta.range(Math.ceil(l/m)*m,c,m).map(g)).concat(ta.range(Math.ceil(r/p)*p,e,p).filter(function(n){return ga(n%d)>Ca}).map(s)).concat(ta.range(Math.ceil(a/v)*v,o,v).filter(function(n){return ga(n%m)>Ca}).map(f))}var e,r,u,i,o,a,c,l,s,f,h,g,p=10,v=p,d=90,m=360,y=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(i).concat(g(c).slice(1),h(u).reverse().slice(1),g(l).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(i=+t[0][0],u=+t[1][0],l=+t[0][1],c=+t[1][1],i>u&&(t=i,i=u,u=t),l>c&&(t=l,l=c,c=t),n.precision(y)):[[i,l],[u,c]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],a=+t[0][1],o=+t[1][1],r>e&&(t=r,r=e,e=t),a>o&&(t=a,a=o,o=t),n.precision(y)):[[r,a],[e,o]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(d=+t[0],m=+t[1],n):[d,m]},n.minorStep=function(t){return arguments.length?(p=+t[0],v=+t[1],n):[p,v]},n.precision=function(t){return arguments.length?(y=+t,s=vr(a,o,90),f=dr(r,e,y),h=vr(l,c,90),g=dr(i,u,y),n):y},n.majorExtent([[-180,-90+Ca],[180,90-Ca]]).minorExtent([[-180,-80-Ca],[180,80+Ca]])},ta.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||u.apply(this,arguments)]}}var t,e,r=mr,u=yr;return n.distance=function(){return ta.geo.distance(t||r.apply(this,arguments),e||u.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(u=t,e="function"==typeof t?null:t,n):u},n.precision=function(){return arguments.length?n:0},n},ta.geo.interpolate=function(n,t){return Mr(n[0]*Da,n[1]*Da,t[0]*Da,t[1]*Da)},ta.geo.length=function(n){return Yc=0,ta.geo.stream(n,Zc),Yc};var Yc,Zc={sphere:b,point:b,lineStart:xr,lineEnd:b,polygonStart:b,polygonEnd:b},Vc=br(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(ta.geo.azimuthalEqualArea=function(){return ur(Vc)}).raw=Vc;var Xc=br(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},y);(ta.geo.azimuthalEquidistant=function(){return ur(Xc)}).raw=Xc,(ta.geo.conicConformal=function(){return Ye(_r)}).raw=_r,(ta.geo.conicEquidistant=function(){return Ye(wr)}).raw=wr;var $c=br(function(n){return 1/n},Math.atan);(ta.geo.gnomonic=function(){return ur($c)}).raw=$c,Sr.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Ra]},(ta.geo.mercator=function(){return kr(Sr)}).raw=Sr;var Bc=br(function(){return 1},Math.asin);(ta.geo.orthographic=function(){return ur(Bc)}).raw=Bc;var Wc=br(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(ta.geo.stereographic=function(){return ur(Wc)}).raw=Wc,Er.invert=function(n,t){return[-t,2*Math.atan(Math.exp(n))-Ra]},(ta.geo.transverseMercator=function(){var n=kr(Er),t=n.center,e=n.rotate;return n.center=function(n){return n?t([-n[1],n[0]]):(n=t(),[n[1],-n[0]])},n.rotate=function(n){return n?e([n[0],n[1],n.length>2?n[2]+90:90]):(n=e(),[n[0],n[1],n[2]-90])},e([0,0,90])}).raw=Er,ta.geom={},ta.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,u=Et(e),i=Et(r),o=n.length,a=[],c=[];for(t=0;o>t;t++)a.push([+u.call(this,n[t],t),+i.call(this,n[t],t),t]);for(a.sort(zr),t=0;o>t;t++)c.push([a[t][0],-a[t][1]]);var l=Cr(a),s=Cr(c),f=s[0]===l[0],h=s[s.length-1]===l[l.length-1],g=[];for(t=l.length-1;t>=0;--t)g.push(n[a[l[t]][2]]);for(t=+f;t=r&&l.x<=i&&l.y>=u&&l.y<=o?[[r,o],[i,o],[i,u],[r,u]]:[];s.point=n[a]}),t}function e(n){return n.map(function(n,t){return{x:Math.round(i(n,t)/Ca)*Ca,y:Math.round(o(n,t)/Ca)*Ca,i:t}})}var r=Ar,u=Nr,i=r,o=u,a=ul;return n?t(n):(t.links=function(n){return iu(e(n)).edges.filter(function(n){return n.l&&n.r}).map(function(t){return{source:n[t.l.i],target:n[t.r.i]}})},t.triangles=function(n){var t=[];return iu(e(n)).cells.forEach(function(e,r){for(var u,i,o=e.site,a=e.edges.sort(Yr),c=-1,l=a.length,s=a[l-1].edge,f=s.l===o?s.r:s.l;++c=l,h=r>=s,g=h<<1|f;n.leaf=!1,n=n.nodes[g]||(n.nodes[g]=su()),f?u=l:a=l,h?o=s:c=s,i(n,t,e,r,u,o,a,c)}var s,f,h,g,p,v,d,m,y,M=Et(a),x=Et(c);if(null!=t)v=t,d=e,m=r,y=u;else if(m=y=-(v=d=1/0),f=[],h=[],p=n.length,o)for(g=0;p>g;++g)s=n[g],s.xm&&(m=s.x),s.y>y&&(y=s.y),f.push(s.x),h.push(s.y);else for(g=0;p>g;++g){var b=+M(s=n[g],g),_=+x(s,g);v>b&&(v=b),d>_&&(d=_),b>m&&(m=b),_>y&&(y=_),f.push(b),h.push(_)}var w=m-v,S=y-d;w>S?y=d+w:m=v+S;var k=su();if(k.add=function(n){i(k,n,+M(n,++g),+x(n,g),v,d,m,y)},k.visit=function(n){fu(n,k,v,d,m,y)},k.find=function(n){return hu(k,n[0],n[1],v,d,m,y)},g=-1,null==t){for(;++g=0?n.slice(0,t):n,r=t>=0?n.slice(t+1):"in";return e=cl.get(e)||al,r=ll.get(r)||y,Mu(r(e.apply(null,ea.call(arguments,1))))},ta.interpolateHcl=Lu,ta.interpolateHsl=Tu,ta.interpolateLab=Ru,ta.interpolateRound=Du,ta.transform=function(n){var t=ua.createElementNS(ta.ns.prefix.svg,"g");return(ta.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new Pu(e?e.matrix:sl)})(n)},Pu.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var sl={a:1,b:0,c:0,d:1,e:0,f:0};ta.interpolateTransform=Hu,ta.layout={},ta.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++ea*a/d){if(p>c){var l=t.charge/c;n.px-=i*l,n.py-=o*l}return!0}if(t.point&&c&&p>c){var l=t.pointCharge/c;n.px-=i*l,n.py-=o*l}}return!t.charge}}function t(n){n.px=ta.event.x,n.py=ta.event.y,a.resume()}var e,r,u,i,o,a={},c=ta.dispatch("start","tick","end"),l=[1,1],s=.9,f=fl,h=hl,g=-30,p=gl,v=.1,d=.64,m=[],M=[];return a.tick=function(){if((r*=.99)<.005)return c.end({type:"end",alpha:r=0}),!0;var t,e,a,f,h,p,d,y,x,b=m.length,_=M.length;for(e=0;_>e;++e)a=M[e],f=a.source,h=a.target,y=h.x-f.x,x=h.y-f.y,(p=y*y+x*x)&&(p=r*i[e]*((p=Math.sqrt(p))-u[e])/p,y*=p,x*=p,h.x-=y*(d=f.weight/(h.weight+f.weight)),h.y-=x*d,f.x+=y*(d=1-d),f.y+=x*d);if((d=r*v)&&(y=l[0]/2,x=l[1]/2,e=-1,d))for(;++e0?n:0:n>0&&(c.start({type:"start",alpha:r=n}),ta.timer(a.tick)),a):r},a.start=function(){function n(n,r){if(!e){for(e=new Array(c),a=0;c>a;++a)e[a]=[];for(a=0;s>a;++a){var u=M[a];e[u.source.index].push(u.target),e[u.target.index].push(u.source)}}for(var i,o=e[t],a=-1,l=o.length;++at;++t)(r=m[t]).index=t,r.weight=0;for(t=0;s>t;++t)r=M[t],"number"==typeof r.source&&(r.source=m[r.source]),"number"==typeof r.target&&(r.target=m[r.target]),++r.source.weight,++r.target.weight;for(t=0;c>t;++t)r=m[t],isNaN(r.x)&&(r.x=n("x",p)),isNaN(r.y)&&(r.y=n("y",v)),isNaN(r.px)&&(r.px=r.x),isNaN(r.py)&&(r.py=r.y);if(u=[],"function"==typeof f)for(t=0;s>t;++t)u[t]=+f.call(this,M[t],t);else for(t=0;s>t;++t)u[t]=f;if(i=[],"function"==typeof h)for(t=0;s>t;++t)i[t]=+h.call(this,M[t],t);else for(t=0;s>t;++t)i[t]=h;if(o=[],"function"==typeof g)for(t=0;c>t;++t)o[t]=+g.call(this,m[t],t);else for(t=0;c>t;++t)o[t]=g;return a.resume()},a.resume=function(){return a.alpha(.1)},a.stop=function(){return a.alpha(0)},a.drag=function(){return e||(e=ta.behavior.drag().origin(y).on("dragstart.force",Xu).on("drag.force",t).on("dragend.force",$u)),arguments.length?void this.on("mouseover.force",Bu).on("mouseout.force",Wu).call(e):e},ta.rebind(a,c,"on")};var fl=20,hl=1,gl=1/0;ta.layout.hierarchy=function(){function n(u){var i,o=[u],a=[];for(u.depth=0;null!=(i=o.pop());)if(a.push(i),(l=e.call(n,i,i.depth))&&(c=l.length)){for(var c,l,s;--c>=0;)o.push(s=l[c]),s.parent=i,s.depth=i.depth+1;r&&(i.value=0),i.children=l}else r&&(i.value=+r.call(n,i,i.depth)||0),delete i.children;return Qu(u,function(n){var e,u;t&&(e=n.children)&&e.sort(t),r&&(u=n.parent)&&(u.value+=n.value)}),a}var t=ei,e=ni,r=ti;return n.sort=function(e){return arguments.length?(t=e,n):t},n.children=function(t){return arguments.length?(e=t,n):e},n.value=function(t){return arguments.length?(r=t,n):r},n.revalue=function(t){return r&&(Ku(t,function(n){n.children&&(n.value=0)}),Qu(t,function(t){var e;t.children||(t.value=+r.call(n,t,t.depth)||0),(e=t.parent)&&(e.value+=t.value)})),t},n},ta.layout.partition=function(){function n(t,e,r,u){var i=t.children;if(t.x=e,t.y=t.depth*u,t.dx=r,t.dy=u,i&&(o=i.length)){var o,a,c,l=-1;for(r=t.value?r/t.value:0;++lf?-1:1),p=(f-c*g)/ta.sum(l),v=ta.range(c),d=[];return null!=e&&v.sort(e===pl?function(n,t){return l[t]-l[n]}:function(n,t){return e(o[n],o[t])}),v.forEach(function(n){d[n]={data:o[n],value:a=l[n],startAngle:s,endAngle:s+=a*p+g,padAngle:h}}),d}var t=Number,e=pl,r=0,u=La,i=0;return n.value=function(e){return arguments.length?(t=e,n):t},n.sort=function(t){return arguments.length?(e=t,n):e},n.startAngle=function(t){return arguments.length?(r=t,n):r},n.endAngle=function(t){return arguments.length?(u=t,n):u},n.padAngle=function(t){return arguments.length?(i=t,n):i},n};var pl={};ta.layout.stack=function(){function n(a,c){if(!(h=a.length))return a;var l=a.map(function(e,r){return t.call(n,e,r)}),s=l.map(function(t){return t.map(function(t,e){return[i.call(n,t,e),o.call(n,t,e)]})}),f=e.call(n,s,c);l=ta.permute(l,f),s=ta.permute(s,f);var h,g,p,v,d=r.call(n,s,c),m=l[0].length;for(p=0;m>p;++p)for(u.call(n,l[0][p],v=d[p],s[0][p][1]),g=1;h>g;++g)u.call(n,l[g][p],v+=s[g-1][p][1],s[g][p][1]);return a}var t=y,e=ai,r=ci,u=oi,i=ui,o=ii;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:vl.get(t)||ai,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:dl.get(t)||ci,n):r},n.x=function(t){return arguments.length?(i=t,n):i},n.y=function(t){return arguments.length?(o=t,n):o},n.out=function(t){return arguments.length?(u=t,n):u},n};var vl=ta.map({"inside-out":function(n){var t,e,r=n.length,u=n.map(li),i=n.map(si),o=ta.range(r).sort(function(n,t){return u[n]-u[t]}),a=0,c=0,l=[],s=[];for(t=0;r>t;++t)e=o[t],c>a?(a+=i[e],l.push(e)):(c+=i[e],s.push(e));return s.reverse().concat(l)},reverse:function(n){return ta.range(n.length).reverse()},"default":ai}),dl=ta.map({silhouette:function(n){var t,e,r,u=n.length,i=n[0].length,o=[],a=0,c=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];r>a&&(a=r),o.push(r)}for(e=0;i>e;++e)c[e]=(a-o[e])/2;return c},wiggle:function(n){var t,e,r,u,i,o,a,c,l,s=n.length,f=n[0],h=f.length,g=[];for(g[0]=c=l=0,e=1;h>e;++e){for(t=0,u=0;s>t;++t)u+=n[t][e][1];for(t=0,i=0,a=f[e][0]-f[e-1][0];s>t;++t){for(r=0,o=(n[t][e][1]-n[t][e-1][1])/(2*a);t>r;++r)o+=(n[r][e][1]-n[r][e-1][1])/a;i+=o*n[t][e][1]}g[e]=c-=u?i/u*a:0,l>c&&(l=c)}for(e=0;h>e;++e)g[e]-=l;return g},expand:function(n){var t,e,r,u=n.length,i=n[0].length,o=1/u,a=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];if(r)for(t=0;u>t;t++)n[t][e][1]/=r;else for(t=0;u>t;t++)n[t][e][1]=o}for(e=0;i>e;++e)a[e]=0;return a},zero:ci});ta.layout.histogram=function(){function n(n,i){for(var o,a,c=[],l=n.map(e,this),s=r.call(this,l,i),f=u.call(this,s,l,i),i=-1,h=l.length,g=f.length-1,p=t?1:1/h;++i0)for(i=-1;++i=s[0]&&a<=s[1]&&(o=c[ta.bisect(f,a,1,g)-1],o.y+=p,o.push(n[i]));return c}var t=!0,e=Number,r=pi,u=hi;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=Et(t),n):r},n.bins=function(t){return arguments.length?(u="number"==typeof t?function(n){return gi(n,t)}:Et(t),n):u},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},ta.layout.pack=function(){function n(n,i){var o=e.call(this,n,i),a=o[0],c=u[0],l=u[1],s=null==t?Math.sqrt:"function"==typeof t?t:function(){return t};if(a.x=a.y=0,Qu(a,function(n){n.r=+s(n.value)}),Qu(a,Mi),r){var f=r*(t?1:Math.max(2*a.r/c,2*a.r/l))/2;Qu(a,function(n){n.r+=f}),Qu(a,Mi),Qu(a,function(n){n.r-=f})}return _i(a,c/2,l/2,t?1:1/Math.max(2*a.r/c,2*a.r/l)),o}var t,e=ta.layout.hierarchy().sort(vi),r=0,u=[1,1];return n.size=function(t){return arguments.length?(u=t,n):u},n.radius=function(e){return arguments.length?(t=null==e||"function"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},Gu(n,e)},ta.layout.tree=function(){function n(n,u){var s=o.call(this,n,u),f=s[0],h=t(f);if(Qu(h,e),h.parent.m=-h.z,Ku(h,r),l)Ku(f,i);else{var g=f,p=f,v=f;Ku(f,function(n){n.xp.x&&(p=n),n.depth>v.depth&&(v=n)});var d=a(g,p)/2-g.x,m=c[0]/(p.x+a(p,g)/2+d),y=c[1]/(v.depth||1);Ku(f,function(n){n.x=(n.x+d)*m,n.y=n.depth*y})}return s}function t(n){for(var t,e={A:null,children:[n]},r=[e];null!=(t=r.pop());)for(var u,i=t.children,o=0,a=i.length;a>o;++o)r.push((i[o]=u={_:i[o],parent:t,children:(u=i[o].children)&&u.slice()||[],A:null,a:null,z:0,m:0,c:0,s:0,t:null,i:o}).a=u);return e.children[0]}function e(n){var t=n.children,e=n.parent.children,r=n.i?e[n.i-1]:null;if(t.length){Ni(n);var i=(t[0].z+t[t.length-1].z)/2;r?(n.z=r.z+a(n._,r._),n.m=n.z-i):n.z=i}else r&&(n.z=r.z+a(n._,r._));n.parent.A=u(n,r,n.parent.A||e[0])}function r(n){n._.x=n.z+n.parent.m,n.m+=n.parent.m}function u(n,t,e){if(t){for(var r,u=n,i=n,o=t,c=u.parent.children[0],l=u.m,s=i.m,f=o.m,h=c.m;o=Ei(o),u=ki(u),o&&u;)c=ki(c),i=Ei(i),i.a=n,r=o.z+f-u.z-l+a(o._,u._),r>0&&(Ai(Ci(o,n,e),n,r),l+=r,s+=r),f+=o.m,l+=u.m,h+=c.m,s+=i.m;o&&!Ei(i)&&(i.t=o,i.m+=f-s),u&&!ki(c)&&(c.t=u,c.m+=l-h,e=n)}return e}function i(n){n.x*=c[0],n.y=n.depth*c[1]}var o=ta.layout.hierarchy().sort(null).value(null),a=Si,c=[1,1],l=null;return n.separation=function(t){return arguments.length?(a=t,n):a},n.size=function(t){return arguments.length?(l=null==(c=t)?i:null,n):l?null:c},n.nodeSize=function(t){return arguments.length?(l=null==(c=t)?null:i,n):l?c:null},Gu(n,o)},ta.layout.cluster=function(){function n(n,i){var o,a=t.call(this,n,i),c=a[0],l=0;Qu(c,function(n){var t=n.children;t&&t.length?(n.x=qi(t),n.y=zi(t)):(n.x=o?l+=e(n,o):0,n.y=0,o=n)});var s=Li(c),f=Ti(c),h=s.x-e(s,f)/2,g=f.x+e(f,s)/2;return Qu(c,u?function(n){n.x=(n.x-c.x)*r[0],n.y=(c.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(g-h)*r[0],n.y=(1-(c.y?n.y/c.y:1))*r[1]}),a}var t=ta.layout.hierarchy().sort(null).value(null),e=Si,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},Gu(n,t)},ta.layout.treemap=function(){function n(n,t){for(var e,r,u=-1,i=n.length;++ut?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var i=e.children;if(i&&i.length){var o,a,c,l=f(e),s=[],h=i.slice(),p=1/0,v="slice"===g?l.dx:"dice"===g?l.dy:"slice-dice"===g?1&e.depth?l.dy:l.dx:Math.min(l.dx,l.dy);for(n(h,l.dx*l.dy/e.value),s.area=0;(c=h.length)>0;)s.push(o=h[c-1]),s.area+=o.area,"squarify"!==g||(a=r(s,v))<=p?(h.pop(),p=a):(s.area-=s.pop().area,u(s,v,l,!1),v=Math.min(l.dx,l.dy),s.length=s.area=0,p=1/0);s.length&&(u(s,v,l,!0),s.length=s.area=0),i.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var i,o=f(t),a=r.slice(),c=[];for(n(a,o.dx*o.dy/t.value),c.area=0;i=a.pop();)c.push(i),c.area+=i.area,null!=i.z&&(u(c,i.z?o.dx:o.dy,o,!a.length),c.length=c.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,u=0,i=1/0,o=-1,a=n.length;++oe&&(i=e),e>u&&(u=e));return r*=r,t*=t,r?Math.max(t*u*p/r,r/(t*i*p)):1/0}function u(n,t,e,r){var u,i=-1,o=n.length,a=e.x,l=e.y,s=t?c(n.area/t):0;if(t==e.dx){for((r||s>e.dy)&&(s=e.dy);++ie.dx)&&(s=e.dx);++ie&&(t=1),1>e&&(n=0),function(){var e,r,u;do e=2*Math.random()-1,r=2*Math.random()-1,u=e*e+r*r;while(!u||u>1);return n+t*e*Math.sqrt(-2*Math.log(u)/u)}},logNormal:function(){var n=ta.random.normal.apply(ta,arguments);return function(){return Math.exp(n())}},bates:function(n){var t=ta.random.irwinHall(n);return function(){return t()/n}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t}}},ta.scale={};var ml={floor:y,ceil:y};ta.scale.linear=function(){return Ii([0,1],[0,1],mu,!1)};var yl={s:1,g:1,p:1,r:1,e:1};ta.scale.log=function(){return Ji(ta.scale.linear().domain([0,1]),10,!0,[1,10])};var Ml=ta.format(".0e"),xl={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};ta.scale.pow=function(){return Gi(ta.scale.linear(),1,[0,1])},ta.scale.sqrt=function(){return ta.scale.pow().exponent(.5)},ta.scale.ordinal=function(){return Qi([],{t:"range",a:[[]]})},ta.scale.category10=function(){return ta.scale.ordinal().range(bl)},ta.scale.category20=function(){return ta.scale.ordinal().range(_l)},ta.scale.category20b=function(){return ta.scale.ordinal().range(wl)},ta.scale.category20c=function(){return ta.scale.ordinal().range(Sl)};var bl=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(Mt),_l=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(Mt),wl=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(Mt),Sl=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(Mt);ta.scale.quantile=function(){return no([],[])},ta.scale.quantize=function(){return to(0,1,[0,1])},ta.scale.threshold=function(){return eo([.5],[0,1])},ta.scale.identity=function(){return ro([0,1])},ta.svg={},ta.svg.arc=function(){function n(){var n=Math.max(0,+e.apply(this,arguments)),l=Math.max(0,+r.apply(this,arguments)),s=o.apply(this,arguments)-Ra,f=a.apply(this,arguments)-Ra,h=Math.abs(f-s),g=s>f?0:1;if(n>l&&(p=l,l=n,n=p),h>=Ta)return t(l,g)+(n?t(n,1-g):"")+"Z";var p,v,d,m,y,M,x,b,_,w,S,k,E=0,A=0,N=[];if((m=(+c.apply(this,arguments)||0)/2)&&(d=i===kl?Math.sqrt(n*n+l*l):+i.apply(this,arguments),g||(A*=-1),l&&(A=tt(d/l*Math.sin(m))),n&&(E=tt(d/n*Math.sin(m)))),l){y=l*Math.cos(s+A),M=l*Math.sin(s+A),x=l*Math.cos(f-A),b=l*Math.sin(f-A);var C=Math.abs(f-s-2*A)<=qa?0:1;if(A&&so(y,M,x,b)===g^C){var z=(s+f)/2;y=l*Math.cos(z),M=l*Math.sin(z),x=b=null}}else y=M=0;if(n){_=n*Math.cos(f-E),w=n*Math.sin(f-E),S=n*Math.cos(s+E),k=n*Math.sin(s+E);var q=Math.abs(s-f+2*E)<=qa?0:1;if(E&&so(_,w,S,k)===1-g^q){var L=(s+f)/2;_=n*Math.cos(L),w=n*Math.sin(L),S=k=null}}else _=w=0;if((p=Math.min(Math.abs(l-n)/2,+u.apply(this,arguments)))>.001){v=l>n^g?0:1;var T=null==S?[_,w]:null==x?[y,M]:Lr([y,M],[S,k],[x,b],[_,w]),R=y-T[0],D=M-T[1],P=x-T[0],U=b-T[1],j=1/Math.sin(Math.acos((R*P+D*U)/(Math.sqrt(R*R+D*D)*Math.sqrt(P*P+U*U)))/2),F=Math.sqrt(T[0]*T[0]+T[1]*T[1]);if(null!=x){var H=Math.min(p,(l-F)/(j+1)),O=fo(null==S?[_,w]:[S,k],[y,M],l,H,g),I=fo([x,b],[_,w],l,H,g);p===H?N.push("M",O[0],"A",H,",",H," 0 0,",v," ",O[1],"A",l,",",l," 0 ",1-g^so(O[1][0],O[1][1],I[1][0],I[1][1]),",",g," ",I[1],"A",H,",",H," 0 0,",v," ",I[0]):N.push("M",O[0],"A",H,",",H," 0 1,",v," ",I[0])}else N.push("M",y,",",M);if(null!=S){var Y=Math.min(p,(n-F)/(j-1)),Z=fo([y,M],[S,k],n,-Y,g),V=fo([_,w],null==x?[y,M]:[x,b],n,-Y,g);p===Y?N.push("L",V[0],"A",Y,",",Y," 0 0,",v," ",V[1],"A",n,",",n," 0 ",g^so(V[1][0],V[1][1],Z[1][0],Z[1][1]),",",1-g," ",Z[1],"A",Y,",",Y," 0 0,",v," ",Z[0]):N.push("L",V[0],"A",Y,",",Y," 0 0,",v," ",Z[0])}else N.push("L",_,",",w)}else N.push("M",y,",",M),null!=x&&N.push("A",l,",",l," 0 ",C,",",g," ",x,",",b),N.push("L",_,",",w),null!=S&&N.push("A",n,",",n," 0 ",q,",",1-g," ",S,",",k);return N.push("Z"),N.join("")}function t(n,t){return"M0,"+n+"A"+n+","+n+" 0 1,"+t+" 0,"+-n+"A"+n+","+n+" 0 1,"+t+" 0,"+n}var e=io,r=oo,u=uo,i=kl,o=ao,a=co,c=lo;return n.innerRadius=function(t){return arguments.length?(e=Et(t),n):e},n.outerRadius=function(t){return arguments.length?(r=Et(t),n):r},n.cornerRadius=function(t){return arguments.length?(u=Et(t),n):u},n.padRadius=function(t){return arguments.length?(i=t==kl?kl:Et(t),n):i},n.startAngle=function(t){return arguments.length?(o=Et(t),n):o},n.endAngle=function(t){return arguments.length?(a=Et(t),n):a},n.padAngle=function(t){return arguments.length?(c=Et(t),n):c},n.centroid=function(){var n=(+e.apply(this,arguments)+ +r.apply(this,arguments))/2,t=(+o.apply(this,arguments)+ +a.apply(this,arguments))/2-Ra;return[Math.cos(t)*n,Math.sin(t)*n]},n};var kl="auto";ta.svg.line=function(){return ho(y)};var El=ta.map({linear:go,"linear-closed":po,step:vo,"step-before":mo,"step-after":yo,basis:So,"basis-open":ko,"basis-closed":Eo,bundle:Ao,cardinal:bo,"cardinal-open":Mo,"cardinal-closed":xo,monotone:To});El.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var Al=[0,2/3,1/3,0],Nl=[0,1/3,2/3,0],Cl=[0,1/6,2/3,1/6];ta.svg.line.radial=function(){var n=ho(Ro);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},mo.reverse=yo,yo.reverse=mo,ta.svg.area=function(){return Do(y)},ta.svg.area.radial=function(){var n=Do(Ro);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},ta.svg.chord=function(){function n(n,a){var c=t(this,i,n,a),l=t(this,o,n,a);return"M"+c.p0+r(c.r,c.p1,c.a1-c.a0)+(e(c,l)?u(c.r,c.p1,c.r,c.p0):u(c.r,c.p1,l.r,l.p0)+r(l.r,l.p1,l.a1-l.a0)+u(l.r,l.p1,c.r,c.p0))+"Z"}function t(n,t,e,r){var u=t.call(n,e,r),i=a.call(n,u,r),o=c.call(n,u,r)-Ra,s=l.call(n,u,r)-Ra;return{r:i,a0:o,a1:s,p0:[i*Math.cos(o),i*Math.sin(o)],p1:[i*Math.cos(s),i*Math.sin(s)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return"A"+n+","+n+" 0 "+ +(e>qa)+",1 "+t}function u(n,t,e,r){return"Q 0,0 "+r}var i=mr,o=yr,a=Po,c=ao,l=co;return n.radius=function(t){return arguments.length?(a=Et(t),n):a},n.source=function(t){return arguments.length?(i=Et(t),n):i},n.target=function(t){return arguments.length?(o=Et(t),n):o},n.startAngle=function(t){return arguments.length?(c=Et(t),n):c},n.endAngle=function(t){return arguments.length?(l=Et(t),n):l},n},ta.svg.diagonal=function(){function n(n,u){var i=t.call(this,n,u),o=e.call(this,n,u),a=(i.y+o.y)/2,c=[i,{x:i.x,y:a},{x:o.x,y:a},o];return c=c.map(r),"M"+c[0]+"C"+c[1]+" "+c[2]+" "+c[3]}var t=mr,e=yr,r=Uo;return n.source=function(e){return arguments.length?(t=Et(e),n):t},n.target=function(t){return arguments.length?(e=Et(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},ta.svg.diagonal.radial=function(){var n=ta.svg.diagonal(),t=Uo,e=n.projection;return n.projection=function(n){return arguments.length?e(jo(t=n)):t},n},ta.svg.symbol=function(){function n(n,r){return(zl.get(t.call(this,n,r))||Oo)(e.call(this,n,r))}var t=Ho,e=Fo;return n.type=function(e){return arguments.length?(t=Et(e),n):t},n.size=function(t){return arguments.length?(e=Et(t),n):e},n};var zl=ta.map({circle:Oo,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*Ll)),e=t*Ll;return"M0,"+-t+"L"+e+",0 0,"+t+" "+-e+",0Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/ql),e=t*ql/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/ql),e=t*ql/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});ta.svg.symbolTypes=zl.keys();var ql=Math.sqrt(3),Ll=Math.tan(30*Da);_a.transition=function(n){for(var t,e,r=Tl||++Ul,u=Xo(n),i=[],o=Rl||{time:Date.now(),ease:Su,delay:0,duration:250},a=-1,c=this.length;++ai;i++){u.push(t=[]);for(var e=this[i],a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return Yo(u,this.namespace,this.id)},Pl.tween=function(n,t){var e=this.id,r=this.namespace;return arguments.length<2?this.node()[r][e].tween.get(n):Y(this,null==t?function(t){t[r][e].tween.remove(n)}:function(u){u[r][e].tween.set(n,t)})},Pl.attr=function(n,t){function e(){this.removeAttribute(a)}function r(){this.removeAttributeNS(a.space,a.local)}function u(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(a);return e!==n&&(t=o(e,n),function(n){this.setAttribute(a,t(n))})})}function i(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(a.space,a.local);return e!==n&&(t=o(e,n),function(n){this.setAttributeNS(a.space,a.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var o="transform"==n?Hu:mu,a=ta.ns.qualify(n);return Zo(this,"attr."+n,t,a.local?i:u)},Pl.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(u));return r&&function(n){this.setAttribute(u,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(u.space,u.local));return r&&function(n){this.setAttributeNS(u.space,u.local,r(n))}}var u=ta.ns.qualify(n);return this.tween("attr."+n,u.local?r:e)},Pl.style=function(n,e,r){function u(){this.style.removeProperty(n)}function i(e){return null==e?u:(e+="",function(){var u,i=t(this).getComputedStyle(this,null).getPropertyValue(n);return i!==e&&(u=mu(i,e),function(t){this.style.setProperty(n,u(t),r)})})}var o=arguments.length;if(3>o){if("string"!=typeof n){2>o&&(e="");for(r in n)this.style(r,n[r],e);return this}r=""}return Zo(this,"style."+n,e,i)},Pl.styleTween=function(n,e,r){function u(u,i){var o=e.call(this,u,i,t(this).getComputedStyle(this,null).getPropertyValue(n));return o&&function(t){this.style.setProperty(n,o(t),r)}}return arguments.length<3&&(r=""),this.tween("style."+n,u)},Pl.text=function(n){return Zo(this,"text",n,Vo)},Pl.remove=function(){var n=this.namespace;return this.each("end.transition",function(){var t;this[n].count<2&&(t=this.parentNode)&&t.removeChild(this)})},Pl.ease=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].ease:("function"!=typeof n&&(n=ta.ease.apply(ta,arguments)),Y(this,function(r){r[e][t].ease=n}))},Pl.delay=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].delay:Y(this,"function"==typeof n?function(r,u,i){r[e][t].delay=+n.call(r,r.__data__,u,i)}:(n=+n,function(r){r[e][t].delay=n}))},Pl.duration=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].duration:Y(this,"function"==typeof n?function(r,u,i){r[e][t].duration=Math.max(1,n.call(r,r.__data__,u,i))}:(n=Math.max(1,n),function(r){r[e][t].duration=n}))},Pl.each=function(n,t){var e=this.id,r=this.namespace;if(arguments.length<2){var u=Rl,i=Tl;try{Tl=e,Y(this,function(t,u,i){Rl=t[r][e],n.call(t,t.__data__,u,i)})}finally{Rl=u,Tl=i}}else Y(this,function(u){var i=u[r][e];(i.event||(i.event=ta.dispatch("start","end","interrupt"))).on(n,t)});return this},Pl.transition=function(){for(var n,t,e,r,u=this.id,i=++Ul,o=this.namespace,a=[],c=0,l=this.length;l>c;c++){a.push(n=[]);for(var t=this[c],s=0,f=t.length;f>s;s++)(e=t[s])&&(r=e[o][u],$o(e,s,o,i,{time:r.time,ease:r.ease,delay:r.delay+r.duration,duration:r.duration})),n.push(e)}return Yo(a,o,i)},ta.svg.axis=function(){function n(n){n.each(function(){var n,l=ta.select(this),s=this.__chart__||e,f=this.__chart__=e.copy(),h=null==c?f.ticks?f.ticks.apply(f,a):f.domain():c,g=null==t?f.tickFormat?f.tickFormat.apply(f,a):y:t,p=l.selectAll(".tick").data(h,f),v=p.enter().insert("g",".domain").attr("class","tick").style("opacity",Ca),d=ta.transition(p.exit()).style("opacity",Ca).remove(),m=ta.transition(p.order()).style("opacity",1),M=Math.max(u,0)+o,x=Ui(f),b=l.selectAll(".domain").data([0]),_=(b.enter().append("path").attr("class","domain"),ta.transition(b));v.append("line"),v.append("text");var w,S,k,E,A=v.select("line"),N=m.select("line"),C=p.select("text").text(g),z=v.select("text"),q=m.select("text"),L="top"===r||"left"===r?-1:1;if("bottom"===r||"top"===r?(n=Bo,w="x",k="y",S="x2",E="y2",C.attr("dy",0>L?"0em":".71em").style("text-anchor","middle"),_.attr("d","M"+x[0]+","+L*i+"V0H"+x[1]+"V"+L*i)):(n=Wo,w="y",k="x",S="y2",E="x2",C.attr("dy",".32em").style("text-anchor",0>L?"end":"start"),_.attr("d","M"+L*i+","+x[0]+"H0V"+x[1]+"H"+L*i)),A.attr(E,L*u),z.attr(k,L*M),N.attr(S,0).attr(E,L*u),q.attr(w,0).attr(k,L*M),f.rangeBand){var T=f,R=T.rangeBand()/2;s=f=function(n){return T(n)+R}}else s.rangeBand?s=f:d.call(n,f,s);v.call(n,s,f),m.call(n,f,f)})}var t,e=ta.scale.linear(),r=jl,u=6,i=6,o=3,a=[10],c=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in Fl?t+"":jl,n):r},n.ticks=function(){return arguments.length?(a=arguments,n):a},n.tickValues=function(t){return arguments.length?(c=t,n):c},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(u=+t,i=+arguments[e-1],n):u},n.innerTickSize=function(t){return arguments.length?(u=+t,n):u},n.outerTickSize=function(t){return arguments.length?(i=+t,n):i},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(){return arguments.length&&n},n};var jl="bottom",Fl={top:1,right:1,bottom:1,left:1};ta.svg.brush=function(){function n(t){t.each(function(){var t=ta.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",i).on("touchstart.brush",i),o=t.selectAll(".background").data([0]);o.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),t.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var a=t.selectAll(".resize").data(v,y);a.exit().remove(),a.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return Hl[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),a.style("display",n.empty()?"none":null);var c,f=ta.transition(t),h=ta.transition(o);l&&(c=Ui(l),h.attr("x",c[0]).attr("width",c[1]-c[0]),r(f)),s&&(c=Ui(s),h.attr("y",c[0]).attr("height",c[1]-c[0]),u(f)),e(f)})}function e(n){n.selectAll(".resize").attr("transform",function(n){return"translate("+f[+/e$/.test(n)]+","+h[+/^s/.test(n)]+")"})}function r(n){n.select(".extent").attr("x",f[0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",f[1]-f[0])}function u(n){n.select(".extent").attr("y",h[0]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",h[1]-h[0])}function i(){function i(){32==ta.event.keyCode&&(C||(M=null,q[0]-=f[1],q[1]-=h[1],C=2),S())}function v(){32==ta.event.keyCode&&2==C&&(q[0]+=f[1],q[1]+=h[1],C=0,S())}function d(){var n=ta.mouse(b),t=!1;x&&(n[0]+=x[0],n[1]+=x[1]),C||(ta.event.altKey?(M||(M=[(f[0]+f[1])/2,(h[0]+h[1])/2]),q[0]=f[+(n[0]s?(u=r,r=s):u=s),v[0]!=r||v[1]!=u?(e?a=null:o=null,v[0]=r,v[1]=u,!0):void 0}function y(){d(),k.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),ta.select("body").style("cursor",null),L.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),z(),w({type:"brushend"})}var M,x,b=this,_=ta.select(ta.event.target),w=c.of(b,arguments),k=ta.select(b),E=_.datum(),A=!/^(n|s)$/.test(E)&&l,N=!/^(e|w)$/.test(E)&&s,C=_.classed("extent"),z=W(b),q=ta.mouse(b),L=ta.select(t(b)).on("keydown.brush",i).on("keyup.brush",v);if(ta.event.changedTouches?L.on("touchmove.brush",d).on("touchend.brush",y):L.on("mousemove.brush",d).on("mouseup.brush",y),k.interrupt().selectAll("*").interrupt(),C)q[0]=f[0]-q[0],q[1]=h[0]-q[1];else if(E){var T=+/w$/.test(E),R=+/^n/.test(E);x=[f[1-T]-q[0],h[1-R]-q[1]],q[0]=f[T],q[1]=h[R]}else ta.event.altKey&&(M=q.slice());k.style("pointer-events","none").selectAll(".resize").style("display",null),ta.select("body").style("cursor",_.style("cursor")),w({type:"brushstart"}),d()}var o,a,c=E(n,"brushstart","brush","brushend"),l=null,s=null,f=[0,0],h=[0,0],g=!0,p=!0,v=Ol[0];return n.event=function(n){n.each(function(){var n=c.of(this,arguments),t={x:f,y:h,i:o,j:a},e=this.__chart__||t;this.__chart__=t,Tl?ta.select(this).transition().each("start.brush",function(){o=e.i,a=e.j,f=e.x,h=e.y,n({type:"brushstart"})}).tween("brush:brush",function(){var e=yu(f,t.x),r=yu(h,t.y);return o=a=null,function(u){f=t.x=e(u),h=t.y=r(u),n({type:"brush",mode:"resize"})}}).each("end.brush",function(){o=t.i,a=t.j,n({type:"brush",mode:"resize"}),n({type:"brushend"})}):(n({type:"brushstart"}),n({type:"brush",mode:"resize"}),n({type:"brushend"}))})},n.x=function(t){return arguments.length?(l=t,v=Ol[!l<<1|!s],n):l},n.y=function(t){return arguments.length?(s=t,v=Ol[!l<<1|!s],n):s},n.clamp=function(t){return arguments.length?(l&&s?(g=!!t[0],p=!!t[1]):l?g=!!t:s&&(p=!!t),n):l&&s?[g,p]:l?g:s?p:null},n.extent=function(t){var e,r,u,i,c;return arguments.length?(l&&(e=t[0],r=t[1],s&&(e=e[0],r=r[0]),o=[e,r],l.invert&&(e=l(e),r=l(r)),e>r&&(c=e,e=r,r=c),(e!=f[0]||r!=f[1])&&(f=[e,r])),s&&(u=t[0],i=t[1],l&&(u=u[1],i=i[1]),a=[u,i],s.invert&&(u=s(u),i=s(i)),u>i&&(c=u,u=i,i=c),(u!=h[0]||i!=h[1])&&(h=[u,i])),n):(l&&(o?(e=o[0],r=o[1]):(e=f[0],r=f[1],l.invert&&(e=l.invert(e),r=l.invert(r)),e>r&&(c=e,e=r,r=c))),s&&(a?(u=a[0],i=a[1]):(u=h[0],i=h[1],s.invert&&(u=s.invert(u),i=s.invert(i)),u>i&&(c=u,u=i,i=c))),l&&s?[[e,u],[r,i]]:l?[e,r]:s&&[u,i])},n.clear=function(){return n.empty()||(f=[0,0],h=[0,0],o=a=null),n},n.empty=function(){return!!l&&f[0]==f[1]||!!s&&h[0]==h[1]},ta.rebind(n,c,"on")};var Hl={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},Ol=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]],Il=ac.format=gc.timeFormat,Yl=Il.utc,Zl=Yl("%Y-%m-%dT%H:%M:%S.%LZ");Il.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?Jo:Zl,Jo.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},Jo.toString=Zl.toString,ac.second=Ft(function(n){return new cc(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),ac.seconds=ac.second.range,ac.seconds.utc=ac.second.utc.range,ac.minute=Ft(function(n){return new cc(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),ac.minutes=ac.minute.range,ac.minutes.utc=ac.minute.utc.range,ac.hour=Ft(function(n){var t=n.getTimezoneOffset()/60;return new cc(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),ac.hours=ac.hour.range,ac.hours.utc=ac.hour.utc.range,ac.month=Ft(function(n){return n=ac.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),ac.months=ac.month.range,ac.months.utc=ac.month.utc.range;var Vl=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Xl=[[ac.second,1],[ac.second,5],[ac.second,15],[ac.second,30],[ac.minute,1],[ac.minute,5],[ac.minute,15],[ac.minute,30],[ac.hour,1],[ac.hour,3],[ac.hour,6],[ac.hour,12],[ac.day,1],[ac.day,2],[ac.week,1],[ac.month,1],[ac.month,3],[ac.year,1]],$l=Il.multi([[".%L",function(n){return n.getMilliseconds()}],[":%S",function(n){return n.getSeconds()}],["%I:%M",function(n){return n.getMinutes()}],["%I %p",function(n){return n.getHours()}],["%a %d",function(n){return n.getDay()&&1!=n.getDate()}],["%b %d",function(n){return 1!=n.getDate()}],["%B",function(n){return n.getMonth()}],["%Y",Ne]]),Bl={range:function(n,t,e){return ta.range(Math.ceil(n/e)*e,+t,e).map(Ko)},floor:y,ceil:y};Xl.year=ac.year,ac.scale=function(){return Go(ta.scale.linear(),Xl,$l)};var Wl=Xl.map(function(n){return[n[0].utc,n[1]]}),Jl=Yl.multi([[".%L",function(n){return n.getUTCMilliseconds()}],[":%S",function(n){return n.getUTCSeconds()}],["%I:%M",function(n){return n.getUTCMinutes()}],["%I %p",function(n){return n.getUTCHours()}],["%a %d",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],["%b %d",function(n){return 1!=n.getUTCDate()}],["%B",function(n){return n.getUTCMonth()}],["%Y",Ne]]);Wl.year=ac.year.utc,ac.scale.utc=function(){return Go(ta.scale.linear(),Wl,Jl)},ta.text=At(function(n){return n.responseText}),ta.json=function(n,t){return Nt(n,"application/json",Qo,t)},ta.html=function(n,t){return Nt(n,"text/html",na,t)},ta.xml=At(function(n){return n.responseXML}),"function"==typeof define&&define.amd?define(ta):"object"==typeof module&&module.exports&&(module.exports=ta),this.d3=ta}(); \ No newline at end of file diff --git a/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/js/holder.min.js b/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/js/holder.min.js new file mode 100644 index 00000000000..6bfc844ba56 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/js/holder.min.js @@ -0,0 +1,12 @@ +/*! + +Holder - client side image placeholders +Version 2.7.1+6hydf +© 2015 Ivan Malopinsky - http://imsky.co + +Site: http://holderjs.com +Issues: https://github.com/imsky/holder/issues +License: http://opensource.org/licenses/MIT + +*/ +!function(a){if(a.document){var b=a.document;b.querySelectorAll||(b.querySelectorAll=function(c){var d,e=b.createElement("style"),f=[];for(b.documentElement.firstChild.appendChild(e),b._qsa=[],e.styleSheet.cssText=c+"{x-qsa:expression(document._qsa && document._qsa.push(this))}",a.scrollBy(0,0),e.parentNode.removeChild(e);b._qsa.length;)d=b._qsa.shift(),d.style.removeAttribute("x-qsa"),f.push(d);return b._qsa=null,f}),b.querySelector||(b.querySelector=function(a){var c=b.querySelectorAll(a);return c.length?c[0]:null}),b.getElementsByClassName||(b.getElementsByClassName=function(a){return a=String(a).replace(/^|\s+/g,"."),b.querySelectorAll(a)}),Object.keys||(Object.keys=function(a){if(a!==Object(a))throw TypeError("Object.keys called on non-object");var b,c=[];for(b in a)Object.prototype.hasOwnProperty.call(a,b)&&c.push(b);return c}),function(a){var b="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";a.atob=a.atob||function(a){a=String(a);var c,d=0,e=[],f=0,g=0;if(a=a.replace(/\s/g,""),a.length%4===0&&(a=a.replace(/=+$/,"")),a.length%4===1)throw Error("InvalidCharacterError");if(/[^+/0-9A-Za-z]/.test(a))throw Error("InvalidCharacterError");for(;d>16&255)),e.push(String.fromCharCode(f>>8&255)),e.push(String.fromCharCode(255&f)),g=0,f=0),d+=1;return 12===g?(f>>=4,e.push(String.fromCharCode(255&f))):18===g&&(f>>=2,e.push(String.fromCharCode(f>>8&255)),e.push(String.fromCharCode(255&f))),e.join("")},a.btoa=a.btoa||function(a){a=String(a);var c,d,e,f,g,h,i,j=0,k=[];if(/[^\x00-\xFF]/.test(a))throw Error("InvalidCharacterError");for(;j>2,g=(3&c)<<4|d>>4,h=(15&d)<<2|e>>6,i=63&e,j===a.length+2?(h=64,i=64):j===a.length+1&&(i=64),k.push(b.charAt(f),b.charAt(g),b.charAt(h),b.charAt(i));return k.join("")}}(a),Object.prototype.hasOwnProperty||(Object.prototype.hasOwnProperty=function(a){var b=this.__proto__||this.constructor.prototype;return a in this&&(!(a in b)||b[a]!==this[a])}),function(){if("performance"in a==!1&&(a.performance={}),Date.now=Date.now||function(){return(new Date).getTime()},"now"in a.performance==!1){var b=Date.now();performance.timing&&performance.timing.navigationStart&&(b=performance.timing.navigationStart),a.performance.now=function(){return Date.now()-b}}}(),a.requestAnimationFrame||(a.webkitRequestAnimationFrame?!function(a){a.requestAnimationFrame=function(b){return webkitRequestAnimationFrame(function(){b(a.performance.now())})},a.cancelAnimationFrame=webkitCancelAnimationFrame}(a):a.mozRequestAnimationFrame?!function(a){a.requestAnimationFrame=function(b){return mozRequestAnimationFrame(function(){b(a.performance.now())})},a.cancelAnimationFrame=mozCancelAnimationFrame}(a):!function(a){a.requestAnimationFrame=function(b){return a.setTimeout(b,1e3/60)},a.cancelAnimationFrame=a.clearTimeout}(a))}}(this),function(a,b){"object"==typeof exports&&"object"==typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):"object"==typeof exports?exports.Holder=b():a.Holder=b()}(this,function(){return function(a){function b(d){if(c[d])return c[d].exports;var e=c[d]={exports:{},id:d,loaded:!1};return a[d].call(e.exports,e,e.exports,b),e.loaded=!0,e.exports}var c={};return b.m=a,b.c=c,b.p="",b(0)}([function(a,b,c){(function(b){function d(a,b,c,d){var f=e(c.substr(c.lastIndexOf(a.domain)),a);f&&h({mode:null,el:d,flags:f,engineSettings:b})}function e(a,b){var c={theme:B(J.settings.themes.gray,null),stylesheets:b.stylesheets,instanceOptions:b};return a.match(/([\d]+p?)x([\d]+p?)(?:\?|$)/)?f(a,c):g(a,c)}function f(a,b){var c=a.split("?"),d=c[0].split("/");b.holderURL=a;var e=d[1],f=e.match(/([\d]+p?)x([\d]+p?)/);if(!f)return!1;if(b.fluid=-1!==e.indexOf("p"),b.dimensions={width:f[1].replace("p","%"),height:f[2].replace("p","%")},2===c.length){var g=A.parse(c[1]);if(g.bg&&(b.theme.background=(-1===g.bg.indexOf("#")?"#":"")+g.bg),g.fg&&(b.theme.foreground=(-1===g.fg.indexOf("#")?"#":"")+g.fg),g.theme&&b.instanceOptions.themes.hasOwnProperty(g.theme)&&(b.theme=B(b.instanceOptions.themes[g.theme],null)),g.text&&(b.text=g.text),g.textmode&&(b.textmode=g.textmode),g.size&&(b.size=g.size),g.font&&(b.font=g.font),g.align&&(b.align=g.align),b.nowrap=z.truthy(g.nowrap),b.auto=z.truthy(g.auto),z.truthy(g.random)){J.vars.cache.themeKeys=J.vars.cache.themeKeys||Object.keys(b.instanceOptions.themes);var h=J.vars.cache.themeKeys[0|Math.random()*J.vars.cache.themeKeys.length];b.theme=B(b.instanceOptions.themes[h],null)}}return b}function g(a,b){var c=!1,d=String.fromCharCode(11),e=a.replace(/([^\\])\//g,"$1"+d).split(d),f=/%[0-9a-f]{2}/gi,g=b.instanceOptions;b.holderURL=[];for(var h=e.length,i=0;h>i;i++){var j=e[i];if(j.match(f))try{j=decodeURIComponent(j)}catch(k){j=e[i]}var l=!1;if(J.flags.dimensions.match(j))c=!0,b.dimensions=J.flags.dimensions.output(j),l=!0;else if(J.flags.fluid.match(j))c=!0,b.dimensions=J.flags.fluid.output(j),b.fluid=!0,l=!0;else if(J.flags.textmode.match(j))b.textmode=J.flags.textmode.output(j),l=!0;else if(J.flags.colors.match(j)){var m=J.flags.colors.output(j);b.theme=B(b.theme,m),l=!0}else if(g.themes[j])g.themes.hasOwnProperty(j)&&(b.theme=B(g.themes[j],null)),l=!0;else if(J.flags.font.match(j))b.font=J.flags.font.output(j),l=!0;else if(J.flags.auto.match(j))b.auto=!0,l=!0;else if(J.flags.text.match(j))b.text=J.flags.text.output(j),l=!0;else if(J.flags.size.match(j))b.size=J.flags.size.output(j),l=!0;else if(J.flags.random.match(j)){null==J.vars.cache.themeKeys&&(J.vars.cache.themeKeys=Object.keys(g.themes));var n=J.vars.cache.themeKeys[0|Math.random()*J.vars.cache.themeKeys.length];b.theme=B(g.themes[n],null),l=!0}l&&b.holderURL.push(j)}return b.holderURL.unshift(g.domain),b.holderURL=b.holderURL.join("/"),c?b:!1}function h(a){var b=a.mode,c=a.el,d=a.flags,e=a.engineSettings,f=d.dimensions,g=d.theme,h=f.width+"x"+f.height;if(b=null==b?d.fluid?"fluid":"image":b,null!=d.text&&(g.text=d.text,"object"===c.nodeName.toLowerCase())){for(var j=g.text.split("\\n"),k=0;k1){var n,o=0,p=0,q=0;j=new e.Group("line"+q),("left"===a.align||"right"===a.align)&&(m=a.width*(1-2*(1-J.setup.lineWrapRatio)));for(var r=0;r=m||t===!0)&&(b(g,j,o,g.properties.leading),g.add(j),o=0,p+=g.properties.leading,q+=1,j=new e.Group("line"+q),j.y=p),t!==!0&&(i.moveTo(o,0),o+=h.spaceWidth+s.width,j.add(i))}if(b(g,j,o,g.properties.leading),g.add(j),"left"===a.align)g.moveTo(a.width-l,null,null);else if("right"===a.align){for(n in g.children)j=g.children[n],j.moveTo(a.width-j.width,null,null);g.moveTo(0-(a.width-l),null,null)}else{for(n in g.children)j=g.children[n],j.moveTo((g.width-j.width)/2,null,null);g.moveTo((a.width-g.width)/2,null,null)}g.moveTo(null,(a.height-g.height)/2,null),(a.height-g.height)/2<0&&g.moveTo(null,0,null)}else i=new e.Text(a.text),j=new e.Group("line0"),j.add(i),g.add(j),"left"===a.align?g.moveTo(a.width-l,null,null):"right"===a.align?g.moveTo(0-(a.width-l),null,null):g.moveTo((a.width-h.boundingBox.width)/2,null,null),g.moveTo(null,(a.height-h.boundingBox.height)/2,null);return d}function k(a,b,c){var d=parseInt(a,10),e=parseInt(b,10),f=Math.max(d,e),g=Math.min(d,e),h=.8*Math.min(g,f*J.defaults.scale);return Math.round(Math.max(c,h))}function l(a){var b;b=null==a||null==a.nodeType?J.vars.resizableImages:[a];for(var c=0,d=b.length;d>c;c++){var e=b[c];if(e.holderData){var f=e.holderData.flags,g=D(e);if(g){if(!e.holderData.resizeUpdate)continue;if(f.fluid&&f.auto){var h=e.holderData.fluidConfig;switch(h.mode){case"width":g.height=g.width/h.ratio;break;case"height":g.width=g.height*h.ratio}}var j={mode:"image",holderSettings:{dimensions:g,theme:f.theme,flags:f},el:e,engineSettings:e.holderData.engineSettings};"exact"==f.textmode&&(f.exactDimensions=g,j.holderSettings.dimensions=f.dimensions),i(j)}else p(e)}}}function m(a){if(a.holderData){var b=D(a);if(b){var c=a.holderData.flags,d={fluidHeight:"%"==c.dimensions.height.slice(-1),fluidWidth:"%"==c.dimensions.width.slice(-1),mode:null,initialDimensions:b};d.fluidWidth&&!d.fluidHeight?(d.mode="width",d.ratio=d.initialDimensions.width/parseFloat(c.dimensions.height)):!d.fluidWidth&&d.fluidHeight&&(d.mode="height",d.ratio=parseFloat(c.dimensions.width)/d.initialDimensions.height),a.holderData.fluidConfig=d}else p(a)}}function n(){for(var a,c=[],d=Object.keys(J.vars.invisibleImages),e=0,f=d.length;f>e;e++)a=J.vars.invisibleImages[d[e]],D(a)&&"img"==a.nodeName.toLowerCase()&&(c.push(a),delete J.vars.invisibleImages[d[e]]);c.length&&I.run({images:c}),b.requestAnimationFrame(n)}function o(){J.vars.visibilityCheckStarted||(b.requestAnimationFrame(n),J.vars.visibilityCheckStarted=!0)}function p(a){a.holderData.invisibleId||(J.vars.invisibleId+=1,J.vars.invisibleImages["i"+J.vars.invisibleId]=a,a.holderData.invisibleId=J.vars.invisibleId)}function q(a,b){return null==b?document.createElement(a):document.createElementNS(b,a)}function r(a,b){for(var c in b)a.setAttribute(c,b[c])}function s(a,b,c){var d,e;null==a?(a=q("svg",E),d=q("defs",E),e=q("style",E),r(e,{type:"text/css"}),d.appendChild(e),a.appendChild(d)):e=a.querySelector("style"),a.webkitMatchesSelector&&a.setAttribute("xmlns",E);for(var f=0;f=0;h--){var i=g.createProcessingInstruction("xml-stylesheet",'href="'+f[h]+'" rel="stylesheet"');g.insertBefore(i,g.firstChild)}g.removeChild(g.documentElement),e=d.serializeToString(g)}var j=d.serializeToString(a);return j=j.replace(/\&(\#[0-9]{2,}\;)/g,"&$1"),e+j}}function u(){return b.DOMParser?(new DOMParser).parseFromString("","application/xml"):void 0}function v(a){J.vars.debounceTimer||a.call(this),J.vars.debounceTimer&&b.clearTimeout(J.vars.debounceTimer),J.vars.debounceTimer=b.setTimeout(function(){J.vars.debounceTimer=null,a.call(this)},J.setup.debounce)}function w(){v(function(){l(null)})}var x=c(1),y=c(2),z=c(3),A=c(4),B=z.extend,C=z.getNodeArray,D=z.dimensionCheck,E="http://www.w3.org/2000/svg",F=8,G="2.7.1",H="\nCreated with Holder.js "+G+".\nLearn more at http://holderjs.com\n(c) 2012-2015 Ivan Malopinsky - http://imsky.co\n",I={version:G,addTheme:function(a,b){return null!=a&&null!=b&&(J.settings.themes[a]=b),delete J.vars.cache.themeKeys,this},addImage:function(a,b){var c=document.querySelectorAll(b);if(c.length)for(var d=0,e=c.length;e>d;d++){var f=q("img"),g={};g[J.vars.dataAttr]=a,r(f,g),c[d].appendChild(f)}return this},setResizeUpdate:function(a,b){a.holderData&&(a.holderData.resizeUpdate=!!b,a.holderData.resizeUpdate&&l(a))},run:function(a){a=a||{};var c={},f=B(J.settings,a);J.vars.preempted=!0,J.vars.dataAttr=f.dataAttr||J.vars.dataAttr,c.renderer=f.renderer?f.renderer:J.setup.renderer,-1===J.setup.renderers.join(",").indexOf(c.renderer)&&(c.renderer=J.setup.supportsSVG?"svg":J.setup.supportsCanvas?"canvas":"html");var g=C(f.images),i=C(f.bgnodes),j=C(f.stylenodes),k=C(f.objects);c.stylesheets=[],c.svgXMLStylesheet=!0,c.noFontFallback=f.noFontFallback?f.noFontFallback:!1;for(var l=0;l1){c.nodeValue="";for(var u=0;u=0?b:1)}function f(a){v?e(a):w.push(a)}null==document.readyState&&document.addEventListener&&(document.addEventListener("DOMContentLoaded",function y(){document.removeEventListener("DOMContentLoaded",y,!1),document.readyState="complete"},!1),document.readyState="loading");var g=a.document,h=g.documentElement,i="load",j=!1,k="on"+i,l="complete",m="readyState",n="attachEvent",o="detachEvent",p="addEventListener",q="DOMContentLoaded",r="onreadystatechange",s="removeEventListener",t=p in g,u=j,v=j,w=[];if(g[m]===l)e(b);else if(t)g[p](q,c,j),a[p](i,c,j);else{g[n](r,c),a[n](k,c);try{u=null==a.frameElement&&h}catch(x){}u&&u.doScroll&&!function z(){if(!v){try{u.doScroll("left")}catch(a){return e(z,50)}d(),b()}}()}return f.version="1.4.0",f.isReady=function(){return v},f}a.exports="undefined"!=typeof window&&b(window)},function(a,b,c){var d=c(5),e=function(a){function b(a,b){for(var c in b)a[c]=b[c];return a}var c=1,e=d.defclass({constructor:function(a){c++,this.parent=null,this.children={},this.id=c,this.name="n"+c,null!=a&&(this.name=a),this.x=0,this.y=0,this.z=0,this.width=0,this.height=0},resize:function(a,b){null!=a&&(this.width=a),null!=b&&(this.height=b)},moveTo:function(a,b,c){this.x=null!=a?a:this.x,this.y=null!=b?b:this.y,this.z=null!=c?c:this.z},add:function(a){var b=a.name;if(null!=this.children[b])throw"SceneGraph: child with that name already exists: "+b;this.children[b]=a,a.parent=this}}),f=d(e,function(b){this.constructor=function(){b.constructor.call(this,"root"),this.properties=a}}),g=d(e,function(a){function c(c,d){if(a.constructor.call(this,c),this.properties={fill:"#000"},null!=d)b(this.properties,d);else if(null!=c&&"string"!=typeof c)throw"SceneGraph: invalid node name"}this.Group=d.extend(this,{constructor:c,type:"group"}),this.Rect=d.extend(this,{constructor:c,type:"rect"}),this.Text=d.extend(this,{constructor:function(a){c.call(this),this.properties.text=a},type:"text"})}),h=new f;return this.Shape=g,this.root=h,this};a.exports=e},function(a,b){(function(a){b.extend=function(a,b){var c={};for(var d in a)a.hasOwnProperty(d)&&(c[d]=a[d]);if(null!=b)for(var e in b)b.hasOwnProperty(e)&&(c[e]=b[e]);return c},b.cssProps=function(a){var b=[];for(var c in a)a.hasOwnProperty(c)&&b.push(c+":"+a[c]);return b.join(";")},b.encodeHtmlEntity=function(a){for(var b=[],c=0,d=a.length-1;d>=0;d--)c=a.charCodeAt(d),b.unshift(c>128?["&#",c,";"].join(""):a[d]);return b.join("")},b.getNodeArray=function(b){var c=null;return"string"==typeof b?c=document.querySelectorAll(b):a.NodeList&&b instanceof a.NodeList?c=b:a.Node&&b instanceof a.Node?c=[b]:a.HTMLCollection&&b instanceof a.HTMLCollection?c=b:b instanceof Array?c=b:null===b&&(c=[]),c},b.imageExists=function(a,b){var c=new Image;c.onerror=function(){b.call(this,!1)},c.onload=function(){b.call(this,!0)},c.src=a},b.decodeHtmlEntity=function(a){return a.replace(/&#(\d+);/g,function(a,b){return String.fromCharCode(b)})},b.dimensionCheck=function(a){var b={height:a.clientHeight,width:a.clientWidth};return b.height&&b.width?b:!1},b.truthy=function(a){return"string"==typeof a?"true"===a||"yes"===a||"1"===a||"on"===a||"✓"===a:!!a}}).call(b,function(){return this}())},function(a,b,c){var d=encodeURIComponent,e=decodeURIComponent,f=c(6),g=c(7),h=/(\w+)\[(\d+)\]/,i=/\w+\.\w+/;b.parse=function(a){if("string"!=typeof a)return{};if(a=f(a),""===a)return{};"?"===a.charAt(0)&&(a=a.slice(1));for(var b={},c=a.split("&"),d=0;d",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.2",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b)}(this,document); \ No newline at end of file diff --git a/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/js/jquery.min.js b/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/js/jquery.min.js new file mode 100644 index 00000000000..0f60b7bd0d9 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/js/jquery.min.js @@ -0,0 +1,5 @@ +/*! jQuery v1.11.3 | (c) 2005, 2015 jQuery Foundation, Inc. | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.3",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b="length"in a&&a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,aa=/[+~]/,ba=/'|\\/g,ca=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),da=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ea=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fa){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(ba,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+ra(o[l]);w=aa.test(a)&&pa(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",ea,!1):e.attachEvent&&e.attachEvent("onunload",ea)),p=!f(g),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?la(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ca,da),a[3]=(a[3]||a[4]||a[5]||"").replace(ca,da),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ca,da).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(ca,da),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return W.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(ca,da).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:oa(function(){return[0]}),last:oa(function(a,b){return[b-1]}),eq:oa(function(a,b,c){return[0>c?c+b:c]}),even:oa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:oa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:oa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:oa(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function sa(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function ta(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ua(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function va(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wa(a,b,c,d,e,f){return d&&!d[u]&&(d=wa(d)),e&&!e[u]&&(e=wa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ua(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:va(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=va(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=va(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sa(function(a){return a===b},h,!0),l=sa(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sa(ta(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wa(i>1&&ta(m),i>1&&ra(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xa(a.slice(i,e)),f>e&&xa(a=a.slice(e)),f>e&&ra(a))}m.push(c)}return ta(m)}function ya(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=va(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&ga.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,ya(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ca,da),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ca,da),aa.test(j[0].type)&&pa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&ra(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,aa.test(a)&&pa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1; + +return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML="
'; - print $langs->trans("AddContactIntoCategory").'  '; + print $langs->trans("AssignCategoryTo").'  '; print $form->selectContacts('', '', 'elemid'); print '
'; if ($permission) { - print ""; + print "id."'>"; print $langs->trans("DeleteFromCat"); print img_picto($langs->trans("DeleteFromCat"), 'unlink', '', false, 0, 0, '', 'paddingleft'); print ""; @@ -931,7 +935,7 @@ if ($type == Categorie::TYPE_ACCOUNT) { // Link to delete from category print ''; if ($permission) { - print ""; + print "id."'>"; print $langs->trans("DeleteFromCat"); print img_picto($langs->trans("DeleteFromCat"), 'unlink', '', false, 0, 0, '', 'paddingleft'); print ""; @@ -1009,7 +1013,7 @@ if ($type == Categorie::TYPE_PROJECT) { // Link to delete from category print ''; if ($permission) { - print ""; + print "id."'>"; print $langs->trans("DeleteFromCat"); print img_picto($langs->trans("DeleteFromCat"), 'unlink', '', false, 0, 0, '', 'paddingleft'); print ""; @@ -1081,7 +1085,7 @@ if ($type == Categorie::TYPE_USER) { // Link to delete from category print ''; if ($user->rights->user->user->creer) { - print ""; + print "id."'>"; print $langs->trans("DeleteFromCat"); print img_picto($langs->trans("DeleteFromCat"), 'unlink', '', false, 0, 0, '', 'paddingleft'); print ""; @@ -1140,7 +1144,7 @@ if ($type == Categorie::TYPE_WAREHOUSE) { // Link to delete from category print ''; if ($permission) { - print ""; + print "id."'>"; print $langs->trans("DeleteFromCat"); print img_picto($langs->trans("DeleteFromCat"), 'unlink', '', false, 0, 0, '', 'paddingleft'); print ""; @@ -1156,6 +1160,7 @@ if ($type == Categorie::TYPE_WAREHOUSE) { } } +// List of tickets if ($type == Categorie::TYPE_TICKET) { $permission = ($user->rights->categorie->creer || $user->rights->categorie->creer); @@ -1212,7 +1217,7 @@ if ($type == Categorie::TYPE_TICKET) { // Link to delete from category print ''; if ($permission) { - print ""; + print "id."'>"; print $langs->trans("DeleteFromCat"); print img_picto($langs->trans("DeleteFromCat"), 'unlink', '', false, 0, 0, '', 'paddingleft'); print ""; From 59b2412bc2d36a0c4435e01ee210385ea91432db Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 29 Jul 2022 12:52:27 +0200 Subject: [PATCH 356/826] Fix position of fields --- htdocs/contact/list.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/contact/list.php b/htdocs/contact/list.php index 8d60b37611f..a0091061adb 100644 --- a/htdocs/contact/list.php +++ b/htdocs/contact/list.php @@ -207,16 +207,16 @@ foreach ($object->fields as $key => $val) { } // Add none object fields to fields for list -$arrayfields['country.code_iso'] = array('label'=>"Country", 'position'=>22, 'checked'=>0); +$arrayfields['country.code_iso'] = array('label'=>"Country", 'position'=>66, 'checked'=>0); if (empty($conf->global->SOCIETE_DISABLE_CONTACTS)) { - $arrayfields['s.nom'] = array('label'=>"ThirdParty", 'position'=>25, 'checked'=>1); + $arrayfields['s.nom'] = array('label'=>"ThirdParty", 'position'=>113, 'checked'=> 1); } $arrayfields['unsubscribed'] = array( 'label'=>'No_Email', 'checked'=>0, 'enabled'=>(!empty($conf->mailing->enabled)), - 'position'=>41); + 'position'=>111); if (!empty($conf->socialnetworks->enabled)) { foreach ($socialnetworks as $key => $value) { From 3dc0e14f0e7956b36604c7282f252e00f47287ff Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Fri, 29 Jul 2022 13:04:04 +0200 Subject: [PATCH 357/826] Fix : HasRight on user.class.php for $permlevel2 --- htdocs/user/class/user.class.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 6fca728ee8b..f206d47bd24 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -775,16 +775,16 @@ class User extends CommonObject // For backward compatibility with old permissions called "lire", "creer", "create", "supprimer" // instead of "read", "write", "delete" if ($permlevel2 == 'read' && !empty($this->rights->$rightsPath->$permlevel1->lire)) { - return $this->rights->$rightsPath->lire; + return $this->rights->$rightsPath->$permlevel1->lire; } if ($permlevel2 == 'write' && !empty($this->rights->$rightsPath->$permlevel1->creer)) { - return $this->rights->$rightsPath->create; + return $this->rights->$rightsPath->$permlevel1->create; } if ($permlevel2 == 'write' && !empty($this->rights->$rightsPath->$permlevel1->create)) { - return $this->rights->$rightsPath->create; + return $this->rights->$rightsPath->$permlevel1->create; } if ($permlevel2 == 'delete' && !empty($this->rights->$rightsPath->$permlevel1->supprimer)) { - return $this->rights->$rightsPath->supprimer; + return $this->rights->$rightsPath->$permlevel1->supprimer; } } } else { From aca6b848d2d722b7d9db0fa0bd2b7631f8d6e2b8 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 29 Jul 2022 13:58:30 +0200 Subject: [PATCH 358/826] Picto --- htdocs/product/stock/index.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/product/stock/index.php b/htdocs/product/stock/index.php index 9aad5f382cc..6efe9f0d9e8 100644 --- a/htdocs/product/stock/index.php +++ b/htdocs/product/stock/index.php @@ -141,7 +141,7 @@ print '
'; $max = 10; $sql = "SELECT p.rowid, p.label as produit, p.tobatch, p.tosell, p.tobuy,"; $sql .= " e.ref as warehouse_ref, e.rowid as warehouse_id, e.ref as warehouse_label, e.lieu, e.statut as warehouse_status,"; -$sql .= " m.value as qty, m.datem, m.batch, m.eatby, m.sellby"; +$sql .= " m.rowid as mid, m.value as qty, m.datem, m.batch, m.eatby, m.sellby"; $sql .= " FROM ".MAIN_DB_PREFIX."entrepot as e"; $sql .= ", ".MAIN_DB_PREFIX."stock_mouvement as m"; $sql .= ", ".MAIN_DB_PREFIX."product as p"; @@ -200,7 +200,7 @@ if ($resql) { $tmplotstatic->eatby = $objp->eatby; print '
'.dol_print_date($db->jdate($objp->datem), 'dayhour').''.img_picto($langs->trans("Ref").' '.$objp->mid, 'movement', 'class="pictofixedwidth"').dol_print_date($db->jdate($objp->datem), 'dayhour').''; print $producttmp->getNomUrl(1); print "
'.$form->editfieldkey('Categories', 'usercats', '', $object, 0).''; $cate_arbo = $form->select_all_categories('user', null, 'parent', null, null, 1); print img_picto('', 'category', 'class="pictofixedwidth"').$form->multiselectarray('usercats', $cate_arbo, GETPOST('usercats', 'array'), 0, 0, 'maxwdith300 widthcentpercentminusx', 0, '90%'); @@ -1234,9 +1234,9 @@ if ($action == 'create' || $action == 'adduserldap') { print ''; print '
'.$langs->trans("Categories").''; print $form->showCategories($object->id, Categorie::TYPE_USER, 1); @@ -1804,7 +1804,7 @@ if ($action == 'create' || $action == 'adduserldap') { print '
'.$langs->trans("ApiKey").''; if (!empty($object->api_key)) { @@ -2369,7 +2369,7 @@ if ($action == 'create' || $action == 'adduserldap') { print "
'.$langs->trans("ApiKey").''; print ''; @@ -2566,7 +2566,7 @@ if ($action == 'create' || $action == 'adduserldap') { print '
'.$form->editfieldkey('Categories', 'usercats', '', $object, 0).''; print img_picto('', 'category', 'class="pictofixedwidth"'); @@ -2711,8 +2711,8 @@ if ($action == 'create' || $action == 'adduserldap') { // Sensitive salary/value information if ((empty($user->socid) && in_array($id, $childids)) // A user can always see salary/value information for its subordinates - || (!empty($conf->salaries->enabled) && !empty($user->rights->salaries->readall)) - || (!empty($conf->hrm->enabled) && !empty($user->rights->hrm->employee->read))) { + || (!empty($conf->salaries->enabled) && !empty($user->hasRight("salaries", "readall"))) + || (!empty($conf->hrm->enabled) && !empty($user->hasRight("hrm", "employee", "read")))) { $langs->load("salaries"); // Salary @@ -2803,8 +2803,8 @@ if ($action == 'create' || $action == 'adduserldap') { $filename = dol_sanitizeFileName($object->ref); $filedir = $conf->user->dir_output."/".dol_sanitizeFileName($object->ref); $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id; - $genallowed = $user->rights->user->user->lire; - $delallowed = $user->rights->user->user->creer; + $genallowed = $user->hasRight("user", "user", "read"); + $delallowed = $user->hasRight("user", "user", "write"); print $formfile->showdocuments('user', $filename, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', 0, '', empty($soc->default_lang) ? '' : $soc->default_lang); $somethingshown = $formfile->numoffiles; diff --git a/htdocs/user/document.php b/htdocs/user/document.php index ed1fe30df4e..31ec618a795 100644 --- a/htdocs/user/document.php +++ b/htdocs/user/document.php @@ -41,23 +41,23 @@ $ref = GETPOST('ref', 'alpha'); $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'userdoc'; // To manage different context of search // Define value to know what current user can do on users -$canadduser = (!empty($user->admin) || $user->rights->user->user->creer); -$canreaduser = (!empty($user->admin) || $user->rights->user->user->lire); -$canedituser = (!empty($user->admin) || $user->rights->user->user->creer); -$candisableuser = (!empty($user->admin) || $user->rights->user->user->supprimer); +$canadduser = (!empty($user->admin) || $user->hasRight("user", "user", "write")); +$canreaduser = (!empty($user->admin) || $user->hasRight("user", "user", "read")); +$canedituser = (!empty($user->admin) || $user->hasRight("user", "user", "write")); +$candisableuser = (!empty($user->admin) || $user->hasRight("user", "user", "delete")); $canreadgroup = $canreaduser; $caneditgroup = $canedituser; if (!empty($conf->global->MAIN_USE_ADVANCED_PERMS)) { - $canreadgroup = (!empty($user->admin) || $user->rights->user->group_advance->read); - $caneditgroup = (!empty($user->admin) || $user->rights->user->group_advance->write); + $canreadgroup = (!empty($user->admin) || $user->hasRight("user", "group_advance", "read")); + $caneditgroup = (!empty($user->admin) || $user->hasRight("user", "group_advance", "write")); } // Define value to know what current user can do on properties of edited user if ($id) { // $user est le user qui edite, $id est l'id de l'utilisateur edite - $caneditfield = ((($user->id == $id) && $user->rights->user->self->creer) - || (($user->id != $id) && $user->rights->user->user->creer)); - $caneditpassword = ((($user->id == $id) && $user->rights->user->self->password) - || (($user->id != $id) && $user->rights->user->user->password)); + $caneditfield = ((($user->id == $id) && $user->hasRight("user", "self", "write")) + || (($user->id != $id) && $user->hasRight("user", "user", "write"))); + $caneditpassword = ((($user->id == $id) && $user->hasRight("user", "self", "password")) + || (($user->id != $id) && $user->hasRight("user", "user", "passsword"))); } $permissiontoadd = $caneditfield; // Used by the include of actions_addupdatedelete.inc.php and actions_linkedfiles @@ -147,7 +147,7 @@ if ($object->id) { print dol_get_fiche_head($head, 'document', $langs->trans("User"), -1, 'user'); $linkback = ''; - if ($user->rights->user->user->lire || $user->admin) { + if ($user->hasRight("user", "user", "read") || $user->admin) { $linkback = ''.$langs->trans("BackToList").''; } @@ -155,7 +155,7 @@ if ($object->id) { $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; - dol_banner_tab($object, 'id', $linkback, $user->rights->user->user->lire || $user->admin, 'rowid', 'ref', $morehtmlref); + dol_banner_tab($object, 'id', $linkback, $user->hasRight("user", "user", "read") || $user->admin, 'rowid', 'ref', $morehtmlref); print '
'; print '
'; diff --git a/htdocs/user/group/card.php b/htdocs/user/group/card.php index 92d309e554b..9b6e9e1c317 100644 --- a/htdocs/user/group/card.php +++ b/htdocs/user/group/card.php @@ -32,16 +32,16 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; // Defini si peux lire/modifier utilisateurs et permisssions -$canreadperms = ($user->admin || $user->rights->user->user->lire); -$caneditperms = ($user->admin || $user->rights->user->user->creer); -$candisableperms = ($user->admin || $user->rights->user->user->supprimer); +$canreadperms = ($user->admin || $user->hasRight("user", "user", "read")); +$caneditperms = ($user->admin || $user->hasRight("user", "user", "write")); +$candisableperms = ($user->admin || $user->hasRight("user", "user", "delete")); $feature2 = 'user'; // Advanced permissions if (!empty($conf->global->MAIN_USE_ADVANCED_PERMS)) { - $canreadperms = ($user->admin || $user->rights->user->group_advance->read); - $caneditperms = ($user->admin || $user->rights->user->group_advance->write); - $candisableperms = ($user->admin || $user->rights->user->group_advance->delete); + $canreadperms = ($user->admin || $user->hasRight("user", "group_advance", "read")); + $caneditperms = ($user->admin || $user->hasRight("user", "group_advance", "write")); + $candisableperms = ($user->admin || $user->hasRight("user", "group_advance", "delete")); $feature2 = 'group_advance'; } @@ -238,7 +238,7 @@ if (empty($reshook)) { // Actions to build doc $upload_dir = $conf->user->dir_output.'/usergroups'; - $permissiontoadd = $user->rights->user->user->creer; + $permissiontoadd = $user->hasRight("user", "user", "write"); include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php'; } @@ -250,7 +250,7 @@ $title = $object->name.' - '.$langs->trans("Card"); if ($action == 'create') { $title = $langs->trans("NewGroup"); } - +$help_url = ""; llxHeader('', $title, $help_url); @@ -329,7 +329,7 @@ if ($action == 'create') { $linkback = ''.$langs->trans("BackToList").''; - dol_banner_tab($object, 'id', $linkback, $user->rights->user->user->lire || $user->admin); + dol_banner_tab($object, 'id', $linkback, $user->hasRight("user", "user", "read") || $user->admin); print '
'; print '
'; @@ -485,8 +485,8 @@ if ($action == 'create') { $filename = dol_sanitizeFileName($object->ref); $filedir = $conf->user->dir_output."/usergroups/".dol_sanitizeFileName($object->ref); $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id; - $genallowed = $user->rights->user->user->creer; - $delallowed = $user->rights->user->user->supprimer; + $genallowed = $user->hasRight("user", "user", "write"); + $delallowed = $user->hasRight("user", "user", "delete"); $somethingshown = $formfile->showdocuments('usergroup', $filename, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', 0, '', $mysoc->default_lang); diff --git a/htdocs/user/group/list.php b/htdocs/user/group/list.php index bb130b33e75..8f7f907eb7b 100644 --- a/htdocs/user/group/list.php +++ b/htdocs/user/group/list.php @@ -38,10 +38,10 @@ $massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choi $contextpage = GETPOST('optioncss', 'aZ09'); // Defini si peux lire/modifier utilisateurs et permisssions -$caneditperms = ($user->admin || $user->rights->user->user->creer); +$caneditperms = ($user->admin || $user->hasRight("user", "user", "write")); // Advanced permissions if (!empty($conf->global->MAIN_USE_ADVANCED_PERMS)) { - $caneditperms = ($user->admin || $user->rights->user->group_advance->write); + $caneditperms = ($user->admin || $user->hasRight("user", "group_advance", "write")); } // Load variable for pagination @@ -70,7 +70,7 @@ $fieldstosearchall = array( ); if (!empty($conf->global->MAIN_USE_ADVANCED_PERMS)) { - if (!$user->rights->user->group_advance->read && !$user->admin) { + if (!$user->hasRight("user", "group_advance", "read") && !$user->admin) { accessforbidden(); } } @@ -80,7 +80,7 @@ if (!empty($conf->multicompany->enabled) && $conf->entity > 1 && $conf->global-> accessforbidden(); } -if (!$user->rights->user->user->lire && !$user->admin) { +if (!$user->hasRight("user", "user", "read") && !$user->admin) { accessforbidden(); } @@ -121,6 +121,7 @@ if (empty($reshook)) { * View */ $title = $langs->trans("ListOfGroups"); +$help_url=""; llxHeader('', $title, $help_url); $sql = "SELECT g.rowid, g.nom as name, g.note, g.entity, g.datec, g.tms as datem, COUNT(DISTINCT ugu.fk_user) as nb, COUNT(DISTINCT ugr.fk_id) as nbpermissions"; diff --git a/htdocs/user/group/perms.php b/htdocs/user/group/perms.php index edf20d0884c..15fcc2a319f 100644 --- a/htdocs/user/group/perms.php +++ b/htdocs/user/group/perms.php @@ -50,15 +50,15 @@ if (!isset($id) || empty($id)) { } // Define if user can read permissions -$canreadperms = ($user->admin || $user->rights->user->user->lire); +$canreadperms = ($user->admin || $user->hasRight("user", "user", "read")); // Define if user can modify group permissions -$caneditperms = ($user->admin || $user->rights->user->user->creer); +$caneditperms = ($user->admin || $user->hasRight("user", "user", "write")); // Advanced permissions $advancedpermsactive = false; if (!empty($conf->global->MAIN_USE_ADVANCED_PERMS)) { $advancedpermsactive = true; - $canreadperms = ($user->admin || ($user->rights->user->group_advance->read && $user->rights->user->group_advance->readperms)); - $caneditperms = ($user->admin || $user->rights->user->group_advance->write); + $canreadperms = ($user->admin || ($user->hasRight("user", "group_advance", "read") && $user->hasRight("user", "group_advance", "readperms"))); + $caneditperms = ($user->admin || $user->hasRight("user", "group_advance", "write")); } // Security check @@ -206,7 +206,7 @@ if ($object->id > 0) { $linkback = ''.$langs->trans("BackToList").''; - dol_banner_tab($object, 'id', $linkback, $user->rights->user->user->lire || $user->admin); + dol_banner_tab($object, 'id', $linkback, $user->hasRight("user", "user", "read") || $user->admin); print '
'; print '
'; diff --git a/htdocs/user/hierarchy.php b/htdocs/user/hierarchy.php index 92d0490f1c6..3f8326d3b7b 100644 --- a/htdocs/user/hierarchy.php +++ b/htdocs/user/hierarchy.php @@ -60,9 +60,9 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter', $userstatic = new User($db); // Define value to know what current user can do on users -$canadduser = (!empty($user->admin) || $user->rights->user->user->creer); +$canadduser = (!empty($user->admin) || $user->hasRight("user", "user", "write")); -if (!$user->rights->user->user->lire && !$user->admin) { +if (!$user->hasRight("user", "user", "read") && !$user->admin) { accessforbidden(); } diff --git a/htdocs/user/list.php b/htdocs/user/list.php index a47fa7a51c2..f0196789e25 100644 --- a/htdocs/user/list.php +++ b/htdocs/user/list.php @@ -131,7 +131,7 @@ $arrayfields = array( 'u.email'=>array('label'=>"EMail", 'checked'=>1, 'position'=>35), 'u.api_key'=>array('label'=>"ApiKey", 'checked'=>0, 'position'=>40, "enabled"=>(!empty($conf->api->enabled) && $user->admin)), 'u.fk_soc'=>array('label'=>"Company", 'checked'=>($contextpage == 'employeelist' ? 0 : 1), 'position'=>45), - 'u.salary'=>array('label'=>"Salary", 'checked'=>1, 'position'=>80, 'enabled'=>(!empty($conf->salaries->enabled) && !empty($user->rights->salaries->readall))), + 'u.salary'=>array('label'=>"Salary", 'checked'=>1, 'position'=>80, 'enabled'=>(!empty($conf->salaries->enabled) && !empty($user->hasRight("salaries", "readall")))), 'u.datelastlogin'=>array('label'=>"LastConnexion", 'checked'=>1, 'position'=>100), 'u.datepreviouslogin'=>array('label'=>"PreviousConnexion", 'checked'=>0, 'position'=>110), 'u.datec'=>array('label'=>"DateCreation", 'checked'=>0, 'position'=>500), @@ -174,26 +174,26 @@ if ($mode == 'employee' && !GETPOSTISSET('search_employee')) { } // Define value to know what current user can do on users -$permissiontoadd = (!empty($user->admin) || $user->rights->user->user->creer); -$canreaduser = (!empty($user->admin) || $user->rights->user->user->lire); -$canedituser = (!empty($user->admin) || $user->rights->user->user->creer); -$candisableuser = (!empty($user->admin) || $user->rights->user->user->supprimer); +$permissiontoadd = (!empty($user->admin) || $user->hasRight("user", "user", "write")); +$canreaduser = (!empty($user->admin) || $user->hasRight("user", "user", "read")); +$canedituser = (!empty($user->admin) || $user->hasRight("user", "user", "write")); +$candisableuser = (!empty($user->admin) || $user->hasRight("user", "user", "delete")); $canreadgroup = $canreaduser; $caneditgroup = $canedituser; if (!empty($conf->global->MAIN_USE_ADVANCED_PERMS)) { - $canreadgroup = (!empty($user->admin) || $user->rights->user->group_advance->read); - $caneditgroup = (!empty($user->admin) || $user->rights->user->group_advance->write); + $canreadgroup = (!empty($user->admin) || $user->hasRight("user", "group_advance", "read")); + $caneditgroup = (!empty($user->admin) || $user->hasRight("user", "group_advance", "write")); } $error = 0; // Permission to list if ($mode == 'employee') { - if (empty($user->rights->salaries->read)) { + if (empty($user->hasRight("salaries", "read"))) { accessforbidden(); } } else { - if (empty($user->rights->user->user->lire) && empty($user->admin)) { + if (empty($user->hasRight("user", "user", "read")) && empty($user->admin)) { accessforbidden(); } } @@ -441,7 +441,7 @@ if ($search_categ == -2) { if ($search_warehouse > 0) { $sql .= " AND u.fk_warehouse = ".((int) $search_warehouse); } -if ($mode == 'employee' && empty($user->rights->salaries->readall)) { +if ($mode == 'employee' && empty($user->hasRight("salaries", "readall"))) { $sql .= " AND u.rowid IN (".$db->sanitize(join(',', $childids)).")"; } // Add where from extra fields @@ -658,7 +658,7 @@ $moreforfilter = ''; $moreforfilter.= '
';*/ // Filter on categories -if (!empty($conf->categorie->enabled) && $user->rights->categorie->lire) { +if (!empty($conf->categorie->enabled) && $user->hasRight("categorie", "read")) { $moreforfilter .= '
'; $tmptitle = $langs->trans('Category'); $moreforfilter .= img_picto($langs->trans("Category"), 'category', 'class="pictofixedwidth"').$formother->select_categories(Categorie::TYPE_USER, $search_categ, 'search_categ', 1, $tmptitle); @@ -939,9 +939,9 @@ while ($i < $imaxinloop) { $li = $object->getNomUrl(-1, '', 0, 0, 24, 1, 'login', '', 1); $canreadhrmdata = 0; - if ((!empty($conf->salaries->enabled) && !empty($user->rights->salaries->read) && in_array($obj->rowid, $childids)) - || (!empty($conf->salaries->enabled) && !empty($user->rights->salaries->readall)) - || (!empty($conf->hrm->enabled) && !empty($user->rights->hrm->employee->read))) { + if ((!empty($conf->salaries->enabled) && !empty($user->hasRight("salaries", "read")) && in_array($obj->rowid, $childids)) + || (!empty($conf->salaries->enabled) && !empty($user->hasRight("salaries", "readall"))) + || (!empty($conf->hrm->enabled) && !empty($user->hasRight("hrm", "employee", "read")))) { $canreadhrmdata = 1; } $canreadsecretapi = 0; diff --git a/htdocs/user/note.php b/htdocs/user/note.php index 2aeb496c20f..2b1e02b1376 100644 --- a/htdocs/user/note.php +++ b/htdocs/user/note.php @@ -39,7 +39,7 @@ $object->fetch($id, '', '', 1); $object->getrights(); // If user is not user read and no permission to read other users, we stop -if (($object->id != $user->id) && (!$user->rights->user->user->lire)) { +if (($object->id != $user->id) && (!$user->hasRight("user", "user", "read"))) { accessforbidden(); } @@ -48,7 +48,7 @@ $socid = 0; if ($user->socid > 0) { $socid = $user->socid; } -$feature2 = (($socid && $user->rights->user->self->creer) ? '' : 'user'); +$feature2 = (($socid && $user->hasRight("user", "self", "write")) ? '' : 'user'); $result = restrictedArea($user, 'user', $id, 'user&user', $feature2); @@ -67,7 +67,7 @@ if ($reshook < 0) { } if (empty($reshook)) { - if ($action == 'update' && $user->rights->user->user->creer && !GETPOST("cancel")) { + if ($action == 'update' && $user->hasRight("user", "user", "write") && !GETPOST("cancel")) { $db->begin(); $res = $object->update_note(dol_html_entity_decode(GETPOST('note_private', 'restricthtml'), ENT_QUOTES | ENT_HTML5)); @@ -99,7 +99,7 @@ if ($id) { $linkback = ''; - if ($user->rights->user->user->lire || $user->admin) { + if ($user->hasRight("user", "user", "read") || $user->admin) { $linkback = ''.$langs->trans("BackToList").''; } @@ -107,7 +107,7 @@ if ($id) { $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; - dol_banner_tab($object, 'id', $linkback, $user->rights->user->user->lire || $user->admin, 'rowid', 'ref', $morehtmlref); + dol_banner_tab($object, 'id', $linkback, $user->hasRight("user", "user", "read") || $user->admin, 'rowid', 'ref', $morehtmlref); print '
'; @@ -138,7 +138,7 @@ if ($id) { } print '
'.$langs->trans("Note").''.price($obj->total_ht)."'.price($obj->total_ht)."'; print $langs->trans("DatabaseName").' : '.$dolibarr_main_db_name.'
'; print '
'; +print '
'; print ''; + print ''; print ''; print ''; + print ''; -print ''; - // OAUTH - if (!empty($conf->use_javascript_ajax) || (isset($conf->global->MAIN_MAIL_SENDMODE) && in_array($conf->global->MAIN_MAIL_SENDMODE, array('smtps', 'swiftmailer')))) { - print ''; - } - // Port print ''; } + + // OAUTH + if (!empty($conf->use_javascript_ajax) || (isset($conf->global->MAIN_MAIL_SENDMODE) && in_array($conf->global->MAIN_MAIL_SENDMODE, array('smtps', 'swiftmailer')))) { + print ''; + } + // PW if (!empty($conf->use_javascript_ajax) || (isset($conf->global->MAIN_MAIL_SENDMODE) && in_array($conf->global->MAIN_MAIL_SENDMODE, array('smtps', 'swiftmailer')))) { $mainsmtppw = (!empty($conf->global->MAIN_MAIL_SMTPS_PW) ? $conf->global->MAIN_MAIL_SMTPS_PW : ''); @@ -493,7 +497,7 @@ if ($action == 'edit') { // OAUTH service provider if (!empty($conf->use_javascript_ajax) || (isset($conf->global->MAIN_MAIL_SENDMODE) && in_array($conf->global->MAIN_MAIL_SENDMODE, array('smtps')))) { - print ''; } - // Use OAUTH - if (isset($conf->global->MAIN_MAIL_SENDMODE) && in_array($conf->global->MAIN_MAIL_SENDMODE, array('smtps'))) { - print ''; - } // Port if ($linuxlike && (isset($conf->global->MAIN_MAIL_SENDMODE) && $conf->global->MAIN_MAIL_SENDMODE == 'mail')) { @@ -697,13 +697,20 @@ if ($action == 'edit') { print ''; } + // AUTH method + if (isset($conf->global->MAIN_MAIL_SENDMODE) && in_array($conf->global->MAIN_MAIL_SENDMODE, array('smtps'))) { + $authtype = $conf->global->MAIN_MAIL_SMTPS_AUTH_TYPE; + $text = ($authtype === "LOGIN") ? $langs->trans("UsePassword") : ($authtype === "XOAUTH2" ? $langs->trans("UseOauth") : '') ; + print ''; + } + // SMTPS PW - if (isset($conf->global->MAIN_MAIL_SENDMODE) && in_array($conf->global->MAIN_MAIL_SENDMODE, array('smtps', 'swiftmailer')) && (!(isset($conf->global->MAIL_SMTP_AUTH_TYPE) && $conf->global->MAIL_SMTP_AUTH_TYPE === "XOAUTH2"))) { + if (isset($conf->global->MAIN_MAIL_SENDMODE) && (in_array($conf->global->MAIN_MAIL_SENDMODE, array('swiftmailer')) || (in_array($conf->global->MAIN_MAIL_SENDMODE, array('smtps')) && (isset($conf->global->MAIN_MAIL_SMTPS_AUTH_TYPE) && $conf->global->MAIN_MAIL_SMTPS_AUTH_TYPE === "LOGIN")))) { print ''; } // SMTPS oauth service - if (isset($conf->global->MAIL_SMTP_AUTH_TYPE) && $conf->global->MAIL_SMTP_AUTH_TYPE === "XOAUTH2") { + if (isset($conf->global->MAIN_MAIL_SENDMODE) && in_array($conf->global->MAIN_MAIL_SENDMODE, array('smtps')) && isset($conf->global->MAIN_MAIL_SMTPS_AUTH_TYPE) && $conf->global->MAIN_MAIL_SMTPS_AUTH_TYPE === "XOAUTH2") { $text = $oauthservices[$conf->global->MAIN_MAIL_SMTPS_OAUTH_SERVICE]; if (empty($text)) { $text = $langs->trans("Undefined").img_warning(); diff --git a/htdocs/core/class/CMailFile.class.php b/htdocs/core/class/CMailFile.class.php index 24c27b47795..de2a44070fc 100644 --- a/htdocs/core/class/CMailFile.class.php +++ b/htdocs/core/class/CMailFile.class.php @@ -658,7 +658,7 @@ class CMailFile } $keyforsmtpserver = 'MAIN_MAIL_SMTP_SERVER'; - $keyforsmtpuseoauth = "MAIN_MAIL_SMTPS_USE_OAUTH"; + $keyforsmtpauthtype = "MAIN_MAIL_SMTPS_AUTH_TYPE"; $keyforsmtpoauthservice = "MAIN_MAIL_SMTPS_OAUTH_SERVICE"; $keyforsmtpport = 'MAIN_MAIL_SMTP_PORT'; $keyforsmtpid = 'MAIN_MAIL_SMTPS_ID'; @@ -835,7 +835,7 @@ class CMailFile $this->smtps->setPW($loginpass); } - if (!empty($conf->global->$keyforsmtpuseoauth)) { + if (!empty($conf->global->$keyforsmtpauthtype) && $conf->global->$keyforsmtpauthtype === "XOAUTH2") { require_once DOL_DOCUMENT_ROOT.'/core/lib/oauth.lib.php'; // define $supportedoauth2array $keyforsupportedoauth2array = $conf->global->$keyforsmtpoauthservice; if (preg_match('/^.*-/', $keyforsupportedoauth2array)) { diff --git a/htdocs/core/class/smtps.class.php b/htdocs/core/class/smtps.class.php index 05248e89143..06ada5c4911 100644 --- a/htdocs/core/class/smtps.class.php +++ b/htdocs/core/class/smtps.class.php @@ -570,13 +570,13 @@ class SMTPs } // Default authentication method is LOGIN - if (empty($conf->global->MAIL_SMTP_AUTH_TYPE)) { - $conf->global->MAIL_SMTP_AUTH_TYPE = 'LOGIN'; + if (empty($conf->global->MAIN_MAIL_SMTPS_AUTH_TYPE)) { + $conf->global->MAIN_MAIL_SMTPS_AUTH_TYPE = 'LOGIN'; } // Send Authentication to Server // Check for errors along the way - switch ($conf->global->MAIL_SMTP_AUTH_TYPE) { + switch ($conf->global->MAIN_MAIL_SMTPS_AUTH_TYPE) { case 'NONE': // Do not send the 'AUTH type' message. For test purpose, if you don't need authentication, it is better to not enter login/pass into setup. $_retVal = true; diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index e5b8fe597bc..d629bbc0fbf 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -2287,7 +2287,9 @@ NoName=No name ShowAdvancedOptions= Show advanced options HideAdvancedoptions= Hide advanced options CIDLookupURL=The module brings an URL that can be used by an external tool to get the name of a thirdparty or contact from its phone number. URL to use is: -MAIN_MAIL_SMTPS_USE_OAUTH=Use OAUTH2 authentication -OauthNotAvailableForAll=OAUTH2 authentication is not available for all hosts +OauthNotAvailableForAllAndHadToBeCreatedBefore=OAUTH2 authentication is not available for all hosts, and a token with the right permissions must have been created upstream with the OAUTH module MAIN_MAIL_SMTPS_OAUTH_SERVICE=OAUTH2 authentication service -DontForgetCreateTokenOauthMod=A token with the right permissions must have been created upstream with the OAUTH module \ No newline at end of file +DontForgetCreateTokenOauthMod=A token with the right permissions must have been created upstream with the OAUTH module +MAIN_MAIL_SMTPS_AUTH_TYPE=Authentification method +UsePassword=Use a password +UseOauth=Use a OAUTH token \ No newline at end of file diff --git a/htdocs/langs/fr_FR/admin.lang b/htdocs/langs/fr_FR/admin.lang index 6302377b449..42d973e8e06 100644 --- a/htdocs/langs/fr_FR/admin.lang +++ b/htdocs/langs/fr_FR/admin.lang @@ -2287,7 +2287,9 @@ ShowAdvancedOptions= Show advanced options HideAdvancedoptions= Hide advanced options CIDLookupURL=The module brings an URL that can be used by an external tool to get the name of a thirdparty or contact from its phone number. URL to use is: DoesNotWorkWithAllThemes=Ne fonctionne pas avec tous les thèmes -MAIN_MAIL_SMTPS_USE_OAUTH=Utilisation de l'authentification OAUTH2 -OauthNotAvailableForAll=L'authentification OAUTH2 n'est pas disponible pour tous les hôtes +OauthNotAvailableForAllAndHadToBeCreatedBefore=L'authentification OAUTH2 n'est pas disponible pour tous les hôtes, de plus, un jeton avec les bonnes permissions doit avoir été créé en amont avec le module OAUTH MAIN_MAIL_SMTPS_OAUTH_SERVICE=Service d'authentification OAUTH2 DontForgetCreateTokenOauthMod=Un jeton avec les bonnes permissions doit avoir été créé en amont avec le module OAUTH +MAIN_MAIL_SMTPS_AUTH_TYPE=Méthode d'authentication +UsePassword=Utiliser un mot de pass +UseOauth=Utiliser un jeton d'authentification OAUTH \ No newline at end of file From f06de750ebca84dc7e2e8b92754665373b997273 Mon Sep 17 00:00:00 2001 From: Faustin Date: Wed, 3 Aug 2022 21:14:38 +0200 Subject: [PATCH 425/826] oauth provider now showed in small caps --- htdocs/admin/mails.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/admin/mails.php b/htdocs/admin/mails.php index 6b09c211414..9145ad9a1a7 100644 --- a/htdocs/admin/mails.php +++ b/htdocs/admin/mails.php @@ -192,6 +192,7 @@ foreach ($conf->global as $key => $val) { $name = $langs->trans("NoName"); } $provider = preg_replace('/-.*$/', '', $key); + $provider = ucfirst(strtolower($provider)); $oauthservices[$key] = $name." (".$provider.")"; } From 3108cd12fb1eda63d7d18601cb61c9cf1d57ef9e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 3 Aug 2022 21:30:40 +0200 Subject: [PATCH 426/826] Fix export of website --- htdocs/core/modules/modWebsite.class.php | 15 ++++++++++++++- htdocs/website/class/website.class.php | 10 ++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/htdocs/core/modules/modWebsite.class.php b/htdocs/core/modules/modWebsite.class.php index e27e7a2f6b0..6e0dc80e41c 100644 --- a/htdocs/core/modules/modWebsite.class.php +++ b/htdocs/core/modules/modWebsite.class.php @@ -164,6 +164,8 @@ class modWebsite extends DolibarrModules { global $conf, $langs; + $error = 0; + $result = $this->_load_tables('/install/mysql/', 'website'); if ($result < 0) { return -1; // Do not activate module if error 'not allowed' returned when loading module SQL queries (the _load_table run sql with run_sql with the error allowed parameter set to 'default') @@ -185,11 +187,16 @@ class modWebsite extends DolibarrModules if ($result < 0) { $langs->load("errors"); $this->error = $langs->trans('ErrorFailToCopyDir', $src, $dest); - return 0; + $this->errors[] = $langs->trans('ErrorFailToCopyDir', $src, $dest); + $error++; } } } + if ($error) { + return 0; + } + // Website templates $srcroot = DOL_DOCUMENT_ROOT.'/install/doctemplates/websites'; $destroot = DOL_DATA_ROOT.'/doctemplates/websites'; @@ -205,9 +212,15 @@ class modWebsite extends DolibarrModules if ($result < 0) { $langs->load("errors"); $this->error = $langs->trans('ErrorFailToCopyFile', $src, $dest); + $this->errors[] = $langs->trans('ErrorFailToCopyFile', $src, $dest); + $error++; } } + if ($error) { + return 0; + } + $sql = array(); return $this->_init($sql, $options); diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index 0e062b038a0..aa405861e6a 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -1059,29 +1059,35 @@ class Website extends CommonObject $line .= "'".$this->db->escape($objectpageold->grabbed_from)."', "; $line .= "'".$this->db->escape($objectpageold->type_container)."', "; + // Make substitution with a generic path into htmlheader content $stringtoexport = $objectpageold->htmlheader; $stringtoexport = str_replace(array("\r\n", "\r", "\n"), "__N__", $stringtoexport); $stringtoexport = str_replace('file=image/'.$website->ref.'/', "file=image/__WEBSITE_KEY__/", $stringtoexport); $stringtoexport = str_replace('file=js/'.$website->ref.'/', "file=js/__WEBSITE_KEY__/", $stringtoexport); $stringtoexport = str_replace('medias/image/'.$website->ref.'/', "medias/image/__WEBSITE_KEY__/", $stringtoexport); $stringtoexport = str_replace('medias/js/'.$website->ref.'/', "medias/js/__WEBSITE_KEY__/", $stringtoexport); + $stringtoexport = str_replace('file=logos%2Fthumbs%2F'.$mysoc->logo_small, "file=logos%2Fthumbs%2F__LOGO_SMALL_KEY__", $stringtoexport); $stringtoexport = str_replace('file=logos%2Fthumbs%2F'.$mysoc->logo_mini, "file=logos%2Fthumbs%2F__LOGO_MINI_KEY__", $stringtoexport); $stringtoexport = str_replace('file=logos%2Fthumbs%2F'.$mysoc->logo, "file=logos%2Fthumbs%2F__LOGO_KEY__", $stringtoexport); $line .= "'".$this->db->escape(str_replace(array("\r\n", "\r", "\n"), "__N__", $stringtoexport))."', "; // Replace \r \n to have record on 1 line + // Make substitution with a generic path into page content $stringtoexport = $objectpageold->content; $stringtoexport = str_replace(array("\r\n", "\r", "\n"), "__N__", $stringtoexport); $stringtoexport = str_replace('file=image/'.$website->ref.'/', "file=image/__WEBSITE_KEY__/", $stringtoexport); $stringtoexport = str_replace('file=js/'.$website->ref.'/', "file=js/__WEBSITE_KEY__/", $stringtoexport); $stringtoexport = str_replace('medias/image/'.$website->ref.'/', "medias/image/__WEBSITE_KEY__/", $stringtoexport); $stringtoexport = str_replace('medias/js/'.$website->ref.'/', "medias/js/__WEBSITE_KEY__/", $stringtoexport); + $stringtoexport = str_replace('"image/'.$website->ref.'/', '"image/__WEBSITE_KEY__/', $stringtoexport); // When we have a link src="image/websiteref/file.png" into html content + $stringtoexport = str_replace('"/image/'.$website->ref.'/', '"/image/__WEBSITE_KEY__/', $stringtoexport); // When we have a link src="/image/websiteref/file.png" into html content + $stringtoexport = str_replace('"js/'.$website->ref.'/', '"js/__WEBSITE_KEY__/', $stringtoexport); + $stringtoexport = str_replace('"/js/'.$website->ref.'/', '"/js/__WEBSITE_KEY__/', $stringtoexport); + $stringtoexport = str_replace('file=logos%2Fthumbs%2F'.$mysoc->logo_small, "file=logos%2Fthumbs%2F__LOGO_SMALL_KEY__", $stringtoexport); $stringtoexport = str_replace('file=logos%2Fthumbs%2F'.$mysoc->logo_mini, "file=logos%2Fthumbs%2F__LOGO_MINI_KEY__", $stringtoexport); $stringtoexport = str_replace('file=logos%2Fthumbs%2F'.$mysoc->logo, "file=logos%2Fthumbs%2F__LOGO_KEY__", $stringtoexport); - // When we have a link src="image/websiteref/file.png" into html content - $stringtoexport = str_replace('="image/'.$website->ref.'/', '="image/__WEBSITE_KEY__/', $stringtoexport); $line .= "'".$this->db->escape($stringtoexport)."', "; // Replace \r \n to have record on 1 line $line .= "'".$this->db->escape($objectpageold->author_alias)."', "; From f731fcc7d18727b4cc28fc49c412b79a6392dbd5 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 3 Aug 2022 21:30:59 +0200 Subject: [PATCH 427/826] Use good format for image templates --- .../websites/website_template-style03.jpg | Bin 0 -> 96899 bytes .../websites/website_template-style03.png | Bin 101033 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 htdocs/install/doctemplates/websites/website_template-style03.jpg delete mode 100644 htdocs/install/doctemplates/websites/website_template-style03.png diff --git a/htdocs/install/doctemplates/websites/website_template-style03.jpg b/htdocs/install/doctemplates/websites/website_template-style03.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1479f08b5d9074d62566bde6922a6b74fa49ab64 GIT binary patch literal 96899 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 T>%|y*8c18fAAsq@KOg@e9)D$= literal 0 HcmV?d00001 diff --git a/htdocs/install/doctemplates/websites/website_template-style03.png b/htdocs/install/doctemplates/websites/website_template-style03.png deleted file mode 100644 index 7732f9f3c18a35ea96d0aaf8fd17e025ca60a189..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 101033 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 d;yVj%i|%V~D7$I0(R*Ph{vSjX1dIRx From a60a8d5057568f12950fe5b290b1772941f9875e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 4 Aug 2022 00:10:18 +0200 Subject: [PATCH 428/826] sql error --- htdocs/fourn/facture/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/fourn/facture/list.php b/htdocs/fourn/facture/list.php index ce3ad5b708e..0a54792c665 100644 --- a/htdocs/fourn/facture/list.php +++ b/htdocs/fourn/facture/list.php @@ -635,7 +635,7 @@ if (!$search_all) { $sql .= ' f.fk_multicurrency, f.multicurrency_code, f.multicurrency_tx, f.multicurrency_total_ht, f.multicurrency_total_tva, f.multicurrency_total_ttc,'; $sql .= " f.note_public, f.note_private,"; $sql .= " f.fk_user_author,"; - $sql .= ' s.rowid, s.nom, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur,'; + $sql .= ' s.rowid, s.nom, s.name_alias, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur,'; $sql .= " typent.code,"; $sql .= " state.code_departement, state.nom,"; $sql .= ' country.code,'; From b6ff439964b76eac460fa1a3bae33ab53cfcd8dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Thu, 4 Aug 2022 09:14:34 +0200 Subject: [PATCH 429/826] catch all errors --- htdocs/core/actions_sendmails.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/actions_sendmails.inc.php b/htdocs/core/actions_sendmails.inc.php index f0ef66eb78b..7494f5a3668 100644 --- a/htdocs/core/actions_sendmails.inc.php +++ b/htdocs/core/actions_sendmails.inc.php @@ -361,7 +361,7 @@ if (($action == 'send' || $action == 'relance') && !GETPOST('addfile') && !GETPO } $mailfile = new CMailFile($subject, $sendto, $from, $message, $filepath, $mimetype, $filename, $sendtocc, $sendtobcc, $deliveryreceipt, -1, '', '', $trackid, '', $sendcontext); - if ($mailfile->error) { + if (!empty($mailfile->error) || !empty($mailfile->errors)) { setEventMessages($mailfile->error, $mailfile->errors, 'errors'); $action = 'presend'; } else { From 32ac59622c6c6bd0e7a8a650dd237e283d7d7832 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Thu, 4 Aug 2022 09:24:57 +0200 Subject: [PATCH 430/826] Update CMailFile.class.php --- htdocs/core/class/CMailFile.class.php | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/htdocs/core/class/CMailFile.class.php b/htdocs/core/class/CMailFile.class.php index 7acd7ac3db0..08f883a388f 100644 --- a/htdocs/core/class/CMailFile.class.php +++ b/htdocs/core/class/CMailFile.class.php @@ -470,12 +470,12 @@ class CMailFile $emailMatchs = preg_match_all($regexp, $from, $adressEmailFrom); $adressEmailFrom = reset($adressEmailFrom); if ($emailMatchs !== false && filter_var($conf->global->MAIN_MAIL_SMTPS_ID, FILTER_VALIDATE_EMAIL) && $conf->global->MAIN_MAIL_SMTPS_ID !== $adressEmailFrom) { - $result = $this->message->setFrom($conf->global->MAIN_MAIL_SMTPS_ID); + $this->message->setFrom($conf->global->MAIN_MAIL_SMTPS_ID); } else { - $result = $this->message->setFrom($this->getArrayAddress($this->addr_from)); + $this->message->setFrom($this->getArrayAddress($this->addr_from)); } } else { - $result = $this->message->setFrom($this->getArrayAddress($this->addr_from)); + $this->message->setFrom($this->getArrayAddress($this->addr_from)); } } catch (Exception $e) { $this->errors[] = $e->getMessage(); @@ -485,7 +485,7 @@ class CMailFile // Set the To addresses with an associative array if (!empty($this->addr_to)) { try { - $result = $this->message->setTo($this->getArrayAddress($this->addr_to)); + $this->message->setTo($this->getArrayAddress($this->addr_to)); } catch (Exception $e) { $this->errors[] = $e->getMessage(); } @@ -493,14 +493,14 @@ class CMailFile if (!empty($this->reply_to)) { try { - $result = $this->message->SetReplyTo($this->getArrayAddress($this->reply_to)); + $this->message->SetReplyTo($this->getArrayAddress($this->reply_to)); } catch (Exception $e) { $this->errors[] = $e->getMessage(); } } try { - $result = $this->message->setCharSet($conf->file->character_set_client); + $this->message->setCharSet($conf->file->character_set_client); } catch (Exception $e) { $this->errors[] = $e->getMessage(); } @@ -562,7 +562,11 @@ class CMailFile } //if (! empty($this->errors_to)) $this->message->setErrorsTo($this->getArrayAddress($this->errors_to)); if (isset($this->deliveryreceipt) && $this->deliveryreceipt == 1) { - $this->message->setReadReceiptTo($this->getArrayAddress($this->addr_from)); + try { + $this->message->setReadReceiptTo($this->getArrayAddress($this->addr_from)); + } catch (Exception $e) { + $this->errors[] = $e->getMessage(); + } } } else { // Send mail method not correctly defined From e742ba45e8ef988dce57d9e061a9c337fa0951a2 Mon Sep 17 00:00:00 2001 From: Franck Lauby Date: Thu, 4 Aug 2022 09:45:00 +0200 Subject: [PATCH 431/826] Eldy's suggestion: replace hidden option with hardcoded '1' --- htdocs/core/class/html.formticket.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/class/html.formticket.class.php b/htdocs/core/class/html.formticket.class.php index 05ecdf3a005..d523fa83953 100644 --- a/htdocs/core/class/html.formticket.class.php +++ b/htdocs/core/class/html.formticket.class.php @@ -210,7 +210,7 @@ class FormTicket // Type print ''; // Group @@ -219,12 +219,12 @@ class FormTicket if ($public) { $filter = 'public=1'; } - $this->selectGroupTickets((GETPOST('category_code') ? GETPOST('category_code') : $this->category_code), 'category_code', $filter, 2, $conf->global->TICKET_FORCE_DISPLAY_EMPTY_OPTION, 0, 0, 'minwidth200'); + $this->selectGroupTickets((GETPOST('category_code') ? GETPOST('category_code') : $this->category_code), 'category_code', $filter, 2, 1, 0, 0, 'minwidth200'); print ''; // Severity print ''; // Subject From 6e6982d365c11fceabc6b3e304d9e7f73f1dfc89 Mon Sep 17 00:00:00 2001 From: Eric Seigne Date: Thu, 4 Aug 2022 09:49:44 +0200 Subject: [PATCH 432/826] new #21654: add bank account number used on invoices for debit --- htdocs/core/modules/facture/doc/pdf_crabe.modules.php | 8 ++++++++ htdocs/core/modules/facture/doc/pdf_sponge.modules.php | 8 ++++++++ htdocs/langs/en_US/bills.lang | 3 ++- htdocs/langs/fr_FR/bills.lang | 1 + 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php index ee45641c57e..71381e24e68 100644 --- a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php @@ -1089,6 +1089,14 @@ class pdf_crabe extends ModelePDFFactures $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posxval, $posy); $lib_mode_reg = $outputlangs->transnoentities("PaymentType".$object->mode_reglement_code) != ('PaymentType'.$object->mode_reglement_code) ? $outputlangs->transnoentities("PaymentType".$object->mode_reglement_code) : $outputlangs->convToOutputCharset($object->mode_reglement); + //#21654: add account number used for the debit + if ($object->mode_reglement_code == "PRE") { + require_once DOL_DOCUMENT_ROOT.'/societe/class/companybankaccount.class.php'; + $bac = new CompanyBankAccount($this->db); + $bac->fetch(0, $object->thirdparty->id); + $iban= $bac->iban.(($bac->iban && $bac->bic) ? ' / ' : '').$bac->bic; + $lib_mode_reg .= $langs->trans("PaymentTypePREdetails", dol_trunc($iban, 6, 'right', 'UTF-8', 1)); + } $pdf->MultiCell(80, 5, $lib_mode_reg, 0, 'L'); // Show online payment link diff --git a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php index 1bbbb2c9f3f..99606bf9100 100644 --- a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php @@ -1174,6 +1174,14 @@ class pdf_sponge extends ModelePDFFactures $pdf->SetFont('', '', $default_font_size - 2); $pdf->SetXY($posxval, $posy); $lib_mode_reg = $outputlangs->transnoentities("PaymentType".$object->mode_reglement_code) != ('PaymentType'.$object->mode_reglement_code) ? $outputlangs->transnoentities("PaymentType".$object->mode_reglement_code) : $outputlangs->convToOutputCharset($object->mode_reglement); + //#21654: add account number used for the debit + if ($object->mode_reglement_code == "PRE") { + require_once DOL_DOCUMENT_ROOT.'/societe/class/companybankaccount.class.php'; + $bac = new CompanyBankAccount($this->db); + $bac->fetch(0, $object->thirdparty->id); + $iban= $bac->iban.(($bac->iban && $bac->bic) ? ' / ' : '').$bac->bic; + $lib_mode_reg .= $langs->trans("PaymentTypePREdetails", dol_trunc($iban, 6, 'right', 'UTF-8', 1)); + } $pdf->MultiCell(80, 5, $lib_mode_reg, 0, 'L'); // Show online payment link diff --git a/htdocs/langs/en_US/bills.lang b/htdocs/langs/en_US/bills.lang index 68e01da9cf2..203520d44d8 100644 --- a/htdocs/langs/en_US/bills.lang +++ b/htdocs/langs/en_US/bills.lang @@ -426,6 +426,7 @@ VarAmountAllLines=Variable amount (%% tot.) - all lines from origin PaymentTypeVIR=Bank transfer PaymentTypeShortVIR=Bank transfer PaymentTypePRE=Direct debit payment order +PaymentTypePREdetails=(on account *-%s) PaymentTypeShortPRE=Debit payment order PaymentTypeLIQ=Cash PaymentTypeShortLIQ=Cash @@ -593,4 +594,4 @@ FacParentLine=Invoice Line Parent SituationTotalRayToRest=Remainder to pay without taxe PDFSituationTitle=Situation n° %d SituationTotalProgress=Total progress %d %% -SearchUnpaidInvoicesWithDueDate=Search unpaid invoices with a due date = %s \ No newline at end of file +SearchUnpaidInvoicesWithDueDate=Search unpaid invoices with a due date = %s diff --git a/htdocs/langs/fr_FR/bills.lang b/htdocs/langs/fr_FR/bills.lang index 0d6ab150fbb..51ce2f95ca9 100644 --- a/htdocs/langs/fr_FR/bills.lang +++ b/htdocs/langs/fr_FR/bills.lang @@ -434,6 +434,7 @@ VarAmountAllLines=Montant variable (%% tot.) - toutes les lignes identiques PaymentTypeVIR=Virement bancaire PaymentTypeShortVIR=Virement bancaire PaymentTypePRE=Ordre de prélèvement +PaymentTypePREdetails=(compte *-%s) PaymentTypeShortPRE=Ordre de prélèvement PaymentTypeLIQ=Espèce PaymentTypeShortLIQ=Espèce From 16618515fefc9f2b4a9e252a416fdb1b01b6852b Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Thu, 4 Aug 2022 07:56:17 +0000 Subject: [PATCH 433/826] Fixing style errors. --- htdocs/core/modules/facture/doc/pdf_crabe.modules.php | 6 +++--- htdocs/core/modules/facture/doc/pdf_sponge.modules.php | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php index 71381e24e68..78012a32934 100644 --- a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php @@ -1090,13 +1090,13 @@ class pdf_crabe extends ModelePDFFactures $pdf->SetXY($posxval, $posy); $lib_mode_reg = $outputlangs->transnoentities("PaymentType".$object->mode_reglement_code) != ('PaymentType'.$object->mode_reglement_code) ? $outputlangs->transnoentities("PaymentType".$object->mode_reglement_code) : $outputlangs->convToOutputCharset($object->mode_reglement); //#21654: add account number used for the debit - if ($object->mode_reglement_code == "PRE") { + if ($object->mode_reglement_code == "PRE") { require_once DOL_DOCUMENT_ROOT.'/societe/class/companybankaccount.class.php'; $bac = new CompanyBankAccount($this->db); $bac->fetch(0, $object->thirdparty->id); $iban= $bac->iban.(($bac->iban && $bac->bic) ? ' / ' : '').$bac->bic; - $lib_mode_reg .= $langs->trans("PaymentTypePREdetails", dol_trunc($iban, 6, 'right', 'UTF-8', 1)); - } + $lib_mode_reg .= $langs->trans("PaymentTypePREdetails", dol_trunc($iban, 6, 'right', 'UTF-8', 1)); + } $pdf->MultiCell(80, 5, $lib_mode_reg, 0, 'L'); // Show online payment link diff --git a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php index 99606bf9100..ff15bb72a9a 100644 --- a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php @@ -1175,13 +1175,13 @@ class pdf_sponge extends ModelePDFFactures $pdf->SetXY($posxval, $posy); $lib_mode_reg = $outputlangs->transnoentities("PaymentType".$object->mode_reglement_code) != ('PaymentType'.$object->mode_reglement_code) ? $outputlangs->transnoentities("PaymentType".$object->mode_reglement_code) : $outputlangs->convToOutputCharset($object->mode_reglement); //#21654: add account number used for the debit - if ($object->mode_reglement_code == "PRE") { + if ($object->mode_reglement_code == "PRE") { require_once DOL_DOCUMENT_ROOT.'/societe/class/companybankaccount.class.php'; $bac = new CompanyBankAccount($this->db); $bac->fetch(0, $object->thirdparty->id); $iban= $bac->iban.(($bac->iban && $bac->bic) ? ' / ' : '').$bac->bic; - $lib_mode_reg .= $langs->trans("PaymentTypePREdetails", dol_trunc($iban, 6, 'right', 'UTF-8', 1)); - } + $lib_mode_reg .= $langs->trans("PaymentTypePREdetails", dol_trunc($iban, 6, 'right', 'UTF-8', 1)); + } $pdf->MultiCell(80, 5, $lib_mode_reg, 0, 'L'); // Show online payment link From fb173da0f3669859cff0e9c4461390e2faad57f7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 4 Aug 2022 11:14:21 +0200 Subject: [PATCH 434/826] css --- htdocs/user/ldap.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/user/ldap.php b/htdocs/user/ldap.php index 8a8ca28092e..01be4fdcbae 100644 --- a/htdocs/user/ldap.php +++ b/htdocs/user/ldap.php @@ -97,7 +97,7 @@ llxHeader('', $title, $help_url); $head = user_prepare_head($object); $title = $langs->trans("User"); -print dol_get_fiche_head($head, 'ldap', $title, 0, 'user'); +print dol_get_fiche_head($head, 'ldap', $title, -1, 'user'); $linkback = ''; @@ -110,7 +110,7 @@ dol_banner_tab($object, 'id', $linkback, $user->rights->user->user->lire || $use print '
'; print '
'; -print '
'; @@ -196,10 +197,11 @@ print ''; print '
'; -print '
'; -print ' '.$langs->trans("ShowAdvancedOptions").''; +print '
'; + +print ''; print ''; diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index 3886651e8d5..078d485a5c9 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -543,6 +543,7 @@ fieldset { border: 1px solid #AAAAAA !important; padding-inline-start: 2em; padding-inline-end: 2em; + min-inline-size: auto; } .legendforfieldsetstep { padding-bottom: 10px; } input#onlinepaymenturl, input#directdownloadlink { diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 6e423228df1..ca485fb0d5f 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -725,6 +725,7 @@ fieldset { border: 1px solid #AAAAAA !important; padding-inline-start: 2em; padding-inline-end: 2em; + min-inline-size: auto; } .legendforfieldsetstep { padding-bottom: 10px; } input#onlinepaymenturl, input#directdownloadlink { From a509ec2c227cae48c8277e2455767107f87eb02e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 3 Aug 2022 18:31:55 +0200 Subject: [PATCH 423/826] Removed bad fields --- htdocs/install/mysql/migration/16.0.0-17.0.0.sql | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql index 597681c4ad5..e72fc1b8dcd 100644 --- a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql +++ b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql @@ -47,6 +47,9 @@ ALTER TABLE llx_expedition ADD COLUMN billed smallint DEFAULT 0; ALTER TABLE llx_accounting_system MODIFY COLUMN pcg_version varchar(32) NOT NULL; +ALTER TABLE llx_user DROP COLUMN idpers1; +ALTER TABLE llx_user DROP COLUMN idpers2; +ALTER TABLE llx_user DROP COLUMN idpers3; -- v17 From 868d07ae9674e6062ac01841e4cb613f559a4142 Mon Sep 17 00:00:00 2001 From: Faustin Date: Wed, 3 Aug 2022 20:01:13 +0200 Subject: [PATCH 424/826] New prop : select auth type with radio box --- htdocs/admin/mails.php | 81 +++++++++++++++------------ htdocs/core/class/CMailFile.class.php | 4 +- htdocs/core/class/smtps.class.php | 6 +- htdocs/langs/en_US/admin.lang | 8 ++- htdocs/langs/fr_FR/admin.lang | 6 +- 5 files changed, 58 insertions(+), 47 deletions(-) diff --git a/htdocs/admin/mails.php b/htdocs/admin/mails.php index 31198471710..6b09c211414 100644 --- a/htdocs/admin/mails.php +++ b/htdocs/admin/mails.php @@ -91,10 +91,8 @@ if ($action == 'update' && !$cancel) { if (GETPOSTISSET("MAIN_MAIL_SMTPS_PW")) { dolibarr_set_const($db, "MAIN_MAIL_SMTPS_PW", GETPOST("MAIN_MAIL_SMTPS_PW", 'none'), 'chaine', 0, '', $conf->entity); } - if (GETPOSTISSET("MAIN_MAIL_SMTPS_USE_OAUTH")) { - dolibarr_set_const($db, "MAIN_MAIL_SMTPS_USE_OAUTH", GETPOST("MAIN_MAIL_SMTPS_USE_OAUTH", 'int'), 'chaine', 0, '', $conf->entity); - $method = GETPOST("MAIN_MAIL_SMTPS_USE_OAUTH", 'aZ09') == 1 ? 'XOAUTH2' : 'LOGIN'; - dolibarr_set_const($db, "MAIL_SMTP_AUTH_TYPE", $method, 'chaine', 0, '', $conf->entity); + if (GETPOSTISSET("MAIN_MAIL_SMTPS_AUTH_TYPE")) { + dolibarr_set_const($db, "MAIN_MAIL_SMTPS_AUTH_TYPE", GETPOST("MAIN_MAIL_SMTPS_AUTH_TYPE", 'chaine'), 'chaine', 0, '', $conf->entity); } if (GETPOSTISSET("MAIN_MAIL_SMTPS_OAUTH_SERVICE")) { dolibarr_set_const($db, "MAIN_MAIL_SMTPS_OAUTH_SERVICE", GETPOST("MAIN_MAIL_SMTPS_OAUTH_SERVICE", 'chaine'), 'chaine', 0, '', $conf->entity); @@ -222,8 +220,7 @@ if ($action == 'edit') { jQuery("#MAIN_MAIL_EMAIL_DKIM_PRIVATE_KEY").prop("disabled", true); jQuery(".smtp_method").hide(); jQuery(".dkim").hide(); - jQuery(".smtp_oauth_service").hide(); - jQuery(".smtp_use_oauth").hide(); + jQuery(".smtp_auth_method").hide(); '; if ($linuxlike) { print ' @@ -266,8 +263,7 @@ if ($action == 'edit') { jQuery("#smtp_port_mess").hide(); jQuery(".smtp_method").show(); jQuery(".dkim").hide(); - jQuery(".smtp_oauth_service").show(); - jQuery(".smtp_use_oauth").show(); + jQuery(".smtp_auth_method").show(); } if (jQuery("#MAIN_MAIL_SENDMODE").val()==\'swiftmailer\') { @@ -295,27 +291,30 @@ if ($action == 'edit') { jQuery("#smtp_port_mess").hide(); jQuery(".smtp_method").show(); jQuery(".dkim").show(); - jQuery(".smtp_oauth_service").hide(); - jQuery(".smtp_use_oauth").hide(); + jQuery(".smtp_auth_method").hide(); } } - function change_smtp_oauth_service() { - console.log(jQuery("#MAIN_MAIL_SMTPS_USE_OAUTH").val()); - if (jQuery("#MAIN_MAIL_SMTPS_USE_OAUTH").val() == 1) { + function change_smtp_auth_method() { + console.log(jQuery("#radio_pw").prop("checked")); + if (jQuery("#MAIN_MAIL_SENDMODE").val()==\'smtps\' && jQuery("#radio_oauth").prop("checked")) { jQuery(".smtp_oauth_service").show(); jQuery(".smtp_pw").hide(); + } else if(jQuery("#MAIN_MAIL_SENDMODE").val()==\'mail\'){ + jQuery(".smtp_oauth_service").hide(); + jQuery(".smtp_pw").hide(); } else { jQuery(".smtp_oauth_service").hide(); jQuery(".smtp_pw").show(); } } initfields(); - change_smtp_oauth_service(); + change_smtp_auth_method(); jQuery("#MAIN_MAIL_SENDMODE").change(function() { initfields(); + change_smtp_auth_method(); }); - jQuery("#MAIN_MAIL_SMTPS_USE_OAUTH").change(function() { - change_smtp_oauth_service(); + jQuery("#radio_pw, #radio_oauth").change(function() { + change_smtp_auth_method(); }); jQuery("#MAIN_MAIL_EMAIL_TLS").change(function() { if (jQuery("#MAIN_MAIL_EMAIL_TLS").val() == 1) @@ -416,20 +415,6 @@ if ($action == 'edit') { } print '
'.$form->textwithpicto($langs->trans("MAIN_MAIL_SMTPS_USE_OAUTH"), $langs->trans("OauthNotAvailableForAll")).''; - if (empty($conf->multicompany->enabled) || ($user->admin && !$user->entity)) { - print $form->selectyesno('MAIN_MAIL_SMTPS_USE_OAUTH', (!empty($conf->global->MAIN_MAIL_SMTPS_USE_OAUTH) ? $conf->global->MAIN_MAIL_SMTPS_USE_OAUTH : 0), 1); - } else { - $value = yn($conf->global->MAIN_MAIL_SMTPS_USE_OAUTH); - $htmltext = $langs->trans("ContactSuperAdminForChange"); - print $form->textwithpicto($text, $htmltext, 1, 'superadmin'); - print ''; - } - print '
'; if (!$conf->use_javascript_ajax && $linuxlike && $conf->global->MAIN_MAIL_SENDMODE == 'mail') { @@ -474,6 +459,25 @@ if ($action == 'edit') { print '
'.$langs->trans("MAIN_MAIL_SMTPS_AUTH_TYPE").''; + if (empty($conf->multicompany->enabled) || ($user->admin && !$user->entity)) { + print 'global->MAIN_MAIL_SMTPS_AUTH_TYPE == 'LOGIN' ? ' checked' : '').'> '; + print ''; + print '            '; + print 'global->MAIN_MAIL_SMTPS_AUTH_TYPE == 'XOAUTH2' ? ' checked' : '').'> '; + print ''; + } else { + $value = $conf->global->MAIN_MAIL_SMTPS_AUTH_TYPE; + $htmltext = $langs->trans("ContactSuperAdminForChange"); + print $form->textwithpicto($langs->trans("MAIN_MAIL_SMTPS_AUTH_TYPE"), $htmltext, 1, 'superadmin'); + print ''; + } + print '
'.$form->textwithpicto($langs->trans("MAIN_MAIL_SMTPS_OAUTH_SERVICE"), $langs->trans("DontForgetCreateTokenOauthMod")).''; + print '
'.$langs->trans("MAIN_MAIL_SMTPS_OAUTH_SERVICE").''; // SuperAdministrator access only if ((empty($conf->global->MAIN_MODULE_MULTICOMPANY)) || ($user->admin && !$user->entity)) { @@ -680,10 +684,6 @@ if ($action == 'edit') { print '
'.$langs->trans("MAIN_MAIL_SMTP_SERVER", ini_get('SMTP') ?ini_get('SMTP') : $langs->transnoentities("Undefined")).''.(!empty($conf->global->MAIN_MAIL_SMTP_SERVER) ? $conf->global->MAIN_MAIL_SMTP_SERVER : '').'
'.$langs->trans("MAIN_MAIL_SMTPS_USE_OAUTH").''.yn($conf->global->MAIN_MAIL_SMTPS_USE_OAUTH).'
'.$langs->trans("MAIN_MAIL_SMTPS_ID").''.$conf->global->MAIN_MAIL_SMTPS_ID.'
'.$langs->trans("MAIN_MAIL_SMTPS_AUTH_TYPE").''.$text.'
'.$langs->trans("MAIN_MAIL_SMTPS_PW").''.preg_replace('/./', '*', $conf->global->MAIN_MAIL_SMTPS_PW).'
'; - $this->selectTypesTickets((GETPOST('type_code', 'alpha') ? GETPOST('type_code', 'alpha') : $this->type_code), 'type_code', '', 2, $conf->global->TICKET_FORCE_DISPLAY_EMPTY_OPTION, 0, 0, 'minwidth200'); + $this->selectTypesTickets((GETPOST('type_code', 'alpha') ? GETPOST('type_code', 'alpha') : $this->type_code), 'type_code', '', 2, 1, 0, 0, 'minwidth200'); print '
'; - $this->selectSeveritiesTickets((GETPOST('severity_code') ? GETPOST('severity_code') : $this->severity_code), 'severity_code', '', 2, $conf->global->TICKET_FORCE_DISPLAY_EMPTY_OPTION); + $this->selectSeveritiesTickets((GETPOST('severity_code') ? GETPOST('severity_code') : $this->severity_code), 'severity_code', '', 2, 1); print '
'; +print '
'; // Login print ''; From 0101b4d151d5e296891fc5708ab1b2ebde035b98 Mon Sep 17 00:00:00 2001 From: Quatadah Nasdami Date: Thu, 4 Aug 2022 11:38:26 +0200 Subject: [PATCH 435/826] removing useless changes --- htdocs/core/lib/functions.lib.php | 2 +- htdocs/projet/card.php | 30 ++++++++++++++++++------------ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index dda26dfa304..70eb4e50fa6 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -10420,6 +10420,7 @@ function dolGetStatus($statusLabel = '', $statusLabelShort = '', $html = '', $st * 'cancel-btn-label' => '', // Overide label of cancel button, if empty default label use "CloseDialog" lang key * 'content' => '', // Overide text of content, if empty default content use "ConfirmBtnCommonContent" lang key * 'modal' => true, // true|false to display dialog as a modal (with dark background) + * 'isDropDrown' => false, // true|false to display dialog as a dropdown (with dark background) * ], * ] * // phpcs:enable @@ -10439,7 +10440,6 @@ function dolGetButtonAction($label, $html = '', $actionType = 'default', $url = if (!empty($url) && strpos($url, 'token=') === false) $url .= '&token='.newToken(); } } - $attr = array( 'class' => $class, 'href' => empty($url) ? '' : $url, diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index f79e2b779ab..95c3a533d1f 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -1338,50 +1338,56 @@ if ($action == 'create' && $user->rights->projet->creer) { } } - // Add button to create objects from project + if (!empty($conf->global->PROJECT_SHOW_CREATE_OBJECT_BUTTON)) { + print'"; } - // Clone if ($user->rights->projet->creer) { if ($userWrite > 0) { From 766943ee43a2f33d7d7d97a2c1b732f553680bc9 Mon Sep 17 00:00:00 2001 From: Quatadah Nasdami Date: Thu, 4 Aug 2022 11:39:16 +0200 Subject: [PATCH 436/826] removing uselss changes2 --- htdocs/core/lib/functions.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 70eb4e50fa6..4efeb18fb60 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -10420,7 +10420,7 @@ function dolGetStatus($statusLabel = '', $statusLabelShort = '', $html = '', $st * 'cancel-btn-label' => '', // Overide label of cancel button, if empty default label use "CloseDialog" lang key * 'content' => '', // Overide text of content, if empty default content use "ConfirmBtnCommonContent" lang key * 'modal' => true, // true|false to display dialog as a modal (with dark background) - * 'isDropDrown' => false, // true|false to display dialog as a dropdown (with dark background) + * 'isDropDrown' => false, // true|false to display dialog as a dropdown (with dark background) * ], * ] * // phpcs:enable From b5ea8c5817073d43c2b136da67300bc6ee77fab0 Mon Sep 17 00:00:00 2001 From: Quatadah Nasdami Date: Thu, 4 Aug 2022 11:39:52 +0200 Subject: [PATCH 437/826] removing uselss changes2 --- htdocs/core/lib/functions.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 4efeb18fb60..57747cbf37a 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -10420,7 +10420,7 @@ function dolGetStatus($statusLabel = '', $statusLabelShort = '', $html = '', $st * 'cancel-btn-label' => '', // Overide label of cancel button, if empty default label use "CloseDialog" lang key * 'content' => '', // Overide text of content, if empty default content use "ConfirmBtnCommonContent" lang key * 'modal' => true, // true|false to display dialog as a modal (with dark background) - * 'isDropDrown' => false, // true|false to display dialog as a dropdown (with dark background) + * 'isDropDrown' => false, // true|false to display dialog as a dropdown (with dark background) * ], * ] * // phpcs:enable From b6b3f6389c51ee821bb1ae3c57aae83ae63574de Mon Sep 17 00:00:00 2001 From: Quatadah Nasdami Date: Thu, 4 Aug 2022 11:40:15 +0200 Subject: [PATCH 438/826] removing uselss changes2 --- htdocs/core/lib/functions.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 57747cbf37a..90698c95f80 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -10420,7 +10420,7 @@ function dolGetStatus($statusLabel = '', $statusLabelShort = '', $html = '', $st * 'cancel-btn-label' => '', // Overide label of cancel button, if empty default label use "CloseDialog" lang key * 'content' => '', // Overide text of content, if empty default content use "ConfirmBtnCommonContent" lang key * 'modal' => true, // true|false to display dialog as a modal (with dark background) - * 'isDropDrown' => false, // true|false to display dialog as a dropdown (with dark background) + * 'isDropDrown' => false, // true|false to display dialog as a dropdown (with dark background) * ], * ] * // phpcs:enable From 4090ce9227f0aa5d1e92a86fa29953375fb2e55b Mon Sep 17 00:00:00 2001 From: Quatadah Nasdami Date: Thu, 4 Aug 2022 11:51:47 +0200 Subject: [PATCH 439/826] changing the zip folder of the template style 02 --- .../websites/website_template-style02.zip | Bin 15973 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 htdocs/install/doctemplates/websites/website_template-style02.zip diff --git a/htdocs/install/doctemplates/websites/website_template-style02.zip b/htdocs/install/doctemplates/websites/website_template-style02.zip deleted file mode 100644 index 11116bcfc648ebc7a11d308b528dffd227668ced..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15973 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 Date: Thu, 4 Aug 2022 11:52:02 +0200 Subject: [PATCH 440/826] fix phpcs --- .../facture/doc/pdf_sponge.modules.php | 110 +++++++++--------- 1 file changed, 54 insertions(+), 56 deletions(-) diff --git a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php index 9c79896ee6e..f096392df4a 100644 --- a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php @@ -116,30 +116,30 @@ class pdf_sponge extends ModelePDFFactures public $marge_basse; - /** - * @var int heightforinfotot - */ - public $heightforinfotot; + /** + * @var int heightforinfotot + */ + public $heightforinfotot; - /** - * @var int heightforfreetext - */ - public $heightforfreetext; + /** + * @var int heightforfreetext + */ + public $heightforfreetext; - /** - * @var int heightforfooter - */ - public $heightforfooter; + /** + * @var int heightforfooter + */ + public $heightforfooter; - /** - * @var int tab_top - */ - public $tab_top; + /** + * @var int tab_top + */ + public $tab_top; - /** - * @var int tab_top_newpage - */ - public $tab_top_newpage; + /** + * @var int tab_top_newpage + */ + public $tab_top_newpage; /** * Issuer @@ -1243,37 +1243,37 @@ class pdf_sponge extends ModelePDFFactures if (empty($object->mode_reglement_code) && empty($conf->global->FACTURE_CHQ_NUMBER) && empty($conf->global->FACTURE_RIB_NUMBER)) { - $this->error = $outputlangs->transnoentities("ErrorNoPaiementModeConfigured"); + $this->error = $outputlangs->transnoentities("ErrorNoPaiementModeConfigured"); } elseif (($object->mode_reglement_code == 'CHQ' && empty($conf->global->FACTURE_CHQ_NUMBER) && empty($object->fk_account) && empty($object->fk_bank)) - || ($object->mode_reglement_code == 'VIR' && empty($conf->global->FACTURE_RIB_NUMBER) && empty($object->fk_account) && empty($object->fk_bank))) { - // Avoid having any valid PDF with setup that is not complete - $outputlangs->load("errors"); + || ($object->mode_reglement_code == 'VIR' && empty($conf->global->FACTURE_RIB_NUMBER) && empty($object->fk_account) && empty($object->fk_bank))) { + // Avoid having any valid PDF with setup that is not complete + $outputlangs->load("errors"); - $pdf->SetXY($this->marge_gauche, $posy); - $pdf->SetTextColor(200, 0, 0); - $pdf->SetFont('', 'B', $default_font_size - 2); - $this->error = $outputlangs->transnoentities("ErrorPaymentModeDefinedToWithoutSetup", $object->mode_reglement_code); - $pdf->MultiCell($posxend - $this->marge_gauche, 3, $this->error, 0, 'L', 0); - $pdf->SetTextColor(0, 0, 0); + $pdf->SetXY($this->marge_gauche, $posy); + $pdf->SetTextColor(200, 0, 0); + $pdf->SetFont('', 'B', $default_font_size - 2); + $this->error = $outputlangs->transnoentities("ErrorPaymentModeDefinedToWithoutSetup", $object->mode_reglement_code); + $pdf->MultiCell($posxend - $this->marge_gauche, 3, $this->error, 0, 'L', 0); + $pdf->SetTextColor(0, 0, 0); - $posy = $pdf->GetY() + 1; + $posy = $pdf->GetY() + 1; } // Show payment mode if (!empty($object->mode_reglement_code) - && $object->mode_reglement_code != 'CHQ' - && $object->mode_reglement_code != 'VIR') { - $pdf->SetFont('', 'B', $default_font_size - 2); - $pdf->SetXY($this->marge_gauche, $posy); - $titre = $outputlangs->transnoentities("PaymentMode").':'; - $pdf->MultiCell($posxend - $this->marge_gauche, 5, $titre, 0, 'L'); + && $object->mode_reglement_code != 'CHQ' + && $object->mode_reglement_code != 'VIR') { + $pdf->SetFont('', 'B', $default_font_size - 2); + $pdf->SetXY($this->marge_gauche, $posy); + $titre = $outputlangs->transnoentities("PaymentMode").':'; + $pdf->MultiCell($posxend - $this->marge_gauche, 5, $titre, 0, 'L'); - $pdf->SetFont('', '', $default_font_size - 2); - $pdf->SetXY($posxval, $posy); - $lib_mode_reg = $outputlangs->transnoentities("PaymentType".$object->mode_reglement_code) != ('PaymentType'.$object->mode_reglement_code) ? $outputlangs->transnoentities("PaymentType".$object->mode_reglement_code) : $outputlangs->convToOutputCharset($object->mode_reglement); - $pdf->MultiCell($posxend - $posxval, 5, $lib_mode_reg, 0, 'L'); + $pdf->SetFont('', '', $default_font_size - 2); + $pdf->SetXY($posxval, $posy); + $lib_mode_reg = $outputlangs->transnoentities("PaymentType".$object->mode_reglement_code) != ('PaymentType'.$object->mode_reglement_code) ? $outputlangs->transnoentities("PaymentType".$object->mode_reglement_code) : $outputlangs->convToOutputCharset($object->mode_reglement); + $pdf->MultiCell($posxend - $posxval, 5, $lib_mode_reg, 0, 'L'); - $posy = $pdf->GetY(); + $posy = $pdf->GetY(); } // Show online payment link @@ -1461,13 +1461,12 @@ class pdf_sponge extends ModelePDFFactures if ($posy > $this->page_hauteur - 4 - $this->heightforfooter) { $this->_pagefoot($pdf, $object, $outputlangs, 1); $pdf->addPage(); - if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) { - $this->_pagehead($pdf, $object, 0, $outputlangs, $outputlangsbis); - $pdf->setY($this->tab_top_newpage); - } - else{ - $pdf->setY($this->marge_haute); - } + if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) { + $this->_pagehead($pdf, $object, 0, $outputlangs, $outputlangsbis); + $pdf->setY($this->tab_top_newpage); + } else { + $pdf->setY($this->marge_haute); + } $posy = $pdf->GetY(); } @@ -1529,13 +1528,12 @@ class pdf_sponge extends ModelePDFFactures if ($posy > $this->page_hauteur - 4 - $this->heightforfooter) { $pdf->addPage(); - if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) { - $this->_pagehead($pdf, $object, 0, $outputlangs, $outputlangsbis); - $pdf->setY($this->tab_top_newpage); - } - else { - $pdf->setY($this->marge_haute); - } + if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) { + $this->_pagehead($pdf, $object, 0, $outputlangs, $outputlangsbis); + $pdf->setY($this->tab_top_newpage); + } else { + $pdf->setY($this->marge_haute); + } $posy = $pdf->GetY(); } From 92d4cb84a0cbd1b65308caaf72e5643832ae46d7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 4 Aug 2022 13:13:24 +0200 Subject: [PATCH 441/826] css --- htdocs/emailcollector/class/emailcollector.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index ecd32d2cefc..e3957637dd0 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -111,7 +111,7 @@ class EmailCollector extends CommonObject public $fields = array( 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'visible'=>2, 'enabled'=>1, 'position'=>1, 'notnull'=>1, 'index'=>1), 'entity' => array('type'=>'integer', 'label'=>'Entity', 'enabled'=>1, 'visible'=>0, 'default'=>1, 'notnull'=>1, 'index'=>1, 'position'=>20), - 'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>1, 'index'=>1, 'position'=>10, 'searchall'=>1, 'help'=>'Example: MyCollector1', 'csslist'=>'tdoverflowmax250'), + 'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>1, 'index'=>1, 'position'=>10, 'searchall'=>1, 'help'=>'Example: MyCollector1', 'csslist'=>'tdoverflowmax150'), 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'visible'=>1, 'enabled'=>1, 'position'=>30, 'notnull'=>-1, 'searchall'=>1, 'help'=>'Example: My Email collector', 'csslist'=>'tdoverflowmax150'), 'description' => array('type'=>'text', 'label'=>'Description', 'visible'=>-1, 'enabled'=>1, 'position'=>60, 'notnull'=>-1, 'csslist'=>'small'), 'host' => array('type'=>'varchar(255)', 'label'=>'EMailHost', 'visible'=>1, 'enabled'=>1, 'position'=>90, 'notnull'=>1, 'searchall'=>1, 'comment'=>"IMAP server", 'help'=>'Example: imap.gmail.com', 'csslist'=>'tdoverflow125'), From 8570fe597366744b7dcc7d91fa288b3576846f43 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 4 Aug 2022 13:19:24 +0200 Subject: [PATCH 442/826] css --- htdocs/emailcollector/class/emailcollector.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index e3957637dd0..4f95a44652e 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -111,13 +111,13 @@ class EmailCollector extends CommonObject public $fields = array( 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'visible'=>2, 'enabled'=>1, 'position'=>1, 'notnull'=>1, 'index'=>1), 'entity' => array('type'=>'integer', 'label'=>'Entity', 'enabled'=>1, 'visible'=>0, 'default'=>1, 'notnull'=>1, 'index'=>1, 'position'=>20), - 'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>1, 'index'=>1, 'position'=>10, 'searchall'=>1, 'help'=>'Example: MyCollector1', 'csslist'=>'tdoverflowmax150'), + 'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>1, 'index'=>1, 'position'=>10, 'searchall'=>1, 'help'=>'Example: MyCollector1', 'csslist'=>'tdoverflowmax200'), 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'visible'=>1, 'enabled'=>1, 'position'=>30, 'notnull'=>-1, 'searchall'=>1, 'help'=>'Example: My Email collector', 'csslist'=>'tdoverflowmax150'), 'description' => array('type'=>'text', 'label'=>'Description', 'visible'=>-1, 'enabled'=>1, 'position'=>60, 'notnull'=>-1, 'csslist'=>'small'), 'host' => array('type'=>'varchar(255)', 'label'=>'EMailHost', 'visible'=>1, 'enabled'=>1, 'position'=>90, 'notnull'=>1, 'searchall'=>1, 'comment'=>"IMAP server", 'help'=>'Example: imap.gmail.com', 'csslist'=>'tdoverflow125'), 'port' => array('type'=>'varchar(10)', 'label'=>'EMailHostPort', 'visible'=>1, 'enabled'=>1, 'position'=>91, 'notnull'=>1, 'searchall'=>0, 'comment'=>"IMAP server port", 'help'=>'Example: 993', 'csslist'=>'tdoverflow125', 'default'=>'993'), 'hostcharset' => array('type'=>'varchar(16)', 'label'=>'HostCharset', 'visible'=>-1, 'enabled'=>1, 'position'=>92, 'notnull'=>0, 'searchall'=>0, 'comment'=>"IMAP server charset", 'help'=>'Example: "UTF-8" (May be "US-ASCII" with some Office365)', 'default'=>'UTF-8'), - 'login' => array('type'=>'varchar(128)', 'label'=>'Login', 'visible'=>1, 'enabled'=>1, 'position'=>101, 'notnull'=>-1, 'index'=>1, 'comment'=>"IMAP login", 'help'=>'Example: myaccount@gmail.com'), + 'login' => array('type'=>'varchar(128)', 'label'=>'Login', 'visible'=>-1, 'enabled'=>1, 'position'=>101, 'notnull'=>-1, 'index'=>1, 'comment'=>"IMAP login", 'help'=>'Example: myaccount@gmail.com'), 'password' => array('type'=>'password', 'label'=>'Password', 'visible'=>-1, 'enabled'=>1, 'position'=>102, 'notnull'=>-1, 'comment'=>"IMAP password", 'help'=>'WithGMailYouCanCreateADedicatedPassword'), 'source_directory' => array('type'=>'varchar(255)', 'label'=>'MailboxSourceDirectory', 'visible'=>-1, 'enabled'=>1, 'position'=>103, 'notnull'=>1, 'default' => 'Inbox', 'help'=>'Example: INBOX'), //'filter' => array('type'=>'text', 'label'=>'Filter', 'visible'=>1, 'enabled'=>1, 'position'=>105), From a7a1c70c654de796be867ad9231ac772051837ea Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 4 Aug 2022 13:42:57 +0200 Subject: [PATCH 443/826] FIX Scan IMAP must not be done automatically --- htdocs/admin/emailcollector_card.php | 86 +++++++++++++++------------- 1 file changed, 45 insertions(+), 41 deletions(-) diff --git a/htdocs/admin/emailcollector_card.php b/htdocs/admin/emailcollector_card.php index ab4f0c7def0..2a32551eaad 100644 --- a/htdocs/admin/emailcollector_card.php +++ b/htdocs/admin/emailcollector_card.php @@ -378,33 +378,54 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $connectstringserver = $object->getConnectStringIMAP($usessl); - try { - if ($sourcedir) { - //$connectstringsource = $connectstringserver.imap_utf7_encode($sourcedir); - $connectstringsource = $connectstringserver.$object->getEncodedUtf7($sourcedir); - } - if ($targetdir) { - //$connectstringtarget = $connectstringserver.imap_utf7_encode($targetdir); - $connectstringtarget = $connectstringserver.$object->getEncodedUtf7($targetdir); + if ($action == 'scan') { + try { + if ($sourcedir) { + //$connectstringsource = $connectstringserver.imap_utf7_encode($sourcedir); + $connectstringsource = $connectstringserver.$object->getEncodedUtf7($sourcedir); + } + if ($targetdir) { + //$connectstringtarget = $connectstringserver.imap_utf7_encode($targetdir); + $connectstringtarget = $connectstringserver.$object->getEncodedUtf7($targetdir); + } + + $timeoutconnect = empty($conf->global->MAIN_USE_CONNECT_TIMEOUT) ? 5 : $conf->global->MAIN_USE_CONNECT_TIMEOUT; + $timeoutread = empty($conf->global->MAIN_USE_RESPONSE_TIMEOUT) ? 20 : $conf->global->MAIN_USE_RESPONSE_TIMEOUT; + + dol_syslog("imap_open connectstring=".$connectstringsource." login=".$object->login." password=".$object->password." timeoutconnect=".$timeoutconnect." timeoutread=".$timeoutread); + + $result1 = imap_timeout(IMAP_OPENTIMEOUT, $timeoutconnect); // timeout seems ignored with ssl connect + $result2 = imap_timeout(IMAP_READTIMEOUT, $timeoutread); + $result3 = imap_timeout(IMAP_WRITETIMEOUT, 5); + $result4 = imap_timeout(IMAP_CLOSETIMEOUT, 5); + + dol_syslog("result1=".$result1." result2=".$result2." result3=".$result3." result4=".$result4); + + $connection = imap_open($connectstringsource, $object->login, $object->password); + + //dol_syslog("end imap_open connection=".var_export($connection, true)); + } catch (Exception $e) { + print $e->getMessage(); } - $timeoutconnect = empty($conf->global->MAIN_USE_CONNECT_TIMEOUT) ? 5 : $conf->global->MAIN_USE_CONNECT_TIMEOUT; - $timeoutread = empty($conf->global->MAIN_USE_RESPONSE_TIMEOUT) ? 20 : $conf->global->MAIN_USE_RESPONSE_TIMEOUT; + if (!$connection) { + $morehtml .= 'Failed to open IMAP connection '.$connectstringsource; + if (function_exists('imap_last_error')) { + $morehtml .= '
'.imap_last_error(); + } + dol_syslog("Error ".$morehtml, LOG_WARNING); + //var_dump(imap_errors()) + } else { + dol_syslog("Imap connected. Now we call imap_num_msg()"); + $morehtml .= imap_num_msg($connection); + } - dol_syslog("imap_open connectstring=".$connectstringsource." login=".$object->login." password=".$object->password." timeoutconnect=".$timeoutconnect." timeoutread=".$timeoutread); - - $result1 = imap_timeout(IMAP_OPENTIMEOUT, $timeoutconnect); // timeout seems ignored with ssl connect - $result2 = imap_timeout(IMAP_READTIMEOUT, $timeoutread); - $result3 = imap_timeout(IMAP_WRITETIMEOUT, 5); - $result4 = imap_timeout(IMAP_CLOSETIMEOUT, 5); - - dol_syslog("result1=".$result1." result2=".$result2." result3=".$result3." result4=".$result4); - - $connection = imap_open($connectstringsource, $object->login, $object->password); - - //dol_syslog("end imap_open connection=".var_export($connection, true)); - } catch (Exception $e) { - print $e->getMessage(); + if ($connection) { + dol_syslog("Imap close"); + imap_close($connection); + } + } else { + $morehtml .= ''.img_picto('', 'refresh', 'class="paddingrightonly"').$langs->trans("Refresh").''; } $morehtml .= $form->textwithpicto('', 'connect string '.$connectstringserver); @@ -412,23 +433,6 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $morehtml .= 'IMAP functions not available on your PHP. '; } - if (!$connection) { - $morehtml .= 'Failed to open IMAP connection '.$connectstringsource; - if (function_exists('imap_last_error')) { - $morehtml .= '
'.imap_last_error(); - } - dol_syslog("Error ".$morehtml, LOG_WARNING); - //var_dump(imap_errors()) - } else { - dol_syslog("Imap connected. Now we call imap_num_msg()"); - $morehtml .= imap_num_msg($connection); - } - - if ($connection) { - dol_syslog("Imap close"); - imap_close($connection); - } - dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref.'
'.$morehtml.'
', '', 0, '', '', 0, ''); print '
'; From 1093084e9b349069a8e0f594d9a9d7308195fc63 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 4 Aug 2022 14:00:04 +0200 Subject: [PATCH 444/826] Better doc --- htdocs/admin/emailcollector_card.php | 6 +++--- htdocs/langs/en_US/admin.lang | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/admin/emailcollector_card.php b/htdocs/admin/emailcollector_card.php index 2a32551eaad..bc8267f9ef9 100644 --- a/htdocs/admin/emailcollector_card.php +++ b/htdocs/admin/emailcollector_card.php @@ -584,11 +584,11 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print '
'; print ''; print ''; print ''; diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 6ca93dc7788..149668e34a7 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -2108,7 +2108,7 @@ CreateCandidature=Create job application FormatZip=Zip MainMenuCode=Menu entry code (mainmenu) ECMAutoTree=Show automatic ECM tree -OperationParamDesc=Define the rules to use to extract or set values.
Example for operations that need to extract a name from email subject:
name=EXTRACT:SUBJECT:Message from company ([^\n]*)
Example for operations that create objects:
objproperty1=SET:the value to set
objproperty2=SET:a value including value of __objproperty1__
objproperty3=SETIFEMPTY:value used if objproperty3 is not already defined
objproperty4=EXTRACT:HEADER:X-Myheaderkey:\s*([^\s]*)
options_myextrafield1=EXTRACT:SUBJECT:([^\n]*)
object.objproperty5=EXTRACT:BODY:My company name is\s([^\s]*)

Use a ; char as separator to extract or set several properties. +OperationParamDesc=Define the rules to use to extract some data or set values to use for operation.

Example to extract a company name from email subject into a temporary variable:
tmp_var=EXTRACT:SUBJECT:Message from company ([^\n]*)

Examples to set the properties of an object to create:
objproperty1=SET:a hard coded value
objproperty2=SET:__tmp_var__
objproperty3=SETIFEMPTY:a value (value is set only if property is not already defined)
objproperty4=EXTRACT:HEADER:X-Myheaderkey:\s*([^\s]*)
options_myextrafield1=EXTRACT:SUBJECT:([^\n]*)
object.objproperty5=EXTRACT:BODY:My company name is\s([^\s]*)

Use a ; char as separator to extract or set several properties. OpeningHours=Opening hours OpeningHoursDesc=Enter here the regular opening hours of your company. ResourceSetup=Configuration of Resource module From 852dc909aa74e7675c643de0884bdf67aaec031c Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Thu, 4 Aug 2022 14:46:20 +0200 Subject: [PATCH 445/826] NEW add hook un takepos/pay.php add hook for new payment method --- htdocs/takepos/pay.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/htdocs/takepos/pay.php b/htdocs/takepos/pay.php index f487862e895..24ca8cc782b 100644 --- a/htdocs/takepos/pay.php +++ b/htdocs/takepos/pay.php @@ -655,6 +655,10 @@ if ($conf->global->TAKEPOS_ENABLE_SUMUP) { } } +$parameters = array(); +$reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $invoice, $action); // Note that $action and $object may have been modified by hook +if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + $class = ($i == 3) ? "calcbutton3" : "calcbutton2"; foreach ($action_buttons as $button) { $newclass = $class.($button["class"] ? " ".$button["class"] : ""); From 236c8e21f54006a32c91895be6ea0aa542a46bdc Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Thu, 4 Aug 2022 15:05:16 +0200 Subject: [PATCH 446/826] Fix : regretion on stockmovement --- htdocs/product/class/product.class.php | 2 +- htdocs/product/stock/massstockmove.php | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 6c249e6b3bd..8ff8f53275e 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -5037,7 +5037,7 @@ class Product extends CommonObject $result .= (img_object(($notooltip ? '' : $label), 'service', ($notooltip ? 'class="paddingright"' : 'class="paddingright classfortooltip"'), 0, 0, $notooltip ? 0 : 1)); } } - $result .= $newref; + $result .= dol_escape_htmltag($newref); $result .= $linkend; if ($withpicto != 2) { $result .= (($add_label && $this->label) ? $sep.dol_trunc($this->label, ($add_label > 1 ? $add_label : 0)) : ''); diff --git a/htdocs/product/stock/massstockmove.php b/htdocs/product/stock/massstockmove.php index 31b2aa8e187..4da9156e955 100644 --- a/htdocs/product/stock/massstockmove.php +++ b/htdocs/product/stock/massstockmove.php @@ -336,11 +336,11 @@ if ($action == 'importCSV' && !empty($user->rights->stock->mouvement->creer)) { continue; } //var_dump($data); - $tmp_id_sw = (int) $data[$i][0]['val']; - $tmp_id_tw = (int) $data[$i][1]['val']; - $tmp_id_product = (int) $data[$i][2]['val']; - $tmp_qty = price2num((float) $data[$i][3]['val'], 'MS'); - $tmp_batch = dol_escape_htmltag($data[$i][4]['val']); + $tmp_id_sw = $data[$i][0]['val']; + $tmp_id_tw = $data[$i][1]['val']; + $tmp_id_product = $data[$i][2]['val']; + $tmp_qty = $data[$i][3]['val']; + $tmp_batch = $data[$i][4]['val']; if (!is_numeric($tmp_id_product)) { $result = fetchref($productstatic, $tmp_id_product); @@ -604,11 +604,11 @@ print ''; if (isModEnabled('productbatch')) { print '
'; } // Qty -print ''; +print ''; // Button to add line print ''; @@ -641,14 +641,14 @@ foreach ($listofdata as $key => $val) { print $warehousestatict->getNomUrl(1); print ''; print ''; if (isModEnabled('productbatch')) { print ''; } - print ''; + print ''; print ''; print ''; } From d4a55e00e2891f58a959aaa08d0f2674edeb24ab Mon Sep 17 00:00:00 2001 From: Faustin Date: Thu, 4 Aug 2022 15:32:20 +0200 Subject: [PATCH 447/826] added Weklek/php-imap lib --- htdocs/includes/Webklex/php-imap/.gitignore | 4 + htdocs/includes/Webklex/php-imap/.travis.yml | 34 + htdocs/includes/Webklex/php-imap/CHANGELOG.md | 666 ++++++++ .../Webklex/php-imap/CODE_OF_CONDUCT.md | 46 + htdocs/includes/Webklex/php-imap/LICENSE | 21 + htdocs/includes/Webklex/php-imap/LICENSE.md | 21 + htdocs/includes/Webklex/php-imap/README.md | 167 ++ htdocs/includes/Webklex/php-imap/_config.yml | 1 + .../includes/Webklex/php-imap/composer.json | 55 + .../examples/custom_attachment_mask.php | 56 + .../php-imap/examples/custom_message_mask.php | 50 + .../examples/folder_structure.blade.php | 42 + .../php-imap/examples/message_table.blade.php | 46 + htdocs/includes/Webklex/php-imap/phpunit.xml | 32 + .../includes/Webklex/php-imap/src/Address.php | 90 ++ .../Webklex/php-imap/src/Attachment.php | 346 ++++ .../Webklex/php-imap/src/Attribute.php | 267 +++ .../includes/Webklex/php-imap/src/Client.php | 699 ++++++++ .../Webklex/php-imap/src/ClientManager.php | 276 ++++ .../src/Connection/Protocols/ImapProtocol.php | 1124 +++++++++++++ .../Connection/Protocols/LegacyProtocol.php | 635 ++++++++ .../src/Connection/Protocols/Protocol.php | 285 ++++ .../Protocols/ProtocolInterface.php | 408 +++++ .../Webklex/php-imap/src/EncodingAliases.php | 482 ++++++ .../Webklex/php-imap/src/Events/Event.php | 28 + .../php-imap/src/Events/FlagDeletedEvent.php | 22 + .../php-imap/src/Events/FlagNewEvent.php | 39 + .../src/Events/FolderDeletedEvent.php | 22 + .../php-imap/src/Events/FolderMovedEvent.php | 38 + .../php-imap/src/Events/FolderNewEvent.php | 35 + .../src/Events/MessageCopiedEvent.php | 22 + .../src/Events/MessageDeletedEvent.php | 22 + .../php-imap/src/Events/MessageMovedEvent.php | 38 + .../php-imap/src/Events/MessageNewEvent.php | 35 + .../src/Events/MessageRestoredEvent.php | 22 + .../src/Exceptions/AuthFailedException.php | 24 + .../Exceptions/ConnectionFailedException.php | 24 + .../src/Exceptions/EventNotFoundException.php | 24 + .../Exceptions/FolderFetchingException.php | 24 + .../Exceptions/GetMessagesFailedException.php | 24 + .../InvalidMessageDateException.php | 24 + .../InvalidWhereQueryCriteriaException.php | 24 + .../src/Exceptions/MaskNotFoundException.php | 24 + .../MessageContentFetchingException.php | 24 + .../src/Exceptions/MessageFlagException.php | 24 + .../MessageHeaderFetchingException.php | 24 + .../Exceptions/MessageNotFoundException.php | 24 + .../MessageSearchValidationException.php | 24 + .../Exceptions/MethodNotFoundException.php | 24 + .../MethodNotSupportedException.php | 24 + .../NotSupportedCapabilityException.php | 24 + .../ProtocolNotSupportedException.php | 24 + .../src/Exceptions/RuntimeException.php | 24 + .../includes/Webklex/php-imap/src/Folder.php | 454 ++++++ .../includes/Webklex/php-imap/src/Header.php | 757 +++++++++ htdocs/includes/Webklex/php-imap/src/IMAP.php | 375 +++++ .../includes/Webklex/php-imap/src/Message.php | 1431 +++++++++++++++++ htdocs/includes/Webklex/php-imap/src/Part.php | 312 ++++ .../Webklex/php-imap/src/Query/Query.php | 980 +++++++++++ .../Webklex/php-imap/src/Query/WhereQuery.php | 546 +++++++ .../Webklex/php-imap/src/Structure.php | 174 ++ .../src/Support/AttachmentCollection.php | 22 + .../php-imap/src/Support/FlagCollection.php | 22 + .../php-imap/src/Support/FolderCollection.php | 22 + .../src/Support/Masks/AttachmentMask.php | 44 + .../php-imap/src/Support/Masks/Mask.php | 137 ++ .../src/Support/Masks/MessageMask.php | 86 + .../src/Support/MessageCollection.php | 22 + .../src/Support/PaginatedCollection.php | 82 + .../Webklex/php-imap/src/Traits/HasEvents.php | 77 + .../Webklex/php-imap/src/config/imap.php | 226 +++ .../Webklex/php-imap/tests/InitialTest.php | 26 + 72 files changed, 12403 insertions(+) create mode 100644 htdocs/includes/Webklex/php-imap/.gitignore create mode 100644 htdocs/includes/Webklex/php-imap/.travis.yml create mode 100755 htdocs/includes/Webklex/php-imap/CHANGELOG.md create mode 100644 htdocs/includes/Webklex/php-imap/CODE_OF_CONDUCT.md create mode 100644 htdocs/includes/Webklex/php-imap/LICENSE create mode 100644 htdocs/includes/Webklex/php-imap/LICENSE.md create mode 100755 htdocs/includes/Webklex/php-imap/README.md create mode 100644 htdocs/includes/Webklex/php-imap/_config.yml create mode 100644 htdocs/includes/Webklex/php-imap/composer.json create mode 100644 htdocs/includes/Webklex/php-imap/examples/custom_attachment_mask.php create mode 100644 htdocs/includes/Webklex/php-imap/examples/custom_message_mask.php create mode 100644 htdocs/includes/Webklex/php-imap/examples/folder_structure.blade.php create mode 100644 htdocs/includes/Webklex/php-imap/examples/message_table.blade.php create mode 100644 htdocs/includes/Webklex/php-imap/phpunit.xml create mode 100644 htdocs/includes/Webklex/php-imap/src/Address.php create mode 100755 htdocs/includes/Webklex/php-imap/src/Attachment.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Attribute.php create mode 100755 htdocs/includes/Webklex/php-imap/src/Client.php create mode 100644 htdocs/includes/Webklex/php-imap/src/ClientManager.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Connection/Protocols/ImapProtocol.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Connection/Protocols/LegacyProtocol.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Connection/Protocols/Protocol.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Connection/Protocols/ProtocolInterface.php create mode 100644 htdocs/includes/Webklex/php-imap/src/EncodingAliases.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Events/Event.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Events/FlagDeletedEvent.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Events/FlagNewEvent.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Events/FolderDeletedEvent.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Events/FolderMovedEvent.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Events/FolderNewEvent.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Events/MessageCopiedEvent.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Events/MessageDeletedEvent.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Events/MessageMovedEvent.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Events/MessageNewEvent.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Events/MessageRestoredEvent.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Exceptions/AuthFailedException.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Exceptions/ConnectionFailedException.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Exceptions/EventNotFoundException.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Exceptions/FolderFetchingException.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Exceptions/GetMessagesFailedException.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Exceptions/InvalidMessageDateException.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Exceptions/InvalidWhereQueryCriteriaException.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Exceptions/MaskNotFoundException.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Exceptions/MessageContentFetchingException.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Exceptions/MessageFlagException.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Exceptions/MessageHeaderFetchingException.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Exceptions/MessageNotFoundException.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Exceptions/MessageSearchValidationException.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Exceptions/MethodNotFoundException.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Exceptions/MethodNotSupportedException.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Exceptions/NotSupportedCapabilityException.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Exceptions/ProtocolNotSupportedException.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Exceptions/RuntimeException.php create mode 100755 htdocs/includes/Webklex/php-imap/src/Folder.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Header.php create mode 100644 htdocs/includes/Webklex/php-imap/src/IMAP.php create mode 100755 htdocs/includes/Webklex/php-imap/src/Message.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Part.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Query/Query.php create mode 100755 htdocs/includes/Webklex/php-imap/src/Query/WhereQuery.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Structure.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Support/AttachmentCollection.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Support/FlagCollection.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Support/FolderCollection.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Support/Masks/AttachmentMask.php create mode 100755 htdocs/includes/Webklex/php-imap/src/Support/Masks/Mask.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Support/Masks/MessageMask.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Support/MessageCollection.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Support/PaginatedCollection.php create mode 100644 htdocs/includes/Webklex/php-imap/src/Traits/HasEvents.php create mode 100644 htdocs/includes/Webklex/php-imap/src/config/imap.php create mode 100644 htdocs/includes/Webklex/php-imap/tests/InitialTest.php diff --git a/htdocs/includes/Webklex/php-imap/.gitignore b/htdocs/includes/Webklex/php-imap/.gitignore new file mode 100644 index 00000000000..77d608c3327 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/.gitignore @@ -0,0 +1,4 @@ +vendor +composer.lock +.idea +/build/ diff --git a/htdocs/includes/Webklex/php-imap/.travis.yml b/htdocs/includes/Webklex/php-imap/.travis.yml new file mode 100644 index 00000000000..26e564efd77 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/.travis.yml @@ -0,0 +1,34 @@ +language: php + +os: linux +dist: xenial + +php: + - 5.6 + - 7.0 + - 7.1 + - 7.2 + - 7.3 + - 7.4 + - hhvm + +jobs: + fast_finish: true + allow_failures: + - php: 7.3 + - php: 7.4 + - php: hhvm + +before_install: + - COMPOSER_MEMORY_LIMIT=-1 composer install --prefer-source --no-interaction --dev + +install: + - COMPOSER_MEMORY_LIMIT=-1 composer install --no-interaction + +script: + - ./vendor/bin/phpunit + +notifications: + email: + on_success: always + on_failure: always diff --git a/htdocs/includes/Webklex/php-imap/CHANGELOG.md b/htdocs/includes/Webklex/php-imap/CHANGELOG.md new file mode 100755 index 00000000000..5956596f52a --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/CHANGELOG.md @@ -0,0 +1,666 @@ +# Changelog + +All notable changes to `webklex/php-imap` will be documented in this file. + +Updates should follow the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [UNRELEASED] +### Fixed +- PHP dependency updated to support php v8.0 #212 #214 (thanks @freescout-helpdesk) +- Method return and argument types added + +### Added +- NaN + +### Affected Classes +- NaN + +### Breaking changes +- No longer supports php >=5.5.9 but instead requires at least php v7.0.0 + + +## [3.2.0] - 2022-03-07 +### Fixed +- Fix attribute serialization #179 (thanks @netpok) +- Use real tls instead of starttls #180 (thanks @netpok) +- Allow to fully overwrite default config arrays #194 (thanks @laurent-rizer) +- Query::chunked does not loop over the last chunk #196 (thanks @laurent-rizer) +- Fix isAttachment that did not properly take in consideration dispositions options #195 (thanks @laurent-rizer) +- Extend date parsing error message #173 +- Fixed 'Where' method replaces the content with uppercase #148 +- Don't surround numeric search values with quotes +- Context added to `InvalidWhereQueryCriteriaException` +- Redundant `stream_set_timeout()` removed + +### Added +- UID Cache added #204 (thanks @HelloSebastian) +- Query::class extended with `getByUidLower`, `getByUidLowerOrEqual` , `getByUidGreaterOrEqual` , `getByUidGreater` to fetch certain ranges of uids #201 (thanks @HelloSebastian) +- Check if IDLE is supported if `Folder::idle()` is called #199 (thanks @HelloSebastian) +- Fallback date support added. The config option `options.fallback_date` is used as fallback date is it is set. Otherwise, an exception will be thrown #198 +- UID filter support added +- Make boundary regex configurable #169 #150 #126 #121 #111 #152 #108 (thanks @EthraZa) +- IMAP ID support added #174 +- Enable debug mode via config +- Custom UID alternative support added +- Fetch additional extensions using `Folder::query(["FEATURE_NAME"])` +- Optionally move a message during "deletion" instead of just "flagging" it #106 (thanks @EthraZa) +- `WhereQuery::where()` accepts now a wide range of criteria / values. #104 + +### Affected Classes +- [Part::class](src/Part.php) +- [Query::class](src/Query/Query.php) +- [Client::class](src/Client.php) +- [Header::class](src/Header.php) +- [Protocol::class](src/Connection/Protocols/Protocol.php) +- [ClientManager::class](src/ClientManager.php) + +### Breaking changes +- If you are using the legacy protocol to search, the results no longer return false if the search criteria could not be interpreted but instead return an empty array. This will ensure it is compatible to the rest of this library and no longer result in a potential type confusion. +- `Folder::idle` will throw an `Webklex\PHPIMAP\Exceptions\NotSupportedCapabilityException` exception if IMAP isn't supported by the mail server +- All protocol methods which had a `boolean` `$uid` option no longer support a boolean value. Use `IMAP::ST_UID` or `IMAP::NIL` instead. If you want to use an alternative to `UID` just use the string instead. +- Default config option `options.sequence` changed from `IMAP::ST_MSGN` to `IMAP::ST_UID`. +- `Folder::query()` no longer accepts a charset string. It has been replaced by an extension array, which provides the ability to automatically fetch additional features. + + +## [3.1.0-alpha] - 2022-02-03 +### Fixed +- Fix attribute serialization #179 (thanks @netpok) +- Use real tls instead of starttls #180 (thanks @netpok) +- Allow to fully overwrite default config arrays #194 (thanks @laurent-rizer) +- Query::chunked does not loop over the last chunk #196 (thanks @laurent-rizer) +- Fix isAttachment that did not properly take in consideration dispositions options #195 (thanks @laurent-rizer) + +### Affected Classes +- [Header::class](src/Header.php) +- [Protocol::class](src/Connection/Protocols/Protocol.php) +- [Query::class](src/Query/Query.php) +- [Part::class](src/Part.php) +- [ClientManager::class](src/ClientManager.php) + +## [3.0.0-alpha] - 2021-11-04 +### Fixed +- Extend date parsing error message #173 +- Fixed 'Where' method replaces the content with uppercase #148 +- Don't surround numeric search values with quotes +- Context added to `InvalidWhereQueryCriteriaException` +- Redundant `stream_set_timeout()` removed + +### Added +- Make boundary regex configurable #169 #150 #126 #121 #111 #152 #108 (thanks @EthraZa) +- IMAP ID support added #174 +- Enable debug mode via config +- Custom UID alternative support added +- Fetch additional extensions using `Folder::query(["FEATURE_NAME"])` +- Optionally move a message during "deletion" instead of just "flagging" it #106 (thanks @EthraZa) +- `WhereQuery::where()` accepts now a wide range of criteria / values. #104 + +### Affected Classes +- [Header::class](src/Header.php) +- [Protocol::class](src/Connection/Protocols/Protocol.php) +- [Query::class](src/Query/Query.php) +- [WhereQuery::class](src/Query/WhereQuery.php) +- [Message::class](src/Message.php) + +### Breaking changes +- All protocol methods which had a `boolean` `$uid` option no longer support a boolean. Use `IMAP::ST_UID` or `IMAP::NIL` instead. If you want to use an alternative to `UID` just use the string instead. +- Default config option `options.sequence` changed from `IMAP::ST_MSGN` to `IMAP::ST_UID`. +- `Folder::query()` no longer accepts a charset string. It has been replaced by an extension array, which provides the ability to automatically fetch additional features. + +## [2.7.2] - 2021-09-27 +### Fixed +- Fixed problem with skipping last line of the response. #166 (thanks @szymekjanaczek) + +## [2.7.1] - 2021-09-08 +### Added +- Added `UID` as available search criteria #161 (thanks @szymekjanaczek) + +## [2.7.0] - 2021-09-04 +### Fixed +- Fixes handling of long header lines which are seperated by `\r\n\t` (thanks @Oliver-Holz) +- Fixes to line parsing with multiple addresses (thanks @Oliver-Holz) + +### Added +- Expose message folder path #154 (thanks @Magiczne) +- Adds mailparse_rfc822_parse_addresses integration (thanks @Oliver-Holz) +- Added moveManyMessages method (thanks @Magiczne) +- Added copyManyMessages method (thanks @Magiczne) + +### Affected Classes +- [Header::class](src/Header.php) +- [Message::class](src/Message.php) + +## [2.6.0] - 2021-08-20 +### Fixed +- POP3 fixes #151 (thanks @Korko) + +### Added +- Added imap 4 handling. #146 (thanks @szymekjanaczek) +- Added laravel's conditionable methods. #147 (thanks @szymekjanaczek) + +### Affected Classes +- [Query::class](src/Query/Query.php) +- [Client::class](src/Client.php) + +## [2.5.1] - 2021-06-19 +### Fixed +- Fix setting default mask from config #133 (thanks @shacky) +- Chunked fetch fails in case of less available mails than page size #114 +- Protocol::createStream() exception information fixed #137 +- Legacy methods (headers, content, flags) fixed #125 +- Legacy connection cycle fixed #124 (thanks @zssarkany) + +### Added +- Disable rfc822 header parsing via config option #115 + +## [2.5.0] - 2021-02-01 +### Fixed +- Attachment saving filename fixed +- Unnecessary parameter removed from `Client::getTimeout()` +- Missing encryption variable added - could have caused problems with unencrypted communications +- Prefer attachment filename attribute over name attribute #82 +- Missing connection settings added to `Folder:idle()` auto mode #89 +- Message move / copy expect a folder path #79 +- `Client::getFolder()` updated to circumvent special edge cases #79 +- Missing connection status checks added to various methods +- Unused default attribute `message_no` removed from `Message::class` + +### Added +- Dynamic Attribute access support added (e.g `$message->from[0]`) +- Message not found exception added #93 +- Chunked fetching support added `Query::chunked()`. Just in case you can't fetch all messages at once +- "Soft fail" support added +- Count method added to `Attribute:class` +- Convert an Attribute instance into a Carbon date object #95 + +### Affected Classes +- [Attachment::class](src/Attachment.php) +- [Attribute::class](src/Attribute.php) +- [Query::class](src/Query/Query.php) +- [Message::class](src/Message.php) +- [Client::class](src/Client.php) +- [Folder::class](src/Folder.php) + +### Breaking changes +- A new exception can occur if a message can't be fetched (`\Webklex\PHPIMAP\Exceptions\MessageNotFoundException::class`) +- `Message::move()` and `Message::copy()` no longer accept folder names as folder path +- A `Message::class` instance might no longer have a `message_no` attribute + +## [2.4.4] - 2021-01-22 +### Fixed +- Boundary detection simplified #90 +- Prevent potential body overwriting #90 +- CSV files are no longer regarded as plain body +- Boundary detection overhauled to support "related" and "alternative" multipart messages #90 #91 + +### Affected Classes +- [Structure::class](src/Structure.php) +- [Message::class](src/Message.php) +- [Header::class](src/Header.php) +- [Part::class](src/Part.php) + +## [2.4.3] - 2021-01-21 +### Fixed +- Attachment detection updated #82 #90 +- Timeout handling improved +- Additional utf-8 checks added to prevent decoding of unencoded values #76 + +### Added +- Auto reconnect option added to `Folder::idle()` #89 + +### Affected Classes +- [Folder::class](src/Folder.php) +- [Part::class](src/Part.php) +- [Client::class](src/Client.php) +- [Header::class](src/Header.php) + +## [2.4.2] - 2021-01-09 +### Fixed +- Attachment::save() return error 'A facade root has not been set' #87 +- Unused dependencies removed +- Fix PHP 8 error that changes null back in to an empty string. #88 (thanks @mennovanhout) +- Fix regex to be case insensitive #88 (thanks @mennovanhout) + +### Affected Classes +- [Attachment::class](src/Attachment.php) +- [Address::class](src/Address.php) +- [Attribute::class](src/Attribute.php) +- [Structure::class](src/Structure.php) + +## [2.4.1] - 2021-01-06 +### Fixed +- Debug line position fixed +- Handle incomplete address to string conversion #83 +- Configured message key gets overwritten by the first fetched message #84 + +### Affected Classes +- [Address::class](src/Address.php) +- [Query::class](src/Query/Query.php) + +## [2.4.0] - 2021-01-03 +### Fixed +- Get partial overview when `IMAP::ST_UID` is set #74 +- Unnecessary "'" removed from address names +- Folder referral typo fixed +- Legacy protocol fixed +- Treat message collection keys always as strings + +### Added +- Configurable supported default flags added +- Message attribute class added to unify value handling +- Address class added and integrated +- Alias `Message::attachments()` for `Message::getAttachments()` added +- Alias `Message::addFlag()` for `Message::setFlag()` added +- Alias `Message::removeFlag()` for `Message::unsetFlag()` added +- Alias `Message::flags()` for `Message::getFlags()` added +- New Exception `MessageFlagException::class` added +- New method `Message::setSequenceId($id)` added +- Optional Header attributizion option added + +### Affected Classes +- [Folder::class](src/Folder.php) +- [Header::class](src/Header.php) +- [Message::class](src/Message.php) +- [Address::class](src/Address.php) +- [Query::class](src/Query/Query.php) +- [Attribute::class](src/Attribute.php) + +### Breaking changes +- Stringified message headers are now separated by ", " instead of " ". +- All message header values such as subject, message_id, from, to, etc now consists of an `Àttribute::class` instance (should behave the same way as before, but might cause some problem in certain edge cases) +- The formal address object "from", "to", etc now consists of an `Address::class` instance (should behave the same way as before, but might cause some problem in certain edge cases) +- When fetching or manipulating message flags a `MessageFlagException::class` exception can be thrown if a runtime error occurs +- Learn more about the new `Attribute` class here: [www.php-imap.com/api/attribute](https://www.php-imap.com/api/attribute) +- Learn more about the new `Address` class here: [www.php-imap.com/api/address](https://www.php-imap.com/api/address) +- Folder attribute "referal" is now called "referral" + +## [2.3.1] - 2020-12-30 +### Fixed +- Missing RFC attributes added +- Set the message sequence when idling +- Missing UID commands added #64 + +### Added +- Get a message by its message number +- Get a message by its uid #72 #66 #63 + +### Affected Classes +- [Message::class](src/Message.php) +- [Folder::class](src/Folder.php) +- [Query::class](src/Query/Query.php) + +## [2.3.0] - 2020-12-21 +### Fixed +- Cert validation issue fixed +- Allow boundaries ending with a space or semicolon (thanks [@smartilabs](https://github.com/smartilabs)) +- Ignore IMAP DONE command response #57 +- Default `options.fetch` set to `IMAP::FT_PEEK` +- Address parsing fixed #60 +- Alternative rfc822 header parsing fixed #60 +- Parse more than one Received: header #61 +- Fetch folder overview fixed +- `Message::getTextBody()` fallback value fixed + +### Added +- Proxy support added +- Flexible disposition support added #58 +- New `options.message_key` option `uid` added +- Protocol UID support added +- Flexible sequence type support added + +### Affected Classes +- [Structure::class](src/Structure.php) +- [Query::class](src/Query/Query.php) +- [Client::class](src/Client.php) +- [Header::class](src/Header.php) +- [Folder::class](src/Folder.php) +- [Part::class](src/Part.php) + +### Breaking changes +- Depending on your configuration, your certificates actually get checked. Which can cause an aborted connection if the certificate can not be validated. +- Messages don't get flagged as read unless you are using your own custom config. +- All `Header::class` attribute keys are now in a snake_format and no longer minus-separated. +- `Message::getTextBody()` no longer returns false if no text body is present. `null` is returned instead. + +## [2.2.5] - 2020-12-11 +### Fixed +- Missing array decoder method added #51 (thanks [@lutchin](https://github.com/lutchin)) +- Additional checks added to prevent message from getting marked as seen #33 +- Boundary parsing improved #39 #36 (thanks [@AntonioDiPassio-AppSys](https://github.com/AntonioDiPassio-AppSys)) +- Idle operation updated #44 + +### Added +- Force a folder to be opened + +### Affected Classes +- [Header::class](src/Header.php) +- [Folder::class](src/Folder.php) +- [Query::class](src/Query/Query.php) +- [Message::class](src/Message.php) +- [Structure::class](src/Structure.php) + +## [2.2.4] - 2020-12-08 +### Fixed +- Search performance increased by fetching all headers, bodies and flags at once #42 +- Legacy protocol support updated +- Fix Query pagination. (#52 [@mikemiller891](https://github.com/mikemiller891)) + +### Added +- Missing message setter methods added +- `Folder::overview()` method added to fetch all headers of all messages in the current folder + +### Affected Classes +- [Message::class](src/Message.php) +- [Folder::class](src/Folder.php) +- [Query::class](src/Query/Query.php) +- [PaginatedCollection::class](src/Support/PaginatedCollection.php) + +## [2.2.3] - 2020-11-02 +### Fixed +- Text/Html body fetched as attachment if subtype is null #34 +- Potential header overwriting through header extensions #35 +- Prevent empty attachments #37 + +### Added +- Set fetch order during query #41 [@Max13](https://github.com/Max13) + +### Affected Classes +- [Message::class](src/Message.php) +- [Part::class](src/Part.php) +- [Header::class](src/Header.php) +- [Query::class](src/Query/Query.php) + + +## [2.2.2] - 2020-10-20 +### Fixed +- IMAP::FT_PEEK removing "Seen" flag issue fixed #33 + +### Affected Classes +- [Message::class](src/Message.php) + +## [2.2.1] - 2020-10-19 +### Fixed +- Header decoding problem fixed #31 + +### Added +- Search for messages by message-Id +- Search for messages by In-Reply-To +- Message threading added `Message::thread()` +- Default folder locations added + +### Affected Classes +- [Query::class](src/Query/Query.php) +- [Message::class](src/Message.php) +- [Header::class](src/Header.php) + + +## [2.2.0] - 2020-10-16 +### Fixed +- Prevent text bodies from being fetched as attachment #27 +- Missing variable check added to prevent exception while parsing an address [webklex/laravel-imap #356](https://github.com/Webklex/laravel-imap/issues/356) +- Missing variable check added to prevent exception while parsing a part subtype #27 +- Missing variable check added to prevent exception while parsing a part content-type [webklex/laravel-imap #356](https://github.com/Webklex/laravel-imap/issues/356) +- Mixed message header attribute `in_reply_to` "unified" to be always an array #26 +- Potential message moving / copying problem fixed #29 +- Move messages by using `Protocol::moveMessage()` instead of `Protocol::copyMessage()` and `Message::delete()` #29 + +### Added +- `Protocol::moveMessage()` method added #29 + +### Affected Classes +- [Message::class](src/Message.php) +- [Header::class](src/Header.php) +- [Part::class](src/Part.php) + +### Breaking changes +- Text bodies might no longer get fetched as attachment +- `Message::$in_reply_to` type changed from mixed to array + +## [2.1.13] - 2020-10-13 +### Fixed +- Boundary detection problem fixed (#28 [@DasTobbel](https://github.com/DasTobbel)) +- Content-Type detection problem fixed (#28 [@DasTobbel](https://github.com/DasTobbel)) + +### Affected Classes +- [Structure::class](src/Structure.php) + +## [2.1.12] - 2020-10-13 +### Fixed +- If content disposition is multiline, implode the array to a simple string (#25 [@DasTobbel](https://github.com/DasTobbel)) + +### Affected Classes +- [Part::class](src/Part.php) + +## [2.1.11] - 2020-10-13 +### Fixed +- Potential problematic prefixed white-spaces removed from header attributes + +### Added +- Expended `Client::getFolder($name, $deleimiter = null)` to accept either a folder name or path ([@DasTobbel](https://github.com/DasTobbel)) +- Special MS-Exchange header decoding support added + +### Affected Classes +- [Client::class](src/Client.php) +- [Header::class](src/Header.php) + +## [2.1.10] - 2020-10-09 +### Added +- `ClientManager::make()` method added to support undefined accounts + +### Affected Classes +- [ClientManager::class](src/ClientManager.php) + +## [2.1.9] - 2020-10-08 +### Fixed +- Fix inline attachments and embedded images (#22 [@dwalczyk](https://github.com/dwalczyk)) + +### Added +- Alternative attachment names support added (#20 [@oneFoldSoftware](https://github.com/oneFoldSoftware)) +- Fetch message content without leaving a "Seen" flag behind + +### Affected Classes +- [Attachment::class](src/Attachment.php) +- [Message::class](src/Message.php) +- [Part::class](src/Part.php) +- [Query::class](src/Query/Query.php) + +## [2.1.8] - 2020-10-08 +### Fixed +- Possible error during address decoding fixed (#16 [@Slauta](https://github.com/Slauta)) +- Flag event dispatching fixed #15 + +### Added +- Support multiple boundaries (#17, #19 [@dwalczyk](https://github.com/dwalczyk)) + +### Affected Classes +- [Structure::class](src/Structure.php) + +## [2.1.7] - 2020-10-03 +### Fixed +- Fixed `Query::paginate()` (#13 #14 by [@Max13](https://github.com/Max13)) + +### Affected Classes +- [Query::class](src/Query/Query.php) + +## [2.1.6] - 2020-10-02 +### Fixed +- `Message::getAttributes()` hasn't returned all parameters + +### Affected Classes +- [Message::class](src/Message.php) + +### Added +- Part number added to attachment +- `Client::getFolderByPath()` added (#12 by [@Max13](https://github.com/Max13)) +- `Client::getFolderByName()` added (#12 by [@Max13](https://github.com/Max13)) +- Throws exceptions if the authentication fails (#11 by [@Max13](https://github.com/Max13)) + +### Affected Classes +- [Client::class](src/Client.php) + +## [2.1.5] - 2020-09-30 +### Fixed +- Wrong message content property reference fixed (#10) + +## [2.1.4] - 2020-09-30 +### Fixed +- Fix header extension values +- Part header detection method changed (#10) + +### Affected Classes +- [Header::class](src/Header.php) +- [Part::class](src/Part.php) + +## [2.1.3] - 2020-09-29 +### Fixed +- Possible decoding problem fixed +- `Str::class` dependency removed from `Header::class` + +### Affected Classes +- [Header::class](src/Header.php) + +## [2.1.2] - 2020-09-28 +### Fixed +- Dependency problem in `Attachement::getExtension()` fixed (#9) + +### Affected Classes +- [Attachment::class](src/Attachment.php) + +## [2.1.1] - 2020-09-23 +### Fixed +- Missing default config parameter added + +### Added +- Default account config fallback added + +### Affected Classes +- [Client::class](src/Client.php) + +## [2.1.0] - 2020-09-22 +### Fixed +- Quota handling fixed + +### Added +- Event system and callbacks added + +### Affected Classes +- [Client::class](src/Client.php) +- [Folder::class](src/Folder.php) +- [Message::class](src/Message.php) + +## [2.0.1] - 2020-09-20 +### Fixed +- Carbon dependency fixed + +## [2.0.0] - 2020-09-20 +### Fixed +- Missing pagination item records fixed + +### Added +- php-imap module replaced by direct socket communication +- Legacy support added +- IDLE support added +- oAuth support added +- Charset detection method updated +- Decoding fallback charsets added + +### Affected Classes +- All + +## [1.4.5] - 2019-01-23 +### Fixed +- .csv attachement is not processed +- mail part structure property comparison changed to lowercase +- Replace helper functions for Laravel 6.0 #4 (@koenhoeijmakers) +- Date handling in Folder::appendMessage() fixed +- Carbon Exception Parse Data +- Convert sender name from non-utf8 to uf8 (@hwilok) +- Convert encoding of personal data struct + +### Added +- Path prefix option added to Client::getFolder() method +- Attachment size handling added +- Find messages by custom search criteria + +### Affected Classes +- [Query::class](src/Query/WhereQuery.php) +- [Mask::class](src/Support/Masks/Mask.php) +- [Attachment::class](src/Attachment.php) +- [Client::class](src/Client.php) +- [Folder::class](src/Folder.php) +- [Message::class](src/Message.php) + +## [1.4.2.1] - 2019-07-03 +### Fixed +- Error in Attachment::__construct #3 +- Examples added + +## [1.4.2] - 2019-07-02 +### Fixed +- Pagination count total bug #213 +- Changed internal message move and copy methods #210 +- Query::since() query returning empty response #215 +- Carbon Exception Parse Data #45 +- Reading a blank body (text / html) but only from this sender #203 +- Problem with Message::moveToFolder() and multiple moves #31 +- Problem with encoding conversion #203 +- Message null value attribute problem fixed +- Client connection path handling changed to be handled inside the calling method #31 +- iconv(): error suppressor for //IGNORE added #184 +- Typo Folder attribute fullName changed to full_name +- Query scope error fixed #153 +- Replace embedded image with URL #151 +- Fix sender name in non-latin emails sent from Gmail (#155) +- Fix broken non-latin characters in body in ASCII (us-ascii) charset #156 +- Message::getMessageId() returns wrong value #197 +- Message date validation extended #45 #192 +- Removed "-i" from "iso-8859-8-i" in Message::parseBody #146 + +### Added +- Message::getFolder() method +- Create a fast count method for queries #216 +- STARTTLS encryption alias added +- Mailbox fetching exception added #201 +- Message::moveToFolder() fetches new Message::class afterwards #31 +- Message structure accessor added #182 +- Shadow Imap const class added #188 +- Connectable "NOT" queries added +- Additional where methods added +- Message attribute handling changed +- Attachment attribute handling changed +- Message flag handling updated +- Message::getHTMLBody($callback) extended +- Masks added (take look at the examples for more information on masks) +- More examples added +- Query::paginate() method added +- Imap client timeout can be modified and read #186 +- Decoder config options added #175 +- Message search criteria "NOT" added #181 +- Invalid message date exception added +- Blade examples + +### Breaking changes +- Message::moveToFolder() returns either a Message::class instance or null and not a boolean +- Folder::fullName is now Folder::full_name +- Attachment::image_src might no longer work as expected - use Attachment::getImageSrc() instead + +### Affected Classes +- [Folder::class](src/Folder.php) +- [Client::class](src/Client.php) +- [Message::class](src/Message.php) +- [Attachment::class](src/Attachment.php) +- [Query::class](src/Query/Query.php) +- [WhereQuery::class](src/Query/WhereQuery.php) + +## 0.0.3 - 2018-12-02 +### Fixed +- Folder delimiter check added #137 +- Config setting not getting loaded +- Date parsing updated + +### Affected Classes +- [Folder::class](src/IMAP/Client.php) +- [Folder::class](src/IMAP/Message.php) + +## 0.0.1 - 2018-08-13 +### Added +- new php-imap package (fork from [webklex/laravel-imap](https://github.com/Webklex/laravel-imap)) diff --git a/htdocs/includes/Webklex/php-imap/CODE_OF_CONDUCT.md b/htdocs/includes/Webklex/php-imap/CODE_OF_CONDUCT.md new file mode 100644 index 00000000000..2ed07c83f5f --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at github@webklex.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/htdocs/includes/Webklex/php-imap/LICENSE b/htdocs/includes/Webklex/php-imap/LICENSE new file mode 100644 index 00000000000..6c13191e712 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 Webklex + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/htdocs/includes/Webklex/php-imap/LICENSE.md b/htdocs/includes/Webklex/php-imap/LICENSE.md new file mode 100644 index 00000000000..feae5f320dc --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/LICENSE.md @@ -0,0 +1,21 @@ +# The MIT License (MIT) + +Copyright (c) 2016 Malte Goldenbaum + +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in +> all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +> THE SOFTWARE. diff --git a/htdocs/includes/Webklex/php-imap/README.md b/htdocs/includes/Webklex/php-imap/README.md new file mode 100755 index 00000000000..7a02da9ce74 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/README.md @@ -0,0 +1,167 @@ + +# IMAP Library for PHP + +[![Latest release on Packagist][ico-release]][link-packagist] +[![Latest prerelease on Packagist][ico-prerelease]][link-packagist] +[![Software License][ico-license]][link-license] +[![Build Status][ico-travis]][link-scrutinizer] +[![Total Downloads][ico-downloads]][link-downloads] +[![Hits][ico-hits]][link-hits] +[![Discord][ico-discord]][link-discord] +[![Snyk][ico-snyk]][link-snyk] + + +## Description +PHP-IMAP is a wrapper for common IMAP communication without the need to have the php-imap module installed / enabled. +The protocol is completely integrated and therefore supports IMAP IDLE operation and the "new" oAuth authentication +process as well. +You can enable the `php-imap` module in order to handle edge cases, improve message decoding quality and is required if +you want to use legacy protocols such as pop3. + +Official documentation: [php-imap.com](https://www.php-imap.com/) + +Laravel wrapper: [webklex/laravel-imap](https://github.com/Webklex/laravel-imap) + +Discord: [discord.gg/jCcZWCSq][link-discord] + +## Table of Contents +- [Documentations](#documentations) +- [Basic usage example](#basic-usage-example) +- [Known issues](#known-issues) +- [Support](#support) +- [Features & pull requests](#features--pull-requests) +- [Security](#security) +- [Credits](#credits) +- [License](#license) + + +## Documentations +- Legacy (< v2.0.0): [legacy documentation](https://github.com/Webklex/php-imap/tree/1.4.5) +- Core documentation: [php-imap.com](https://www.php-imap.com/) + + +## Basic usage example +This is a basic example, which will echo out all Mails within all imap folders +and will move every message into INBOX.read. Please be aware that this should not be +tested in real life and is only meant to gives an impression on how things work. + +```php +use Webklex\PHPIMAP\ClientManager; + +$cm = new ClientManager('path/to/config/imap.php'); + +/** @var \Webklex\PHPIMAP\Client $client */ +$client = $cm->account('account_identifier'); + +//Connect to the IMAP Server +$client->connect(); + +//Get all Mailboxes +/** @var \Webklex\PHPIMAP\Support\FolderCollection $folders */ +$folders = $client->getFolders(); + +//Loop through every Mailbox +/** @var \Webklex\PHPIMAP\Folder $folder */ +foreach($folders as $folder){ + + //Get all Messages of the current Mailbox $folder + /** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */ + $messages = $folder->messages()->all()->get(); + + /** @var \Webklex\PHPIMAP\Message $message */ + foreach($messages as $message){ + echo $message->getSubject().'
'; + echo 'Attachments: '.$message->getAttachments()->count().'
'; + echo $message->getHTMLBody(); + + //Move the current Message to 'INBOX.read' + if($message->move('INBOX.read') == true){ + echo 'Message has been moved'; + }else{ + echo 'Message could not be moved'; + } + } +} +``` + + +### Known issues +| Error | Solution | +| ------------------------------------------------------------------------- | ---------------------------------------------------------- | +| Kerberos error: No credentials cache file found (try running kinit) (...) | Uncomment "DISABLE_AUTHENTICATOR" inside your config and use the `legacy-imap` protocol | + + +## Support +If you encounter any problems or if you find a bug, please don't hesitate to create a new [issue](https://github.com/Webklex/php-imap/issues). +However please be aware that it might take some time to get an answer. +Off topic, rude or abusive issues will be deleted without any notice. + +If you need **commercial** support, feel free to send me a mail at github@webklex.com. + + +##### A little notice +If you write source code in your issue, please consider to format it correctly. This makes it so much nicer to read +and people are more likely to comment and help :) + +```php + +echo 'your php code...'; + +``` + +will turn into: +```php +echo 'your php code...'; +``` + + +## Features & pull requests +Everyone can contribute to this project. Every pull request will be considered but it can also happen to be declined. +To prevent unnecessary work, please consider to create a [feature issue](https://github.com/Webklex/php-imap/issues/new?template=feature_request.md) +first, if you're planning to do bigger changes. Of course you can also create a new [feature issue](https://github.com/Webklex/php-imap/issues/new?template=feature_request.md) +if you're just wishing a feature ;) + + +## Change log +Please see [CHANGELOG][link-changelog] for more information what has changed recently. + + +## Security +If you discover any security related issues, please email github@webklex.com instead of using the issue tracker. + + +## Credits +- [Webklex][link-author] +- [All Contributors][link-contributors] + + +## License +The MIT License (MIT). Please see [License File][link-license] for more information. + + +[ico-release]: https://img.shields.io/packagist/v/Webklex/php-imap.svg?style=flat-square&label=version +[ico-prerelease]: https://img.shields.io/github/v/release/webklex/php-imap?include_prereleases&style=flat-square&label=pre-release +[ico-license]: https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square +[ico-travis]: https://img.shields.io/travis/Webklex/php-imap/master.svg?style=flat-square +[ico-scrutinizer]: https://img.shields.io/scrutinizer/coverage/g/Webklex/php-imap.svg?style=flat-square +[ico-code-quality]: https://img.shields.io/scrutinizer/g/Webklex/php-imap.svg?style=flat-square +[ico-downloads]: https://img.shields.io/packagist/dt/Webklex/php-imap.svg?style=flat-square +[ico-build]: https://img.shields.io/scrutinizer/build/g/Webklex/php-imap/master?style=flat-square +[ico-quality]: https://img.shields.io/scrutinizer/quality/g/Webklex/php-imap/master?style=flat-square +[ico-hits]: https://hits.webklex.com/svg/webklex/php-imap +[ico-snyk]: https://snyk-widget.herokuapp.com/badge/composer/webklex/php-imap/badge.svg +[ico-discord]: https://img.shields.io/static/v1?label=discord&message=open&color=5865f2&style=flat-square + +[link-packagist]: https://packagist.org/packages/Webklex/php-imap +[link-travis]: https://travis-ci.org/Webklex/php-imap +[link-scrutinizer]: https://scrutinizer-ci.com/g/Webklex/php-imap/code-structure +[link-code-quality]: https://scrutinizer-ci.com/g/Webklex/php-imap +[link-downloads]: https://packagist.org/packages/Webklex/php-imap +[link-author]: https://github.com/webklex +[link-contributors]: https://github.com/Webklex/php-imap/graphs/contributors +[link-license]: https://github.com/Webklex/php-imap/blob/master/LICENSE +[link-changelog]: https://github.com/Webklex/php-imap/blob/master/CHANGELOG.md +[link-jetbrains]: https://www.jetbrains.com +[link-hits]: https://hits.webklex.com +[link-snyk]: https://snyk.io/vuln/composer:webklex%2Fphp-imap +[link-discord]: https://discord.gg/jCcZWCSq diff --git a/htdocs/includes/Webklex/php-imap/_config.yml b/htdocs/includes/Webklex/php-imap/_config.yml new file mode 100644 index 00000000000..c4192631f25 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-cayman \ No newline at end of file diff --git a/htdocs/includes/Webklex/php-imap/composer.json b/htdocs/includes/Webklex/php-imap/composer.json new file mode 100644 index 00000000000..2a62e223ea6 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/composer.json @@ -0,0 +1,55 @@ +{ + "name": "webklex/php-imap", + "type": "library", + "description": "PHP IMAP client", + "keywords": [ + "webklex", + "imap", + "pop3", + "php-imap", + "mail" + ], + "homepage": "https://github.com/webklex/php-imap", + "license": "MIT", + "authors": [ + { + "name": "Malte Goldenbaum", + "email": "github@webklex.com", + "role": "Developer" + } + ], + "require": { + "php": ">=7.0.0", + "ext-openssl": "*", + "ext-json": "*", + "ext-mbstring": "*", + "ext-iconv": "*", + "ext-fileinfo": "*", + "nesbot/carbon": ">=1.0", + "symfony/http-foundation": ">=2.8.0", + "illuminate/pagination": ">=5.0.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "autoload": { + "psr-4": { + "Webklex\\PHPIMAP\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "Tests\\": "tests" + } + }, + "scripts": { + "test": "phpunit" + }, + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "minimum-stability": "dev", + "prefer-stable": true +} diff --git a/htdocs/includes/Webklex/php-imap/examples/custom_attachment_mask.php b/htdocs/includes/Webklex/php-imap/examples/custom_attachment_mask.php new file mode 100644 index 00000000000..32b7b91ef32 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/examples/custom_attachment_mask.php @@ -0,0 +1,56 @@ +id, $this->getMessage()->getUid(), $this->name]); + } + + /** + * Custom attachment saving method + * @return bool + */ + public function custom_save() { + $path = "foo".DIRECTORY_SEPARATOR."bar".DIRECTORY_SEPARATOR; + $filename = $this->token(); + + return file_put_contents($path.$filename, $this->getContent()) !== false; + } + +} + +/** @var \Webklex\PHPIMAP\Client $client */ +$cm = new \Webklex\PHPIMAP\ClientManager('path/to/config/imap.php'); +$client = $cm->account('default'); +$client->connect(); +$client->setDefaultAttachmentMask(CustomAttachmentMask::class); + +/** @var \Webklex\PHPIMAP\Folder $folder */ +$folder = $client->getFolder('INBOX'); + +/** @var \Webklex\PHPIMAP\Message $message */ +$message = $folder->query()->limit(1)->get()->first(); + +/** @var \Webklex\PHPIMAP\Attachment $attachment */ +$attachment = $message->getAttachments()->first(); + +/** @var CustomAttachmentMask $masked_attachment */ +$masked_attachment = $attachment->mask(); + +echo 'Token for uid ['.$masked_attachment->getMessage()->getUid().']: '.$masked_attachment->token(); + +$masked_attachment->custom_save(); \ No newline at end of file diff --git a/htdocs/includes/Webklex/php-imap/examples/custom_message_mask.php b/htdocs/includes/Webklex/php-imap/examples/custom_message_mask.php new file mode 100644 index 00000000000..25d05667623 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/examples/custom_message_mask.php @@ -0,0 +1,50 @@ +message_id, $this->uid, $this->message_no]); + } + + /** + * Get number of message attachments + * @return integer + */ + public function getAttachmentCount() { + return $this->getAttachments()->count(); + } + +} + +/** @var \Webklex\PHPIMAP\Client $client */ +$cm = new \Webklex\PHPIMAP\ClientManager('path/to/config/imap.php'); +$client = $cm->account('default'); +$client->connect(); + +/** @var \Webklex\PHPIMAP\Folder $folder */ +$folder = $client->getFolder('INBOX'); + +/** @var \Webklex\PHPIMAP\Message $message */ +$message = $folder->query()->limit(1)->get()->first(); + +/** @var CustomMessageMask $masked_message */ +$masked_message = $message->mask(CustomMessageMask::class); + +echo 'Token for uid ['.$masked_message->uid.']: '.$masked_message->token().' @atms:'.$masked_message->getAttachmentCount(); + +$masked_message->setFlag('seen'); + diff --git a/htdocs/includes/Webklex/php-imap/examples/folder_structure.blade.php b/htdocs/includes/Webklex/php-imap/examples/folder_structure.blade.php new file mode 100644 index 00000000000..a80dfb6cece --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/examples/folder_structure.blade.php @@ -0,0 +1,42 @@ + +
'.$langs->trans("Login").''; print $form->selectarray('operationtype', $arrayoftypes, '', 1, 0, 0, '', 1, 0, 0, '', 'maxwidth300', 1); print ''; - print ''; + //print ''; + $htmltext = $langs->transnoentitiesnoconv("OperationParamDesc"); + print $form->textwithpicto('', $htmltext, 1, 'help', '', 0, 2, 'operationparamtt'); print ''; - $htmltext = $langs->transnoentitiesnoconv("OperationParamDesc"); - print $form->textwithpicto('', $htmltext, 1, 'help', '', 0, 2, 'operationparamtt'); print '
'; print img_picto($langs->trans("LotSerial"), 'lot', 'class="paddingright"'); - print ''; + print ''; print ''; - print $productstatic->getNomUrl(1).' - '.$productstatic->label; + print $productstatic->getNomUrl(1).' - '.dol_escape_htmltag($productstatic->label); print ''; - print $val['batch']; + print dol_escape_htmltag($val['batch']); print ''.$val['qty'].''.price2num((float) $val['qty'], 'MS').''.img_delete($langs->trans("Remove")).'
+ + + + + + + + count() > 0): ?> + + + + + + + + + + + + +
FolderUnread messages
name; ?>search()->unseen()->setFetchBody(false)->count(); ?>
No folders found
+ +links(); ?> \ No newline at end of file diff --git a/htdocs/includes/Webklex/php-imap/examples/message_table.blade.php b/htdocs/includes/Webklex/php-imap/examples/message_table.blade.php new file mode 100644 index 00000000000..c3bd7af8eb5 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/examples/message_table.blade.php @@ -0,0 +1,46 @@ + + + + + + + + + + + + count() > 0): ?> + + + + + + + + + + + + + + +
UIDSubjectFromAttachments
getUid(); ?>getSubject(); ?>getFrom()[0]->mail; ?>getAttachments()->count() > 0 ? 'yes' : 'no'; ?>
No messages found
+ +links(); ?> \ No newline at end of file diff --git a/htdocs/includes/Webklex/php-imap/phpunit.xml b/htdocs/includes/Webklex/php-imap/phpunit.xml new file mode 100644 index 00000000000..bfbb0b093c9 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/phpunit.xml @@ -0,0 +1,32 @@ + + + + + tests + + + + + src/ + + + + + + + + + + + + + \ No newline at end of file diff --git a/htdocs/includes/Webklex/php-imap/src/Address.php b/htdocs/includes/Webklex/php-imap/src/Address.php new file mode 100644 index 00000000000..96e48d94b6f --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/Address.php @@ -0,0 +1,90 @@ +personal = $object->personal; } + if (property_exists($object, "mailbox")){ $this->mailbox = $object->mailbox; } + if (property_exists($object, "host")){ $this->host = $object->host; } + if (property_exists($object, "mail")){ $this->mail = $object->mail; } + if (property_exists($object, "full")){ $this->full = $object->full; } + } + + + /** + * Return the stringified address + * + * @return string + */ + public function __toString() { + return $this->full ?: ""; + } + + /** + * Return the serialized address + * + * @return array + */ + public function __serialize(){ + return [ + "personal" => $this->personal, + "mailbox" => $this->mailbox, + "host" => $this->host, + "mail" => $this->mail, + "full" => $this->full, + ]; + } + + /** + * Convert instance to array + * + * @return array + */ + public function toArray(): array { + return $this->__serialize(); + } + + /** + * Return the stringified attribute + * + * @return string + */ + public function toString(): string { + return $this->__toString(); + } +} \ No newline at end of file diff --git a/htdocs/includes/Webklex/php-imap/src/Attachment.php b/htdocs/includes/Webklex/php-imap/src/Attachment.php new file mode 100755 index 00000000000..cff02269202 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/Attachment.php @@ -0,0 +1,346 @@ + null, + 'type' => null, + 'part_number' => 0, + 'content_type' => null, + 'id' => null, + 'name' => null, + 'disposition' => null, + 'img_src' => null, + 'size' => null, + ]; + + /** + * Default mask + * + * @var string $mask + */ + protected $mask = AttachmentMask::class; + + /** + * Attachment constructor. + * @param Message $oMessage + * @param Part $part + */ + public function __construct(Message $oMessage, Part $part) { + $this->config = ClientManager::get('options'); + + $this->oMessage = $oMessage; + $this->part = $part; + $this->part_number = $part->part_number; + + $default_mask = $this->oMessage->getClient()->getDefaultAttachmentMask(); + if($default_mask != null) { + $this->mask = $default_mask; + } + + $this->findType(); + $this->fetch(); + } + + /** + * Call dynamic attribute setter and getter methods + * @param string $method + * @param array $arguments + * + * @return mixed + * @throws MethodNotFoundException + */ + public function __call(string $method, array $arguments) { + if(strtolower(substr($method, 0, 3)) === 'get') { + $name = Str::snake(substr($method, 3)); + + if(isset($this->attributes[$name])) { + return $this->attributes[$name]; + } + + return null; + }elseif (strtolower(substr($method, 0, 3)) === 'set') { + $name = Str::snake(substr($method, 3)); + + $this->attributes[$name] = array_pop($arguments); + + return $this->attributes[$name]; + } + + throw new MethodNotFoundException("Method ".self::class.'::'.$method.'() is not supported'); + } + + /** + * Magic setter + * @param $name + * @param $value + * + * @return mixed + */ + public function __set($name, $value) { + $this->attributes[$name] = $value; + + return $this->attributes[$name]; + } + + /** + * magic getter + * @param $name + * + * @return mixed|null + */ + public function __get($name) { + if(isset($this->attributes[$name])) { + return $this->attributes[$name]; + } + + return null; + } + + /** + * Determine the structure type + */ + protected function findType() { + switch ($this->part->type) { + case IMAP::ATTACHMENT_TYPE_MESSAGE: + $this->type = 'message'; + break; + case IMAP::ATTACHMENT_TYPE_APPLICATION: + $this->type = 'application'; + break; + case IMAP::ATTACHMENT_TYPE_AUDIO: + $this->type = 'audio'; + break; + case IMAP::ATTACHMENT_TYPE_IMAGE: + $this->type = 'image'; + break; + case IMAP::ATTACHMENT_TYPE_VIDEO: + $this->type = 'video'; + break; + case IMAP::ATTACHMENT_TYPE_MODEL: + $this->type = 'model'; + break; + case IMAP::ATTACHMENT_TYPE_TEXT: + $this->type = 'text'; + break; + case IMAP::ATTACHMENT_TYPE_MULTIPART: + $this->type = 'multipart'; + break; + default: + $this->type = 'other'; + break; + } + } + + /** + * Fetch the given attachment + */ + protected function fetch() { + + $content = $this->part->content; + + $this->content_type = $this->part->content_type; + $this->content = $this->oMessage->decodeString($content, $this->part->encoding); + + if (($id = $this->part->id) !== null) { + $this->id = str_replace(['<', '>'], '', $id); + } + + $this->size = $this->part->bytes; + $this->disposition = $this->part->disposition; + + if (($filename = $this->part->filename) !== null) { + $this->setName($filename); + } elseif (($name = $this->part->name) !== null) { + $this->setName($name); + }else { + $this->setName("undefined"); + } + + if (IMAP::ATTACHMENT_TYPE_MESSAGE == $this->part->type) { + if ($this->part->ifdescription) { + $this->setName($this->part->description); + } else { + $this->setName($this->part->subtype); + } + } + } + + /** + * Save the attachment content to your filesystem + * @param string $path + * @param string|null $filename + * + * @return boolean + */ + public function save(string $path, $filename = null): bool { + $filename = $filename ?: $this->getName(); + + return file_put_contents($path.$filename, $this->getContent()) !== false; + } + + /** + * Set the attachment name and try to decode it + * @param $name + */ + public function setName($name) { + $decoder = $this->config['decoder']['attachment']; + if ($name !== null) { + if($decoder === 'utf-8' && extension_loaded('imap')) { + $this->name = \imap_utf8($name); + }else{ + $this->name = mb_decode_mimeheader($name); + } + } + } + + /** + * Get the attachment mime type + * + * @return string|null + */ + public function getMimeType(){ + return (new \finfo())->buffer($this->getContent(), FILEINFO_MIME_TYPE); + } + + /** + * Try to guess the attachment file extension + * + * @return string|null + */ + public function getExtension(){ + $deprecated_guesser = "\Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser"; + if (class_exists($deprecated_guesser) !== false){ + /** @var \Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser $deprecated_guesser */ + return $deprecated_guesser::getInstance()->guess($this->getMimeType()); + } + $guesser = "\Symfony\Component\Mime\MimeTypes"; + /** @var Symfony\Component\Mime\MimeTypes $guesser */ + $extensions = $guesser::getDefault()->getExtensions($this->getMimeType()); + return $extensions[0] ?? null; + } + + /** + * Get all attributes + * + * @return array + */ + public function getAttributes(): array { + return $this->attributes; + } + + /** + * @return Message + */ + public function getMessage(): Message { + return $this->oMessage; + } + + /** + * Set the default mask + * @param $mask + * + * @return $this + */ + public function setMask($mask): Attachment { + if(class_exists($mask)){ + $this->mask = $mask; + } + + return $this; + } + + /** + * Get the used default mask + * + * @return string + */ + public function getMask(): string { + return $this->mask; + } + + /** + * Get a masked instance by providing a mask name + * @param string|null $mask + * + * @return mixed + * @throws MaskNotFoundException + */ + public function mask($mask = null){ + $mask = $mask !== null ? $mask : $this->mask; + if(class_exists($mask)){ + return new $mask($this); + } + + throw new MaskNotFoundException("Unknown mask provided: ".$mask); + } +} \ No newline at end of file diff --git a/htdocs/includes/Webklex/php-imap/src/Attribute.php b/htdocs/includes/Webklex/php-imap/src/Attribute.php new file mode 100644 index 00000000000..2f3aab0fee4 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/Attribute.php @@ -0,0 +1,267 @@ +setName($name); + $this->add($value); + } + + + /** + * Return the stringified attribute + * + * @return string + */ + public function __toString() { + return implode(", ", $this->values); + } + + /** + * Return the stringified attribute + * + * @return string + */ + public function toString(): string { + return $this->__toString(); + } + + /** + * Convert instance to array + * + * @return array + */ + public function toArray(): array { + return $this->values; + } + + /** + * Convert first value to a date object + * + * @return Carbon + */ + public function toDate(): Carbon { + $date = $this->first(); + if ($date instanceof Carbon) return $date; + + return Carbon::parse($date); + } + + /** + * Determine if a value exists at an offset. + * + * @param mixed $offset + * @return bool + */ + public function offsetExists($offset): bool { + return array_key_exists($offset, $this->values); + } + + /** + * Get a value at a given offset. + * + * @param mixed $offset + * @return mixed + */ + #[ReturnTypeWillChange] + public function offsetGet($offset) { + return $this->values[$offset]; + } + + /** + * Set the value at a given offset. + * + * @param mixed $offset + * @param mixed $value + * @return void + */ + #[ReturnTypeWillChange] + public function offsetSet($offset, $value) { + if (is_null($offset)) { + $this->values[] = $value; + } else { + $this->values[$offset] = $value; + } + } + + /** + * Unset the value at a given offset. + * + * @param string $offset + * @return void + */ + #[ReturnTypeWillChange] + public function offsetUnset($offset) { + unset($this->values[$offset]); + } + + /** + * Add one or more values to the attribute + * @param array|mixed $value + * @param boolean $strict + * + * @return Attribute + */ + public function add($value, bool $strict = false): Attribute { + if (is_array($value)) { + return $this->merge($value, $strict); + }elseif ($value !== null) { + $this->attach($value, $strict); + } + + return $this; + } + + /** + * Merge a given array of values with the current values array + * @param array $values + * @param boolean $strict + * + * @return Attribute + */ + public function merge(array $values, bool $strict = false): Attribute { + foreach ($values as $value) { + $this->attach($value, $strict); + } + + return $this; + } + + /** + * Check if the attribute contains the given value + * @param mixed $value + * + * @return bool + */ + public function contains($value): bool { + foreach ($this->values as $v) { + if ($v === $value) { + return true; + } + } + return false; + } + + /** + * Attach a given value to the current value array + * @param $value + * @param bool $strict + */ + public function attach($value, bool $strict = false) { + if ($strict === true) { + if ($this->contains($value) === false) { + $this->values[] = $value; + } + }else{ + $this->values[] = $value; + } + } + + /** + * Set the attribute name + * @param $name + * + * @return Attribute + */ + public function setName($name): Attribute { + $this->name = $name; + + return $this; + } + + /** + * Get the attribute name + * + * @return string + */ + public function getName(): string { + return $this->name; + } + + /** + * Get all values + * + * @return array + */ + public function get(): array { + return $this->values; + } + + /** + * Alias method for self::get() + * + * @return array + */ + public function all(): array { + return $this->get(); + } + + /** + * Get the first value if possible + * + * @return mixed|null + */ + public function first(){ + if ($this->offsetExists(0)) { + return $this->values[0]; + } + return null; + } + + /** + * Get the last value if possible + * + * @return mixed|null + */ + public function last(){ + if (($cnt = $this->count()) > 0) { + return $this->values[$cnt - 1]; + } + return null; + } + + /** + * Get the number of values + * + * @return int + */ + public function count(): int { + return count($this->values); + } +} \ No newline at end of file diff --git a/htdocs/includes/Webklex/php-imap/src/Client.php b/htdocs/includes/Webklex/php-imap/src/Client.php new file mode 100755 index 00000000000..c4abe3a7596 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/Client.php @@ -0,0 +1,699 @@ + null, + 'request_fulluri' => false, + 'username' => null, + 'password' => null, + ]; + + /** + * Connection timeout + * @var int $timeout + */ + public $timeout; + + /** + * Account username/ + * + * @var mixed + */ + public $username; + + /** + * Account password. + * + * @var string + */ + public $password; + + /** + * Additional data fetched from the server. + * + * @var string + */ + public $extensions; + + /** + * Account authentication method. + * + * @var string + */ + public $authentication; + + /** + * Active folder path. + * + * @var string + */ + protected $active_folder = null; + + /** + * Default message mask + * + * @var string $default_message_mask + */ + protected $default_message_mask = MessageMask::class; + + /** + * Default attachment mask + * + * @var string $default_attachment_mask + */ + protected $default_attachment_mask = AttachmentMask::class; + + /** + * Used default account values + * + * @var array $default_account_config + */ + protected $default_account_config = [ + 'host' => 'localhost', + 'port' => 993, + 'protocol' => 'imap', + 'encryption' => 'ssl', + 'validate_cert' => true, + 'username' => '', + 'password' => '', + 'authentication' => null, + "extensions" => [], + 'proxy' => [ + 'socket' => null, + 'request_fulluri' => false, + 'username' => null, + 'password' => null, + ], + "timeout" => 30 + ]; + + /** + * Client constructor. + * @param array $config + * + * @throws MaskNotFoundException + */ + public function __construct(array $config = []) { + $this->setConfig($config); + $this->setMaskFromConfig($config); + $this->setEventsFromConfig($config); + } + + /** + * Client destructor + */ + public function __destruct() { + $this->disconnect(); + } + + /** + * Set the Client configuration + * @param array $config + * + * @return self + */ + public function setConfig(array $config): Client { + $default_account = ClientManager::get('default'); + $default_config = ClientManager::get("accounts.$default_account"); + + foreach ($this->default_account_config as $key => $value) { + $this->setAccountConfig($key, $config, $default_config); + } + + return $this; + } + + /** + * Set a specific account config + * @param string $key + * @param array $config + * @param array $default_config + */ + private function setAccountConfig(string $key, array $config, array $default_config){ + $value = $this->default_account_config[$key]; + if(isset($config[$key])) { + $value = $config[$key]; + }elseif(isset($default_config[$key])) { + $value = $default_config[$key]; + } + $this->$key = $value; + } + + /** + * Look for a possible events in any available config + * @param $config + */ + protected function setEventsFromConfig($config) { + $this->events = ClientManager::get("events"); + if(isset($config['events'])){ + foreach($config['events'] as $section => $events) { + $this->events[$section] = array_merge($this->events[$section], $events); + } + } + } + + /** + * Look for a possible mask in any available config + * @param $config + * + * @throws MaskNotFoundException + */ + protected function setMaskFromConfig($config) { + $default_config = ClientManager::get("masks"); + + if(isset($config['masks'])){ + if(isset($config['masks']['message'])) { + if(class_exists($config['masks']['message'])) { + $this->default_message_mask = $config['masks']['message']; + }else{ + throw new MaskNotFoundException("Unknown mask provided: ".$config['masks']['message']); + } + }else{ + if(class_exists($default_config['message'])) { + $this->default_message_mask = $default_config['message']; + }else{ + throw new MaskNotFoundException("Unknown mask provided: ".$default_config['message']); + } + } + if(isset($config['masks']['attachment'])) { + if(class_exists($config['masks']['attachment'])) { + $this->default_attachment_mask = $config['masks']['attachment']; + }else{ + throw new MaskNotFoundException("Unknown mask provided: ".$config['masks']['attachment']); + } + }else{ + if(class_exists($default_config['attachment'])) { + $this->default_attachment_mask = $default_config['attachment']; + }else{ + throw new MaskNotFoundException("Unknown mask provided: ".$default_config['attachment']); + } + } + }else{ + if(class_exists($default_config['message'])) { + $this->default_message_mask = $default_config['message']; + }else{ + throw new MaskNotFoundException("Unknown mask provided: ".$default_config['message']); + } + + if(class_exists($default_config['attachment'])) { + $this->default_attachment_mask = $default_config['attachment']; + }else{ + throw new MaskNotFoundException("Unknown mask provided: ".$default_config['attachment']); + } + } + + } + + /** + * Get the current imap resource + * + * @return bool|Protocol|ProtocolInterface + * @throws ConnectionFailedException + */ + public function getConnection() { + $this->checkConnection(); + return $this->connection; + } + + /** + * Determine if connection was established. + * + * @return bool + */ + public function isConnected(): bool { + return $this->connection && $this->connection->connected(); + } + + /** + * Determine if connection was established and connect if not. + * + * @throws ConnectionFailedException + */ + public function checkConnection() { + if (!$this->isConnected()) { + $this->connect(); + } + } + + /** + * Force a reconnect + * + * @throws ConnectionFailedException + */ + public function reconnect() { + if ($this->isConnected()) { + $this->disconnect(); + } + $this->connect(); + } + + /** + * Connect to server. + * + * @return $this + * @throws ConnectionFailedException + */ + public function connect(): Client { + $this->disconnect(); + $protocol = strtolower($this->protocol); + + if (in_array($protocol, ['imap', 'imap4', 'imap4rev1'])) { + $this->connection = new ImapProtocol($this->validate_cert, $this->encryption); + $this->connection->setConnectionTimeout($this->timeout); + $this->connection->setProxy($this->proxy); + }else{ + if (extension_loaded('imap') === false) { + throw new ConnectionFailedException("connection setup failed", 0, new ProtocolNotSupportedException($protocol." is an unsupported protocol")); + } + $this->connection = new LegacyProtocol($this->validate_cert, $this->encryption); + if (strpos($protocol, "legacy-") === 0) { + $protocol = substr($protocol, 7); + } + $this->connection->setProtocol($protocol); + } + + if (ClientManager::get('options.debug')) { + $this->connection->enableDebug(); + } + + if (!ClientManager::get('options.uid_cache')) { + $this->connection->disableUidCache(); + } + + try { + $this->connection->connect($this->host, $this->port); + } catch (ErrorException $e) { + throw new ConnectionFailedException("connection setup failed", 0, $e); + } catch (Exceptions\RuntimeException $e) { + throw new ConnectionFailedException("connection setup failed", 0, $e); + } + $this->authenticate(); + + return $this; + } + + /** + * Authenticate the current session + * + * @throws ConnectionFailedException + */ + protected function authenticate() { + try { + if ($this->authentication == "oauth") { + if (!$this->connection->authenticate($this->username, $this->password)) { + throw new AuthFailedException(); + } + } elseif (!$this->connection->login($this->username, $this->password)) { + throw new AuthFailedException(); + } + } catch (AuthFailedException $e) { + throw new ConnectionFailedException("connection setup failed", 0, $e); + } + } + + /** + * Disconnect from server. + * + * @return $this + */ + public function disconnect(): Client { + if ($this->isConnected() && $this->connection !== false) { + $this->connection->logout(); + } + $this->active_folder = null; + + return $this; + } + + /** + * Get a folder instance by a folder name + * @param string $folder_name + * @param string|bool|null $delimiter + * + * @return mixed + * @throws ConnectionFailedException + * @throws FolderFetchingException + * @throws Exceptions\RuntimeException + */ + public function getFolder(string $folder_name, $delimiter = null) { + if ($delimiter !== false && $delimiter !== null) { + return $this->getFolderByPath($folder_name); + } + + // Set delimiter to false to force selection via getFolderByName (maybe useful for uncommon folder names) + $delimiter = is_null($delimiter) ? ClientManager::get('options.delimiter', "/") : $delimiter; + if (strpos($folder_name, (string)$delimiter) !== false) { + return $this->getFolderByPath($folder_name); + } + + return $this->getFolderByName($folder_name); + } + + /** + * Get a folder instance by a folder name + * @param $folder_name + * + * @return mixed + * @throws ConnectionFailedException + * @throws FolderFetchingException + * @throws Exceptions\RuntimeException + */ + public function getFolderByName($folder_name) { + return $this->getFolders(false)->where("name", $folder_name)->first(); + } + + /** + * Get a folder instance by a folder path + * @param $folder_path + * + * @return mixed + * @throws ConnectionFailedException + * @throws FolderFetchingException + * @throws Exceptions\RuntimeException + */ + public function getFolderByPath($folder_path) { + return $this->getFolders(false)->where("path", $folder_path)->first(); + } + + /** + * Get folders list. + * If hierarchical order is set to true, it will make a tree of folders, otherwise it will return flat array. + * + * @param boolean $hierarchical + * @param string|null $parent_folder + * + * @return FolderCollection + * @throws ConnectionFailedException + * @throws FolderFetchingException + * @throws Exceptions\RuntimeException + */ + public function getFolders(bool $hierarchical = true, string $parent_folder = null): FolderCollection { + $this->checkConnection(); + $folders = FolderCollection::make([]); + + $pattern = $parent_folder.($hierarchical ? '%' : '*'); + $items = $this->connection->folders('', $pattern); + + if(is_array($items)){ + foreach ($items as $folder_name => $item) { + $folder = new Folder($this, $folder_name, $item["delimiter"], $item["flags"]); + + if ($hierarchical && $folder->hasChildren()) { + $pattern = $folder->full_name.$folder->delimiter.'%'; + + $children = $this->getFolders(true, $pattern); + $folder->setChildren($children); + } + + $folders->push($folder); + } + + return $folders; + }else{ + throw new FolderFetchingException("failed to fetch any folders"); + } + } + + /** + * Open a given folder. + * @param string $folder_path + * @param boolean $force_select + * + * @return array|bool + * @throws ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + public function openFolder(string $folder_path, bool $force_select = false) { + if ($this->active_folder == $folder_path && $this->isConnected() && $force_select === false) { + return true; + } + $this->checkConnection(); + $this->active_folder = $folder_path; + return $this->connection->selectFolder($folder_path); + } + + /** + * Create a new Folder + * @param string $folder + * @param boolean $expunge + * + * @return Folder + * @throws ConnectionFailedException + * @throws FolderFetchingException + * @throws Exceptions\EventNotFoundException + * @throws Exceptions\RuntimeException + */ + public function createFolder(string $folder, bool $expunge = true): Folder { + $this->checkConnection(); + $status = $this->connection->createFolder($folder); + + if($expunge) $this->expunge(); + + $folder = $this->getFolder($folder); + if($status && $folder) { + $event = $this->getEvent("folder", "new"); + $event::dispatch($folder); + } + + return $folder; + } + + /** + * Check a given folder + * @param $folder + * + * @return array|bool + * @throws ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + public function checkFolder($folder) { + $this->checkConnection(); + return $this->connection->examineFolder($folder); + } + + /** + * Get the current active folder + * + * @return string + */ + public function getFolderPath(){ + return $this->active_folder; + } + + /** + * Exchange identification information + * Ref.: https://datatracker.ietf.org/doc/html/rfc2971 + * + * @param array|null $ids + * @return array|bool|void|null + * + * @throws ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + public function Id(array $ids = null) { + $this->checkConnection(); + return $this->connection->ID($ids); + } + + /** + * Retrieve the quota level settings, and usage statics per mailbox + * + * @return array + * @throws ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + public function getQuota(): array { + $this->checkConnection(); + return $this->connection->getQuota($this->username); + } + + /** + * Retrieve the quota settings per user + * @param string $quota_root + * + * @return array + * @throws ConnectionFailedException + */ + public function getQuotaRoot(string $quota_root = 'INBOX'): array { + $this->checkConnection(); + return $this->connection->getQuotaRoot($quota_root); + } + + /** + * Delete all messages marked for deletion + * + * @return bool + * @throws ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + public function expunge(): bool { + $this->checkConnection(); + return $this->connection->expunge(); + } + + /** + * Set the connection timeout + * @param integer $timeout + * + * @return Protocol + * @throws ConnectionFailedException + */ + public function setTimeout(int $timeout): Protocol { + $this->checkConnection(); + return $this->connection->setConnectionTimeout($timeout); + } + + /** + * Get the connection timeout + * + * @return int + * @throws ConnectionFailedException + */ + public function getTimeout(): int { + $this->checkConnection(); + return $this->connection->getConnectionTimeout(); + } + + /** + * Get the default message mask + * + * @return string + */ + public function getDefaultMessageMask(): string { + return $this->default_message_mask; + } + + /** + * Get the default events for a given section + * @param $section + * + * @return array + */ + public function getDefaultEvents($section): array { + return $this->events[$section]; + } + + /** + * Set the default message mask + * @param string $mask + * + * @return $this + * @throws MaskNotFoundException + */ + public function setDefaultMessageMask(string $mask): Client { + if(class_exists($mask)) { + $this->default_message_mask = $mask; + + return $this; + } + + throw new MaskNotFoundException("Unknown mask provided: ".$mask); + } + + /** + * Get the default attachment mask + * + * @return string + */ + public function getDefaultAttachmentMask(): string { + return $this->default_attachment_mask; + } + + /** + * Set the default attachment mask + * @param string $mask + * + * @return $this + * @throws MaskNotFoundException + */ + public function setDefaultAttachmentMask(string $mask): Client { + if(class_exists($mask)) { + $this->default_attachment_mask = $mask; + + return $this; + } + + throw new MaskNotFoundException("Unknown mask provided: ".$mask); + } +} diff --git a/htdocs/includes/Webklex/php-imap/src/ClientManager.php b/htdocs/includes/Webklex/php-imap/src/ClientManager.php new file mode 100644 index 00000000000..72fe4304b8e --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/ClientManager.php @@ -0,0 +1,276 @@ +setConfig($config); + } + + /** + * Dynamically pass calls to the default account. + * @param string $method + * @param array $parameters + * + * @return mixed + * @throws Exceptions\MaskNotFoundException + */ + public function __call(string $method, array $parameters) { + $callable = [$this->account(), $method]; + + return call_user_func_array($callable, $parameters); + } + + /** + * Safely create a new client instance which is not listed in accounts + * @param array $config + * + * @return Client + * @throws Exceptions\MaskNotFoundException + */ + public function make(array $config): Client { + return new Client($config); + } + + /** + * Get a dotted config parameter + * @param string $key + * @param null $default + * + * @return mixed|null + */ + public static function get(string $key, $default = null) { + $parts = explode('.', $key); + $value = null; + foreach($parts as $part) { + if($value === null) { + if(isset(self::$config[$part])) { + $value = self::$config[$part]; + }else{ + break; + } + }else{ + if(isset($value[$part])) { + $value = $value[$part]; + }else{ + break; + } + } + } + + return $value === null ? $default : $value; + } + + /** + * Resolve a account instance. + * @param string|null $name + * + * @return Client + * @throws Exceptions\MaskNotFoundException + */ + public function account(string $name = null): Client { + $name = $name ?: $this->getDefaultAccount(); + + // If the connection has not been resolved yet we will resolve it now as all + // of the connections are resolved when they are actually needed so we do + // not make any unnecessary connection to the various queue end-points. + if (!isset($this->accounts[$name])) { + $this->accounts[$name] = $this->resolve($name); + } + + return $this->accounts[$name]; + } + + /** + * Resolve an account. + * @param string $name + * + * @return Client + * @throws Exceptions\MaskNotFoundException + */ + protected function resolve(string $name): Client { + $config = $this->getClientConfig($name); + + return new Client($config); + } + + /** + * Get the account configuration. + * @param string|null $name + * + * @return array + */ + protected function getClientConfig($name): array { + if ($name === null || $name === 'null') { + return ['driver' => 'null']; + } + + return self::$config["accounts"][$name]; + } + + /** + * Get the name of the default account. + * + * @return string + */ + public function getDefaultAccount(): string { + return self::$config['default']; + } + + /** + * Set the name of the default account. + * @param string $name + * + * @return void + */ + public function setDefaultAccount(string $name) { + self::$config['default'] = $name; + } + + + /** + * Merge the vendor settings with the local config + * + * The default account identifier will be used as default for any missing account parameters. + * If however the default account is missing a parameter the package default account parameter will be used. + * This can be disabled by setting imap.default in your config file to 'false' + * + * @param array|string $config + * + * @return $this + */ + public function setConfig($config): ClientManager { + + if(is_array($config) === false) { + $config = require $config; + } + + $config_key = 'imap'; + $path = __DIR__.'/config/'.$config_key.'.php'; + + $vendor_config = require $path; + $config = $this->array_merge_recursive_distinct($vendor_config, $config); + + if(is_array($config)){ + if(isset($config['default'])){ + if(isset($config['accounts']) && $config['default'] != false){ + + $default_config = $vendor_config['accounts']['default']; + if(isset($config['accounts'][$config['default']])){ + $default_config = array_merge($default_config, $config['accounts'][$config['default']]); + } + + if(is_array($config['accounts'])){ + foreach($config['accounts'] as $account_key => $account){ + $config['accounts'][$account_key] = array_merge($default_config, $account); + } + } + } + } + } + + self::$config = $config; + + return $this; + } + + /** + * Marge arrays recursively and distinct + * + * Merges any number of arrays / parameters recursively, replacing + * entries with string keys with values from latter arrays. + * If the entry or the next value to be assigned is an array, then it + * automatically treats both arguments as an array. + * Numeric entries are appended, not replaced, but only if they are + * unique + * + * @return array|mixed + * + * @link http://www.php.net/manual/en/function.array-merge-recursive.php#96201 + * @author Mark Roduner + */ + private function array_merge_recursive_distinct() { + + $arrays = func_get_args(); + $base = array_shift($arrays); + + // From https://stackoverflow.com/a/173479 + $isAssoc = function(array $arr) { + if (array() === $arr) return false; + return array_keys($arr) !== range(0, count($arr) - 1); + }; + + if(!is_array($base)) $base = empty($base) ? array() : array($base); + + foreach($arrays as $append) { + + if(!is_array($append)) $append = array($append); + + foreach($append as $key => $value) { + + if(!array_key_exists($key, $base) and !is_numeric($key)) { + $base[$key] = $value; + continue; + } + + if( + ( + is_array($value) + && $isAssoc($value) + ) + || ( + is_array($base[$key]) + && $isAssoc($base[$key]) + ) + ) { + // If the arrays are not associates we don't want to array_merge_recursive_distinct + // else merging $baseConfig['dispositions'] = ['attachment', 'inline'] with $customConfig['dispositions'] = ['attachment'] + // results in $resultConfig['dispositions'] = ['attachment', 'inline'] + $base[$key] = $this->array_merge_recursive_distinct($base[$key], $value); + } else if(is_numeric($key)) { + if(!in_array($value, $base)) $base[] = $value; + } else { + $base[$key] = $value; + } + + } + + } + + return $base; + } +} \ No newline at end of file diff --git a/htdocs/includes/Webklex/php-imap/src/Connection/Protocols/ImapProtocol.php b/htdocs/includes/Webklex/php-imap/src/Connection/Protocols/ImapProtocol.php new file mode 100644 index 00000000000..b2949033e59 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/Connection/Protocols/ImapProtocol.php @@ -0,0 +1,1124 @@ +setCertValidation($cert_validation); + $this->encryption = $encryption; + } + + /** + * Public destructor + */ + public function __destruct() { + $this->logout(); + } + + /** + * Open connection to IMAP server + * @param string $host hostname or IP address of IMAP server + * @param int|null $port of IMAP server, default is 143 and 993 for ssl + * + * @throws ConnectionFailedException + */ + public function connect(string $host, $port = null) { + $transport = 'tcp'; + $encryption = ''; + + if ($this->encryption) { + $encryption = strtolower($this->encryption); + if (in_array($encryption, ['ssl', 'tls'])) { + $transport = $encryption; + $port = $port === null ? 993 : $port; + } + } + $port = $port === null ? 143 : $port; + try { + $this->stream = $this->createStream($transport, $host, $port, $this->connection_timeout); + if (!$this->assumedNextLine('* OK')) { + throw new ConnectionFailedException('connection refused'); + } + if ($encryption == 'starttls') { + $this->enableStartTls(); + } + } catch (Exception $e) { + throw new ConnectionFailedException('connection failed', 0, $e); + } + } + + /** + * Enable tls on the current connection + * + * @throws ConnectionFailedException + * @throws RuntimeException + */ + protected function enableStartTls(){ + $response = $this->requestAndResponse('STARTTLS'); + $result = $response && stream_socket_enable_crypto($this->stream, true, $this->getCryptoMethod()); + if (!$result) { + throw new ConnectionFailedException('failed to enable TLS'); + } + } + + /** + * Get the next line from stream + * + * @return string next line + * @throws RuntimeException + */ + public function nextLine(): string { + $line = fgets($this->stream); + + if ($line === false) { + throw new RuntimeException('failed to read - connection closed?'); + } + + return $line; + } + + /** + * Get the next line and check if it starts with a given string + * @param string $start + * + * @return bool + * @throws RuntimeException + */ + protected function assumedNextLine(string $start): bool { + $line = $this->nextLine(); + return strpos($line, $start) === 0; + } + + /** + * Get the next line and split the tag + * @param string|null $tag reference tag + * + * @return string next line + * @throws RuntimeException + */ + protected function nextTaggedLine(&$tag): string { + $line = $this->nextLine(); + list($tag, $line) = explode(' ', $line, 2); + + return $line; + } + + /** + * Split a given line in values. A value is literal of any form or a list + * @param string $line + * + * @return array + * @throws RuntimeException + */ + protected function decodeLine(string $line): array { + $tokens = []; + $stack = []; + + // replace any trailing including spaces with a single space + $line = rtrim($line) . ' '; + while (($pos = strpos($line, ' ')) !== false) { + $token = substr($line, 0, $pos); + if (!strlen($token)) { + continue; + } + while ($token[0] == '(') { + $stack[] = $tokens; + $tokens = []; + $token = substr($token, 1); + } + if ($token[0] == '"') { + if (preg_match('%^\(*"((.|\\\\|\\")*?)" *%', $line, $matches)) { + $tokens[] = $matches[1]; + $line = substr($line, strlen($matches[0])); + continue; + } + } + if ($token[0] == '{') { + $endPos = strpos($token, '}'); + $chars = substr($token, 1, $endPos - 1); + if (is_numeric($chars)) { + $token = ''; + while (strlen($token) < $chars) { + $token .= $this->nextLine(); + } + $line = ''; + if (strlen($token) > $chars) { + $line = substr($token, $chars); + $token = substr($token, 0, $chars); + } else { + $line .= $this->nextLine(); + } + $tokens[] = $token; + $line = trim($line) . ' '; + continue; + } + } + if ($stack && $token[strlen($token) - 1] == ')') { + // closing braces are not separated by spaces, so we need to count them + $braces = strlen($token); + $token = rtrim($token, ')'); + // only count braces if more than one + $braces -= strlen($token) + 1; + // only add if token had more than just closing braces + if (rtrim($token) != '') { + $tokens[] = rtrim($token); + } + $token = $tokens; + $tokens = array_pop($stack); + // special handline if more than one closing brace + while ($braces-- > 0) { + $tokens[] = $token; + $token = $tokens; + $tokens = array_pop($stack); + } + } + $tokens[] = $token; + $line = substr($line, $pos + 1); + } + + // maybe the server forgot to send some closing braces + while ($stack) { + $child = $tokens; + $tokens = array_pop($stack); + $tokens[] = $child; + } + + return $tokens; + } + + /** + * Read abd decode a response "line" + * @param array|string $tokens to decode + * @param string $wantedTag targeted tag + * @param bool $dontParse if true only the unparsed line is returned in $tokens + * + * @return bool + * @throws RuntimeException + */ + public function readLine(&$tokens = [], string $wantedTag = '*', bool $dontParse = false): bool { + $line = $this->nextTaggedLine($tag); // get next tag + if (!$dontParse) { + $tokens = $this->decodeLine($line); + } else { + $tokens = $line; + } + if ($this->debug) echo "<< ".$line."\n"; + + // if tag is wanted tag we might be at the end of a multiline response + return $tag == $wantedTag; + } + + /** + * Read all lines of response until given tag is found + * @param string $tag request tag + * @param bool $dontParse if true every line is returned unparsed instead of the decoded tokens + * + * @return void|null|bool|array tokens if success, false if error, null if bad request + * @throws RuntimeException + */ + public function readResponse(string $tag, bool $dontParse = false) { + $lines = []; + $tokens = null; // define $tokens variable before first use + do { + $readAll = $this->readLine($tokens, $tag, $dontParse); + $lines[] = $tokens; + } while (!$readAll); + + if ($dontParse) { + // First two chars are still needed for the response code + $tokens = [substr($tokens, 0, 2)]; + } + + // last line has response code + if ($tokens[0] == 'OK') { + return $lines ? $lines : true; + } elseif ($tokens[0] == 'NO') { + return false; + } + + return null; + } + + /** + * Send a new request + * @param string $command + * @param array $tokens additional parameters to command, use escapeString() to prepare + * @param string|null $tag provide a tag otherwise an autogenerated is returned + * + * @throws RuntimeException + */ + public function sendRequest(string $command, array $tokens = [], string &$tag = null) { + if (!$tag) { + $this->noun++; + $tag = 'TAG' . $this->noun; + } + + $line = $tag . ' ' . $command; + + foreach ($tokens as $token) { + if (is_array($token)) { + if (fwrite($this->stream, $line . ' ' . $token[0] . "\r\n") === false) { + throw new RuntimeException('failed to write - connection closed?'); + } + if (!$this->assumedNextLine('+ ')) { + throw new RuntimeException('failed to send literal string'); + } + $line = $token[1]; + } else { + $line .= ' ' . $token; + } + } + if ($this->debug) echo ">> ".$line."\n"; + + if (fwrite($this->stream, $line . "\r\n") === false) { + throw new RuntimeException('failed to write - connection closed?'); + } + } + + /** + * Send a request and get response at once + * @param string $command + * @param array $tokens parameters as in sendRequest() + * @param bool $dontParse if true unparsed lines are returned instead of tokens + * + * @return void|null|bool|array response as in readResponse() + * @throws RuntimeException + */ + public function requestAndResponse(string $command, array $tokens = [], bool $dontParse = false) { + $this->sendRequest($command, $tokens, $tag); + + return $this->readResponse($tag, $dontParse); + } + + /** + * Escape one or more literals i.e. for sendRequest + * @param string|array $string the literal/-s + * + * @return string|array escape literals, literals with newline ar returned + * as array('{size}', 'string'); + */ + public function escapeString($string) { + if (func_num_args() < 2) { + if (strpos($string, "\n") !== false) { + return ['{' . strlen($string) . '}', $string]; + } else { + return '"' . str_replace(['\\', '"'], ['\\\\', '\\"'], $string) . '"'; + } + } + $result = []; + foreach (func_get_args() as $string) { + $result[] = $this->escapeString($string); + } + return $result; + } + + /** + * Escape a list with literals or lists + * @param array $list list with literals or lists as PHP array + * + * @return string escaped list for imap + */ + public function escapeList(array $list): string { + $result = []; + foreach ($list as $v) { + if (!is_array($v)) { + $result[] = $v; + continue; + } + $result[] = $this->escapeList($v); + } + return '(' . implode(' ', $result) . ')'; + } + + /** + * Login to a new session. + * @param string $user username + * @param string $password password + * + * @return bool|mixed + * @throws AuthFailedException + */ + public function login(string $user, string $password): bool { + try { + $response = $this->requestAndResponse('LOGIN', $this->escapeString($user, $password), true); + return $response !== null && $response !== false; + } catch (RuntimeException $e) { + throw new AuthFailedException("failed to authenticate", 0, $e); + } + } + + /** + * Authenticate your current IMAP session. + * @param string $user username + * @param string $token access token + * + * @return bool + * @throws AuthFailedException + */ + public function authenticate(string $user, string $token): bool { + try { + $authenticateParams = ['XOAUTH2', base64_encode("user=$user\1auth=Bearer $token\1\1")]; + $this->sendRequest('AUTHENTICATE', $authenticateParams); + + while (true) { + $response = ""; + $is_plus = $this->readLine($response, '+', true); + if ($is_plus) { + // try to log the challenge somewhere where it can be found + error_log("got an extra server challenge: $response"); + // respond with an empty response. + $this->sendRequest(''); + } else { + if (preg_match('/^NO /i', $response) || + preg_match('/^BAD /i', $response)) { + error_log("got failure response: $response"); + return false; + } else if (preg_match("/^OK /i", $response)) { + return true; + } + } + } + } catch (RuntimeException $e) { + throw new AuthFailedException("failed to authenticate", 0, $e); + } + } + + /** + * Logout of imap server + * + * @return bool success + */ + public function logout(): bool { + $result = false; + if ($this->stream) { + try { + $result = $this->requestAndResponse('LOGOUT', [], true); + } catch (Exception $e) {} + fclose($this->stream); + $this->stream = null; + $this->uid_cache = null; + } + + return $result !== false; + } + + /** + * Check if the current session is connected + * + * @return bool + */ + public function connected(): bool { + return (boolean) $this->stream; + } + + /** + * Get an array of available capabilities + * + * @return array list of capabilities + * @throws RuntimeException + */ + public function getCapabilities(): array { + $response = $this->requestAndResponse('CAPABILITY'); + + if (!$response) return []; + + $capabilities = []; + foreach ($response as $line) { + $capabilities = array_merge($capabilities, $line); + } + return $capabilities; + } + + /** + * Examine and select have the same response. + * @param string $command can be 'EXAMINE' or 'SELECT' + * @param string $folder target folder + * + * @return bool|array + * @throws RuntimeException + */ + public function examineOrSelect(string $command = 'EXAMINE', string $folder = 'INBOX') { + $this->sendRequest($command, [$this->escapeString($folder)], $tag); + + $result = []; + $tokens = null; // define $tokens variable before first use + while (!$this->readLine($tokens, $tag)) { + if ($tokens[0] == 'FLAGS') { + array_shift($tokens); + $result['flags'] = $tokens; + continue; + } + switch ($tokens[1]) { + case 'EXISTS': + case 'RECENT': + $result[strtolower($tokens[1])] = $tokens[0]; + break; + case '[UIDVALIDITY': + $result['uidvalidity'] = (int)$tokens[2]; + break; + case '[UIDNEXT': + $result['uidnext'] = (int)$tokens[2]; + break; + default: + // ignore + break; + } + } + + if ($tokens[0] != 'OK') { + return false; + } + return $result; + } + + /** + * Change the current folder + * @param string $folder change to this folder + * + * @return bool|array see examineOrselect() + * @throws RuntimeException + */ + public function selectFolder(string $folder = 'INBOX') { + $this->uid_cache = null; + + return $this->examineOrSelect('SELECT', $folder); + } + + /** + * Examine a given folder + * @param string $folder examine this folder + * + * @return bool|array see examineOrselect() + * @throws RuntimeException + */ + public function examineFolder(string $folder = 'INBOX') { + return $this->examineOrSelect('EXAMINE', $folder); + } + + /** + * Fetch one or more items of one or more messages + * @param string|array $items items to fetch [RFC822.HEADER, FLAGS, RFC822.TEXT, etc] + * @param int|array $from message for items or start message if $to !== null + * @param int|null $to if null only one message ($from) is fetched, else it's the + * last message, INF means last message available + * @param int|string $uid set to IMAP::ST_UID or any string representing the UID - set to IMAP::ST_MSGN to use + * message numbers instead. + * + * @return string|array if only one item of one message is fetched it's returned as string + * if items of one message are fetched it's returned as (name => value) + * if one items of messages are fetched it's returned as (msgno => value) + * if items of messages are fetched it's returned as (msgno => (name => value)) + * @throws RuntimeException + */ + public function fetch($items, $from, $to = null, $uid = IMAP::ST_UID) { + if (is_array($from)) { + $set = implode(',', $from); + } elseif ($to === null) { + $set = (int)$from; + } elseif ($to === INF) { + $set = (int)$from . ':*'; + } else { + $set = (int)$from . ':' . (int)$to; + } + + $items = (array)$items; + $itemList = $this->escapeList($items); + + $this->sendRequest($this->buildUIDCommand("FETCH", $uid), [$set, $itemList], $tag); + $result = []; + $tokens = null; // define $tokens variable before first use + while (!$this->readLine($tokens, $tag)) { + // ignore other responses + if ($tokens[1] != 'FETCH') { + continue; + } + + // find array key of UID value; try the last elements, or search for it + if ($uid) { + $count = count($tokens[2]); + if ($tokens[2][$count - 2] == 'UID') { + $uidKey = $count - 1; + } else if ($tokens[2][0] == 'UID') { + $uidKey = 1; + } else { + $uidKey = array_search('UID', $tokens[2]) + 1; + } + } + + // ignore other messages + if ($to === null && !is_array($from) && ($uid ? $tokens[2][$uidKey] != $from : $tokens[0] != $from)) { + continue; + } + $data = ""; + + // if we only want one item we return that one directly + if (count($items) == 1) { + if ($tokens[2][0] == $items[0]) { + $data = $tokens[2][1]; + } elseif ($uid && $tokens[2][2] == $items[0]) { + $data = $tokens[2][3]; + } else { + // maybe the server send an other field we didn't wanted + $count = count($tokens[2]); + // we start with 2, because 0 was already checked + for ($i = 2; $i < $count; $i += 2) { + if ($tokens[2][$i] != $items[0]) { + continue; + } + $data = $tokens[2][$i + 1]; + break; + } + } + } else { + $data = []; + while (key($tokens[2]) !== null) { + $data[current($tokens[2])] = next($tokens[2]); + next($tokens[2]); + } + } + + // if we want only one message we can ignore everything else and just return + if ($to === null && !is_array($from) && ($uid ? $tokens[2][$uidKey] == $from : $tokens[0] == $from)) { + // we still need to read all lines + while (!$this->readLine($tokens, $tag)) + + return $data; + } + if ($uid) { + $result[$tokens[2][$uidKey]] = $data; + }else{ + $result[$tokens[0]] = $data; + } + } + + if ($to === null && !is_array($from)) { + throw new RuntimeException('the single id was not found in response'); + } + + return $result; + } + + /** + * Fetch message headers + * @param array|int $uids + * @param string $rfc + * @param int|string $uid set to IMAP::ST_UID or any string representing the UID - set to IMAP::ST_MSGN to use + * message numbers instead. + * + * @return array + * @throws RuntimeException + */ + public function content($uids, string $rfc = "RFC822", $uid = IMAP::ST_UID): array { + return $this->fetch(["$rfc.TEXT"], $uids, null, $uid); + } + + /** + * Fetch message headers + * @param array|int $uids + * @param string $rfc + * @param int|string $uid set to IMAP::ST_UID or any string representing the UID - set to IMAP::ST_MSGN to use + * message numbers instead. + * + * @return array + * @throws RuntimeException + */ + public function headers($uids, string $rfc = "RFC822", $uid = IMAP::ST_UID): array{ + return $this->fetch(["$rfc.HEADER"], $uids, null, $uid); + } + + /** + * Fetch message flags + * @param array|int $uids + * @param int|string $uid set to IMAP::ST_UID or any string representing the UID - set to IMAP::ST_MSGN to use + * message numbers instead. + * + * @return array + * @throws RuntimeException + */ + public function flags($uids, $uid = IMAP::ST_UID): array { + return $this->fetch(["FLAGS"], $uids, null, $uid); + } + + /** + * Get uid for a given id + * @param int|null $id message number + * + * @return array|string message number for given message or all messages as array + * @throws MessageNotFoundException + */ + public function getUid($id = null) { + $uids = []; + + if ($this->enable_uid_cache && $this->uid_cache) { + $uids = $this->uid_cache; + } else { + try { + $uids = $this->fetch('UID', 1, INF); + $this->setUidCache($uids); // set cache for this folder + } catch (RuntimeException $e) {} + } + + if ($id == null) { + return $uids; + } + + foreach ($uids as $k => $v) { + if ($k == $id) { + return $v; + } + } + + // clear uid cache and run method again + if ($this->enable_uid_cache && $this->uid_cache) { + $this->setUidCache(null); + return $this->getUid($id); + } + + throw new MessageNotFoundException('unique id not found'); + } + + /** + * Get a message number for a uid + * @param string $id uid + * + * @return int message number + * @throws MessageNotFoundException + */ + public function getMessageNumber(string $id): int { + $ids = $this->getUid(); + foreach ($ids as $k => $v) { + if ($v == $id) { + return $k; + } + } + + throw new MessageNotFoundException('message number not found'); + } + + /** + * Get a list of available folders + * @param string $reference mailbox reference for list + * @param string $folder mailbox name match with wildcards + * + * @return array folders that matched $folder as array(name => array('delimiter' => .., 'flags' => ..)) + * @throws RuntimeException + */ + public function folders(string $reference = '', string $folder = '*'): array { + $result = []; + $list = $this->requestAndResponse('LIST', $this->escapeString($reference, $folder)); + if (!$list || $list === true) { + return $result; + } + + foreach ($list as $item) { + if (count($item) != 4 || $item[0] != 'LIST') { + continue; + } + $result[$item[3]] = ['delimiter' => $item[2], 'flags' => $item[1]]; + } + + return $result; + } + + /** + * Manage flags + * @param array $flags flags to set, add or remove - see $mode + * @param int $from message for items or start message if $to !== null + * @param int|null $to if null only one message ($from) is fetched, else it's the + * last message, INF means last message available + * @param string|null $mode '+' to add flags, '-' to remove flags, everything else sets the flags as given + * @param bool $silent if false the return values are the new flags for the wanted messages + * @param int|string $uid set to IMAP::ST_UID or any string representing the UID - set to IMAP::ST_MSGN to use + * message numbers instead. + * @param null|string $item command used to store a flag + * + * @return bool|array new flags if $silent is false, else true or false depending on success + * @throws RuntimeException + */ + public function store(array $flags, int $from, $to = null, $mode = null, bool $silent = true, $uid = IMAP::ST_UID, $item = null) { + $flags = $this->escapeList($flags); + $set = $this->buildSet($from, $to); + + $command = $this->buildUIDCommand("STORE", $uid); + $item = ($mode == '-' ? "-" : "+").($item === null ? "FLAGS" : $item).($silent ? '.SILENT' : ""); + + $response = $this->requestAndResponse($command, [$set, $item, $flags], $silent); + + if ($silent) { + return (bool)$response; + } + + $result = []; + foreach ($response as $token) { + if ($token[1] != 'FETCH' || $token[2][0] != 'FLAGS') { + continue; + } + $result[$token[0]] = $token[2][1]; + } + + return $result; + } + + /** + * Append a new message to given folder + * @param string $folder name of target folder + * @param string $message full message content + * @param array|null $flags flags for new message + * @param string $date date for new message + * + * @return bool success + * @throws RuntimeException + */ + public function appendMessage(string $folder, string $message, $flags = null, $date = null): bool { + $tokens = []; + $tokens[] = $this->escapeString($folder); + if ($flags !== null) { + $tokens[] = $this->escapeList($flags); + } + if ($date !== null) { + $tokens[] = $this->escapeString($date); + } + $tokens[] = $this->escapeString($message); + + return $this->requestAndResponse('APPEND', $tokens, true); + } + + /** + * Copy a message set from current folder to an other folder + * @param string $folder destination folder + * @param $from + * @param int|null $to if null only one message ($from) is fetched, else it's the + * last message, INF means last message available + * @param int|string $uid set to IMAP::ST_UID or any string representing the UID - set to IMAP::ST_MSGN to use + * message numbers instead. + * + * @return bool success + * @throws RuntimeException + */ + public function copyMessage(string $folder, $from, $to = null, $uid = IMAP::ST_UID): bool { + $set = $this->buildSet($from, $to); + $command = $this->buildUIDCommand("COPY", $uid); + return $this->requestAndResponse($command, [$set, $this->escapeString($folder)], true); + } + + /** + * Copy multiple messages to the target folder + * + * @param array $messages List of message identifiers + * @param string $folder Destination folder + * @param int|string $uid set to IMAP::ST_UID or any string representing the UID - set to IMAP::ST_MSGN to use + * message numbers instead. + * @return array|bool Tokens if operation successful, false if an error occurred + * + * @throws RuntimeException + */ + public function copyManyMessages(array $messages, string $folder, $uid = IMAP::ST_UID) { + $command = $this->buildUIDCommand("COPY", $uid); + + $set = implode(',', $messages); + $tokens = [$set, $this->escapeString($folder)]; + + return $this->requestAndResponse($command, $tokens, true); + } + + /** + * Move a message set from current folder to an other folder + * @param string $folder destination folder + * @param $from + * @param int|null $to if null only one message ($from) is fetched, else it's the + * last message, INF means last message available + * @param int|string $uid set to IMAP::ST_UID or any string representing the UID - set to IMAP::ST_MSGN to use + * message numbers instead. + * + * @return bool success + * @throws RuntimeException + */ + public function moveMessage(string $folder, $from, $to = null, $uid = IMAP::ST_UID): bool { + $set = $this->buildSet($from, $to); + $command = $this->buildUIDCommand("MOVE", $uid); + + return $this->requestAndResponse($command, [$set, $this->escapeString($folder)], true); + } + + /** + * Move multiple messages to the target folder + * @param array $messages List of message identifiers + * @param string $folder Destination folder + * @param int|string $uid set to IMAP::ST_UID or any string representing the UID - set to IMAP::ST_MSGN to use + * message numbers instead. + * + * @return array|bool Tokens if operation successful, false if an error occurred + * @throws RuntimeException + */ + public function moveManyMessages(array $messages, string $folder, $uid = IMAP::ST_UID) { + $command = $this->buildUIDCommand("MOVE", $uid); + + $set = implode(',', $messages); + $tokens = [$set, $this->escapeString($folder)]; + + return $this->requestAndResponse($command, $tokens, true); + } + + /** + * Exchange identification information + * Ref.: https://datatracker.ietf.org/doc/html/rfc2971 + * + * @param null $ids + * @return array|bool|void|null + * + * @throws RuntimeException + */ + public function ID($ids = null) { + $token = "NIL"; + if (is_array($ids) && !empty($ids)) { + $token = "("; + foreach ($ids as $id) { + $token .= '"'.$id.'" '; + } + $token = rtrim($token).")"; + } + + return $this->requestAndResponse("ID", [$token], true); + } + + /** + * Create a new folder (and parent folders if needed) + * @param string $folder folder name + * + * @return bool success + * @throws RuntimeException + */ + public function createFolder(string $folder): bool { + return $this->requestAndResponse('CREATE', [$this->escapeString($folder)], true); + } + + /** + * Rename an existing folder + * @param string $old old name + * @param string $new new name + * + * @return bool success + * @throws RuntimeException + */ + public function renameFolder(string $old, string $new): bool { + return $this->requestAndResponse('RENAME', $this->escapeString($old, $new), true); + } + + /** + * Delete a folder + * @param string $folder folder name + * + * @return bool success + * @throws RuntimeException + */ + public function deleteFolder(string $folder): bool { + return $this->requestAndResponse('DELETE', [$this->escapeString($folder)], true); + } + + /** + * Subscribe to a folder + * @param string $folder folder name + * + * @return bool success + * @throws RuntimeException + */ + public function subscribeFolder(string $folder): bool { + return $this->requestAndResponse('SUBSCRIBE', [$this->escapeString($folder)], true); + } + + /** + * Unsubscribe from a folder + * @param string $folder folder name + * + * @return bool success + * @throws RuntimeException + */ + public function unsubscribeFolder(string $folder): bool { + return $this->requestAndResponse('UNSUBSCRIBE', [$this->escapeString($folder)], true); + } + + /** + * Apply session saved changes to the server + * + * @return bool success + * @throws RuntimeException + */ + public function expunge(): bool { + return $this->requestAndResponse('EXPUNGE'); + } + + /** + * Send noop command + * + * @return bool success + * @throws RuntimeException + */ + public function noop(): bool { + return $this->requestAndResponse('NOOP'); + } + + /** + * Retrieve the quota level settings, and usage statics per mailbox + * @param $username + * + * @return array + * @throws RuntimeException + */ + public function getQuota($username): array { + return $this->requestAndResponse("GETQUOTA", ['"#user/'.$username.'"']); + } + + /** + * Retrieve the quota settings per user + * @param string $quota_root + * + * @return array + * @throws RuntimeException + */ + public function getQuotaRoot(string $quota_root = 'INBOX'): array { + return $this->requestAndResponse("QUOTA", [$quota_root]); + } + + /** + * Send idle command + * + * @throws RuntimeException + */ + public function idle() { + $this->sendRequest("IDLE"); + if (!$this->assumedNextLine('+ ')) { + throw new RuntimeException('idle failed'); + } + } + + /** + * Send done command + * @throws RuntimeException + */ + public function done(): bool { + if (fwrite($this->stream, "DONE\r\n") === false) { + throw new RuntimeException('failed to write - connection closed?'); + } + return true; + } + + /** + * Search for matching messages + * @param array $params + * @param int|string $uid set to IMAP::ST_UID or any string representing the UID - set to IMAP::ST_MSGN to use + * message numbers instead. + * + * @return array message ids + * @throws RuntimeException + */ + public function search(array $params, $uid = IMAP::ST_UID): array { + $command = $this->buildUIDCommand("SEARCH", $uid); + $response = $this->requestAndResponse($command, $params); + if (!$response) { + return $response; + } + + foreach ($response as $ids) { + if ($ids[0] == 'SEARCH') { + array_shift($ids); + return $ids; + } + } + return []; + } + + /** + * Get a message overview + * @param string $sequence + * @param int|string $uid set to IMAP::ST_UID or any string representing the UID - set to IMAP::ST_MSGN to use + * message numbers instead. + * + * @return array + * @throws RuntimeException + * @throws MessageNotFoundException + * @throws InvalidMessageDateException + */ + public function overview(string $sequence, $uid = IMAP::ST_UID): array { + $result = []; + list($from, $to) = explode(":", $sequence); + + $uids = $this->getUid(); + $ids = []; + foreach ($uids as $msgn => $v) { + $id = $uid ? $v : $msgn; + if ( ($to >= $id && $from <= $id) || ($to === "*" && $from <= $id) ){ + $ids[] = $id; + } + } + $headers = $this->headers($ids, "RFC822", $uid); + foreach ($headers as $id => $raw_header) { + $result[$id] = (new Header($raw_header, false))->getAttributes(); + } + return $result; + } + + /** + * Enable the debug mode + */ + public function enableDebug(){ + $this->debug = true; + } + + /** + * Disable the debug mode + */ + public function disableDebug(){ + $this->debug = false; + } + + /** + * Build a valid UID number set + * @param $from + * @param null $to + * + * @return int|string + */ + public function buildSet($from, $to = null) { + $set = (int)$from; + if ($to !== null) { + $set .= ':' . ($to == INF ? '*' : (int)$to); + } + return $set; + } +} diff --git a/htdocs/includes/Webklex/php-imap/src/Connection/Protocols/LegacyProtocol.php b/htdocs/includes/Webklex/php-imap/src/Connection/Protocols/LegacyProtocol.php new file mode 100644 index 00000000000..df960e0608b --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/Connection/Protocols/LegacyProtocol.php @@ -0,0 +1,635 @@ +setCertValidation($cert_validation); + $this->encryption = $encryption; + } + + /** + * Public destructor + */ + public function __destruct() { + $this->logout(); + } + + /** + * Save the information for a nw connection + * @param string $host + * @param null $port + */ + public function connect(string $host, $port = null) { + if ($this->encryption) { + $encryption = strtolower($this->encryption); + if ($encryption == "ssl") { + $port = $port === null ? 993 : $port; + } + } + $port = $port === null ? 143 : $port; + $this->host = $host; + $this->port = $port; + } + + /** + * Login to a new session. + * @param string $user username + * @param string $password password + * + * @return bool + * @throws AuthFailedException + * @throws RuntimeException + */ + public function login(string $user, string $password): bool { + try { + $this->stream = \imap_open( + $this->getAddress(), + $user, + $password, + 0, + $attempts = 3, + ClientManager::get('options.open') + ); + } catch (\ErrorException $e) { + $errors = \imap_errors(); + $message = $e->getMessage().'. '.implode("; ", (is_array($errors) ? $errors : array())); + throw new AuthFailedException($message); + } + + if(!$this->stream) { + $errors = \imap_errors(); + $message = implode("; ", (is_array($errors) ? $errors : array())); + throw new AuthFailedException($message); + } + + $errors = \imap_errors(); + if(is_array($errors)) { + $status = $this->examineFolder(); + if($status['exists'] !== 0) { + $message = implode("; ", (is_array($errors) ? $errors : array())); + throw new RuntimeException($message); + } + } + + return $this->stream !== false; + } + + /** + * Authenticate your current session. + * @param string $user username + * @param string $token access token + * + * @return bool|resource + * @throws AuthFailedException|RuntimeException + */ + public function authenticate(string $user, string $token): bool { + return $this->login($user, $token); + } + + /** + * Get full address of mailbox. + * + * @return string + */ + protected function getAddress(): string { + $address = "{".$this->host.":".$this->port."/".$this->protocol; + if (!$this->cert_validation) { + $address .= '/novalidate-cert'; + } + if (in_array($this->encryption,['tls', 'notls', 'ssl'])) { + $address .= '/'.$this->encryption; + } elseif ($this->encryption === "starttls") { + $address .= '/tls'; + } + + $address .= '}'; + + return $address; + } + + /** + * Logout of the current session + * + * @return bool success + */ + public function logout(): bool { + if ($this->stream) { + $result = \imap_close($this->stream, IMAP::CL_EXPUNGE); + $this->stream = false; + $this->uid_cache = null; + return $result; + } + return false; + } + + /** + * Check if the current session is connected + * + * @return bool + */ + public function connected(): bool { + return boolval($this->stream); + } + + /** + * Get an array of available capabilities + * + * @throws MethodNotSupportedException + */ + public function getCapabilities(): array { + throw new MethodNotSupportedException(); + } + + /** + * Change the current folder + * @param string $folder change to this folder + * + * @return bool|array see examineOrselect() + * @throws RuntimeException + */ + public function selectFolder(string $folder = 'INBOX') { + \imap_reopen($this->stream, $folder, IMAP::OP_READONLY, 3); + $this->uid_cache = null; + return $this->examineFolder($folder); + } + + /** + * Examine a given folder + * @param string $folder examine this folder + * + * @return bool|array + * @throws RuntimeException + */ + public function examineFolder(string $folder = 'INBOX') { + if (strpos($folder, ".") === 0) { + throw new RuntimeException("Segmentation fault prevented. Folders starts with an illegal char '.'."); + } + $folder = $this->getAddress().$folder; + $status = \imap_status($this->stream, $folder, IMAP::SA_ALL); + return [ + "flags" => [], + "exists" => $status->messages, + "recent" => $status->recent, + "unseen" => $status->unseen, + "uidnext" => $status->uidnext, + ]; + } + + /** + * Fetch message content + * @param array|int $uids + * @param string $rfc + * @param int $uid set to IMAP::ST_UID if you pass message unique identifiers instead of numbers. + * + * @return array + */ + public function content($uids, string $rfc = "RFC822", $uid = IMAP::ST_UID): array { + $result = []; + $uids = is_array($uids) ? $uids : [$uids]; + foreach ($uids as $id) { + $result[$id] = \imap_fetchbody($this->stream, $id, "", $uid ? IMAP::ST_UID : IMAP::NIL); + } + return $result; + } + + /** + * Fetch message headers + * @param array|int $uids + * @param string $rfc + * @param int $uid set to IMAP::ST_UID if you pass message unique identifiers instead of numbers. + * + * @return array + */ + public function headers($uids, string $rfc = "RFC822", $uid = IMAP::ST_UID): array { + $result = []; + $uids = is_array($uids) ? $uids : [$uids]; + foreach ($uids as $id) { + $result[$id] = \imap_fetchheader($this->stream, $id, $uid ? IMAP::ST_UID : IMAP::NIL); + } + return $result; + } + + /** + * Fetch message flags + * @param array|int $uids + * @param int $uid set to IMAP::ST_UID if you pass message unique identifiers instead of numbers. + * + * @return array + */ + public function flags($uids, $uid = IMAP::ST_UID): array { + $result = []; + $uids = is_array($uids) ? $uids : [$uids]; + foreach ($uids as $id) { + $raw_flags = \imap_fetch_overview($this->stream, $id, $uid ? IMAP::ST_UID : IMAP::NIL); + $flags = []; + if (is_array($raw_flags) && isset($raw_flags[0])) { + $raw_flags = (array) $raw_flags[0]; + foreach($raw_flags as $flag => $value) { + if ($value === 1 && in_array($flag, ["size", "uid", "msgno", "update"]) === false){ + $flags[] = "\\".ucfirst($flag); + } + } + } + $result[$uid] = $flags; + } + + return $result; + } + + /** + * Get uid for a given id + * @param int|null $id message number + * + * @return array|string message number for given message or all messages as array + */ + public function getUid($id = null) { + if ($id === null) { + if ($this->enable_uid_cache && $this->uid_cache) { + return $this->uid_cache; + } + + $overview = $this->overview("1:*"); + $uids = []; + foreach($overview as $set){ + $uids[$set->msgno] = $set->uid; + } + + $this->setUidCache($uids); + return $uids; + } + + return \imap_uid($this->stream, $id); + } + + /** + * Get a message number for a uid + * @param string $id uid + * + * @return int message number + */ + public function getMessageNumber(string $id): int { + return \imap_msgno($this->stream, $id); + } + + /** + * Get a message overview + * @param string $sequence uid sequence + * @param int $uid set to IMAP::ST_UID if you pass message unique identifiers instead of numbers. + * + * @return array + */ + public function overview(string $sequence, $uid = IMAP::ST_UID): array { + return \imap_fetch_overview($this->stream, $sequence,$uid ? IMAP::ST_UID : IMAP::NIL); + } + + /** + * Get a list of available folders + * @param string $reference mailbox reference for list + * @param string $folder mailbox name match with wildcards + * + * @return array folders that matched $folder as array(name => array('delimiter' => .., 'flags' => ..)) + * @throws RuntimeException + */ + public function folders(string $reference = '', string $folder = '*'): array { + $result = []; + + $items = \imap_getmailboxes($this->stream, $this->getAddress(), $reference.$folder); + if(is_array($items)){ + foreach ($items as $item) { + $name = $this->decodeFolderName($item->name); + $result[$name] = ['delimiter' => $item->delimiter, 'flags' => []]; + } + }else{ + throw new RuntimeException(\imap_last_error()); + } + + return $result; + } + + /** + * Manage flags + * @param array $flags flags to set, add or remove - see $mode + * @param int $from message for items or start message if $to !== null + * @param int|null $to if null only one message ($from) is fetched, else it's the + * last message, INF means last message available + * @param string|null $mode '+' to add flags, '-' to remove flags, everything else sets the flags as given + * @param bool $silent if false the return values are the new flags for the wanted messages + * @param int $uid set to IMAP::ST_UID if you pass message unique identifiers instead of numbers. + * @param null $item unused attribute + * + * @return bool|array new flags if $silent is false, else true or false depending on success + */ + public function store(array $flags, int $from, $to = null, $mode = null, bool $silent = true, $uid = IMAP::ST_UID, $item = null) { + $flag = trim(is_array($flags) ? implode(" ", $flags) : $flags); + + if ($mode == "+"){ + $status = \imap_setflag_full($this->stream, $from, $flag, $uid ? IMAP::ST_UID : IMAP::NIL); + }else{ + $status = \imap_clearflag_full($this->stream, $from, $flag, $uid ? IMAP::ST_UID : IMAP::NIL); + } + + if ($silent === true) { + return $status; + } + + return $this->flags($from); + } + + /** + * Append a new message to given folder + * @param string $folder name of target folder + * @param string $message full message content + * @param array|null $flags flags for new message + * @param string $date date for new message + * + * @return bool success + */ + public function appendMessage(string $folder, string $message, $flags = null, $date = null): bool { + if ($date != null) { + if ($date instanceof \Carbon\Carbon){ + $date = $date->format('d-M-Y H:i:s O'); + } + return \imap_append($this->stream, $folder, $message, $flags, $date); + } + + return \imap_append($this->stream, $folder, $message, $flags); + } + + /** + * Copy message set from current folder to other folder + * @param string $folder destination folder + * @param $from + * @param int|null $to if null only one message ($from) is fetched, else it's the + * last message, INF means last message available + * @param int $uid set to IMAP::ST_UID if you pass message unique identifiers instead of numbers. + * + * @return bool success + */ + public function copyMessage(string $folder, $from, $to = null, $uid = IMAP::ST_UID): bool { + return \imap_mail_copy($this->stream, $from, $folder, $uid ? IMAP::ST_UID : IMAP::NIL); + } + + /** + * Copy multiple messages to the target folder + * @param array $messages List of message identifiers + * @param string $folder Destination folder + * @param int $uid set to IMAP::ST_UID if you pass message unique identifiers instead of numbers. + * + * @return array|bool Tokens if operation successful, false if an error occurred + */ + public function copyManyMessages(array $messages, string $folder, $uid = IMAP::ST_UID) { + foreach($messages as $msg) { + if ($this->copyMessage($folder, $msg, null, $uid) == false) { + return false; + } + } + + return $messages; + } + + /** + * Move a message set from current folder to an other folder + * @param string $folder destination folder + * @param $from + * @param int|null $to if null only one message ($from) is fetched, else it's the + * last message, INF means last message available + * @param int $uid set to IMAP::ST_UID if you pass message unique identifiers instead of numbers. + * + * @return bool success + */ + public function moveMessage(string $folder, $from, $to = null, $uid = IMAP::ST_UID): bool { + return \imap_mail_move($this->stream, $from, $folder, $uid ? IMAP::ST_UID : IMAP::NIL); + } + + /** + * Move multiple messages to the target folder + * @param array $messages List of message identifiers + * @param string $folder Destination folder + * @param int $uid set to IMAP::ST_UID if you pass message unique identifiers instead of numbers. + * + * @return array|bool Tokens if operation successful, false if an error occurred + */ + public function moveManyMessages(array $messages, string $folder, $uid = IMAP::ST_UID) { + foreach($messages as $msg) { + if ($this->moveMessage($folder, $msg, null, $uid) == false) { + return false; + } + } + + return $messages; + } + + /** + * Exchange identification information + * Ref.: https://datatracker.ietf.org/doc/html/rfc2971 + * + * @param null $ids + * @return array|bool|void|null + * + * @throws MethodNotSupportedException + */ + public function ID($ids = null) { + throw new MethodNotSupportedException(); + } + + /** + * Create a new folder (and parent folders if needed) + * @param string $folder folder name + * + * @return bool success + */ + public function createFolder(string $folder): bool { + return \imap_createmailbox($this->stream, $folder); + } + + /** + * Rename an existing folder + * @param string $old old name + * @param string $new new name + * + * @return bool success + */ + public function renameFolder(string $old, string $new): bool { + return \imap_renamemailbox($this->stream, $old, $new); + } + + /** + * Delete a folder + * @param string $folder folder name + * + * @return bool success + */ + public function deleteFolder(string $folder): bool { + return \imap_deletemailbox($this->stream, $folder); + } + + /** + * Subscribe to a folder + * @param string $folder folder name + * + * @throws MethodNotSupportedException + */ + public function subscribeFolder(string $folder): bool { + throw new MethodNotSupportedException(); + } + + /** + * Unsubscribe from a folder + * @param string $folder folder name + * + * @throws MethodNotSupportedException + */ + public function unsubscribeFolder(string $folder): bool { + throw new MethodNotSupportedException(); + } + + /** + * Apply session saved changes to the server + * + * @return bool success + */ + public function expunge(): bool { + return \imap_expunge($this->stream); + } + + /** + * Send noop command + * + * @throws MethodNotSupportedException + */ + public function noop(): bool { + throw new MethodNotSupportedException(); + } + + /** + * Send idle command + * + * @throws MethodNotSupportedException + */ + public function idle() { + throw new MethodNotSupportedException(); + } + + /** + * Send done command + * + * @throws MethodNotSupportedException + */ + public function done() { + throw new MethodNotSupportedException(); + } + + /** + * Search for matching messages + * @param array $params + * @param int $uid set to IMAP::ST_UID if you pass message unique identifiers instead of numbers. + * + * @return array message ids + */ + public function search(array $params, $uid = IMAP::ST_UID): array { + $result = \imap_search($this->stream, $params[0], $uid ? IMAP::ST_UID : IMAP::NIL); + if ($result === false) { + return []; + } + return $result; + } + + /** + * Enable the debug mode + */ + public function enableDebug(){ + $this->debug = true; + } + + /** + * Disable the debug mode + */ + public function disableDebug(){ + $this->debug = false; + } + + /** + * Decode name. + * It converts UTF7-IMAP encoding to UTF-8. + * + * @param $name + * + * @return array|false|string|string[]|null + */ + protected function decodeFolderName($name) { + preg_match('#\{(.*)\}(.*)#', $name, $preg); + return mb_convert_encoding($preg[2], "UTF-8", "UTF7-IMAP"); + } + + /** + * @return string + */ + public function getProtocol(): string { + return $this->protocol; + } + + /** + * Retrieve the quota level settings, and usage statics per mailbox + * @param $username + * + * @return array + */ + public function getQuota($username): array { + return \imap_get_quota($this->stream, 'user.'.$username); + } + + /** + * Retrieve the quota settings per user + * @param string $quota_root + * + * @return array + */ + public function getQuotaRoot(string $quota_root = 'INBOX'): array { + return \imap_get_quotaroot($this->stream, $quota_root); + } + + /** + * @param string $protocol + * @return LegacyProtocol + */ + public function setProtocol(string $protocol): LegacyProtocol { + if (($pos = strpos($protocol, "legacy")) > 0) { + $protocol = substr($protocol, 0, ($pos + 2) * -1); + } + $this->protocol = $protocol; + return $this; + } +} diff --git a/htdocs/includes/Webklex/php-imap/src/Connection/Protocols/Protocol.php b/htdocs/includes/Webklex/php-imap/src/Connection/Protocols/Protocol.php new file mode 100644 index 00000000000..c622e9ed528 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/Connection/Protocols/Protocol.php @@ -0,0 +1,285 @@ + null, + 'request_fulluri' => false, + 'username' => null, + 'password' => null, + ]; + + /** + * Cache for uid of active folder. + * + * @var null|array + */ + protected $uid_cache = null; + + /** + * Get an available cryptographic method + * + * @return int + */ + public function getCryptoMethod() { + // Allow the best TLS version(s) we can + $cryptoMethod = STREAM_CRYPTO_METHOD_TLS_CLIENT; + + // PHP 5.6.7 dropped inclusion of TLS 1.1 and 1.2 in STREAM_CRYPTO_METHOD_TLS_CLIENT + // so add them back in manually if we can + if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) { + $cryptoMethod = STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT; + }elseif (defined('STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT')) { + $cryptoMethod = STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT; + } + + return $cryptoMethod; + } + + /** + * Enable SSL certificate validation + * + * @return $this + */ + public function enableCertValidation() { + $this->cert_validation = true; + return $this; + } + + /** + * Disable SSL certificate validation + * @return $this + */ + public function disableCertValidation() { + $this->cert_validation = false; + return $this; + } + + /** + * Set SSL certificate validation + * @var int $cert_validation + * + * @return $this + */ + public function setCertValidation($cert_validation) { + $this->cert_validation = $cert_validation; + return $this; + } + + /** + * Should we validate SSL certificate? + * + * @return bool + */ + public function getCertValidation() { + return $this->cert_validation; + } + + /** + * Set connection proxy settings + * @var array $options + * + * @return $this + */ + public function setProxy($options) { + foreach ($this->proxy as $key => $val) { + if (isset($options[$key])) { + $this->proxy[$key] = $options[$key]; + } + } + + return $this; + } + + /** + * Get the current proxy settings + * + * @return array + */ + public function getProxy() { + return $this->proxy; + } + + /** + * Prepare socket options + * @var string $transport + * + * @return array + */ + private function defaultSocketOptions($transport) { + $options = []; + if ($this->encryption != false) { + $options["ssl"] = [ + 'verify_peer_name' => $this->getCertValidation(), + 'verify_peer' => $this->getCertValidation(), + ]; + } + + if ($this->proxy["socket"] != null) { + $options[$transport]["proxy"] = $this->proxy["socket"]; + $options[$transport]["request_fulluri"] = $this->proxy["request_fulluri"]; + + if ($this->proxy["username"] != null) { + $auth = base64_encode($this->proxy["username"].':'.$this->proxy["password"]); + + $options[$transport]["header"] = [ + "Proxy-Authorization: Basic $auth" + ]; + } + } + + return $options; + } + + /** + * Create a new resource stream + * @param $transport + * @param string $host hostname or IP address of IMAP server + * @param int $port of IMAP server, default is 143 (993 for ssl) + * @param int $timeout timeout in seconds for initiating session + * + * @return resource|boolean The socket created. + * @throws ConnectionFailedException + */ + protected function createStream($transport, $host, $port, $timeout) { + $socket = "$transport://$host:$port"; + $stream = stream_socket_client($socket, $errno, $errstr, $timeout, + STREAM_CLIENT_CONNECT, + stream_context_create($this->defaultSocketOptions($transport)) + ); + + if (!$stream) { + throw new ConnectionFailedException($errstr, $errno); + } + + if (false === stream_set_timeout($stream, $timeout)) { + throw new ConnectionFailedException('Failed to set stream timeout'); + } + + return $stream; + } + + /** + * @return int + */ + public function getConnectionTimeout() { + return $this->connection_timeout; + } + + /** + * @param int $connection_timeout + * @return Protocol + */ + public function setConnectionTimeout($connection_timeout) { + if ($connection_timeout !== null) { + $this->connection_timeout = $connection_timeout; + } + return $this; + } + + /** + * Get the UID key string + * @param int|string $uid + * + * @return string + */ + public function getUIDKey($uid) { + if ($uid == IMAP::ST_UID || $uid == IMAP::FT_UID) { + return "UID"; + } + if (strlen($uid) > 0 && !is_numeric($uid)) { + return (string)$uid; + } + + return ""; + } + + public function buildUIDCommand($command, $uid) { + return trim($this->getUIDKey($uid)." ".$command); + } + + /** + * Set the uid cache of current active folder + * + * @param array|null $uids + */ + public function setUidCache($uids) { + if (is_null($uids)) { + $this->uid_cache = null; + return; + } + + $messageNumber = 1; + + $uid_cache = []; + foreach ($uids as $uid) { + $uid_cache[$messageNumber++] = $uid; + } + + $this->uid_cache = $uid_cache; + } + + public function enableUidCache() { + $this->enable_uid_cache = true; + } + + public function disableUidCache() { + $this->enable_uid_cache = false; + } +} diff --git a/htdocs/includes/Webklex/php-imap/src/Connection/Protocols/ProtocolInterface.php b/htdocs/includes/Webklex/php-imap/src/Connection/Protocols/ProtocolInterface.php new file mode 100644 index 00000000000..a512afe87c3 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/Connection/Protocols/ProtocolInterface.php @@ -0,0 +1,408 @@ + array('delim' => .., 'flags' => ..)) + * @throws RuntimeException + */ + public function folders(string $reference = '', string $folder = '*'): array; + + /** + * Set message flags + * @param array $flags flags to set, add or remove + * @param int $from message for items or start message if $to !== null + * @param int|null $to if null only one message ($from) is fetched, else it's the + * last message, INF means last message available + * @param string|null $mode '+' to add flags, '-' to remove flags, everything else sets the flags as given + * @param bool $silent if false the return values are the new flags for the wanted messages + * @param int|string $uid set to IMAP::ST_UID or any string representing the UID - set to IMAP::ST_MSGN to use + * message numbers instead. + * @param null|string $item command used to store a flag + * + * @return bool|array new flags if $silent is false, else true or false depending on success + * @throws RuntimeException + */ + public function store(array $flags, int $from, $to = null, $mode = null, bool $silent = true, $uid = IMAP::ST_UID, $item = null); + + /** + * Append a new message to given folder + * @param string $folder name of target folder + * @param string $message full message content + * @param array|null $flags flags for new message + * @param string|null $date date for new message + * + * @return bool success + * @throws RuntimeException + */ + public function appendMessage(string $folder, string $message, $flags = null, $date = null): bool; + + /** + * Copy message set from current folder to other folder + * + * @param string $folder destination folder + * @param $from + * @param int|null $to if null only one message ($from) is fetched, else it's the + * last message, INF means last message available + * @param int|string $uid set to IMAP::ST_UID or any string representing the UID - set to IMAP::ST_MSGN to use + * message numbers instead. + * + * @return bool success + * @throws RuntimeException + */ + public function copyMessage(string $folder, $from, $to = null, $uid = IMAP::ST_UID): bool; + + /** + * Copy multiple messages to the target folder + * @param array $messages List of message identifiers + * @param string $folder Destination folder + * @param int|string $uid set to IMAP::ST_UID or any string representing the UID - set to IMAP::ST_MSGN to use + * message numbers instead. + * + * @return array|bool Tokens if operation successful, false if an error occurred + * @throws RuntimeException + */ + public function copyManyMessages(array $messages, string $folder, $uid = IMAP::ST_UID); + + /** + * Move a message set from current folder to an other folder + * @param string $folder destination folder + * @param $from + * @param int|null $to if null only one message ($from) is fetched, else it's the + * last message, INF means last message available + * @param int|string $uid set to IMAP::ST_UID or any string representing the UID - set to IMAP::ST_MSGN to use + * message numbers instead. + * + * @return bool success + */ + public function moveMessage(string $folder, $from, $to = null, $uid = IMAP::ST_UID): bool; + + /** + * Move multiple messages to the target folder + * + * @param array $messages List of message identifiers + * @param string $folder Destination folder + * @param int|string $uid set to IMAP::ST_UID or any string representing the UID - set to IMAP::ST_MSGN to use + * message numbers instead. + * + * @return array|bool Tokens if operation successful, false if an error occurred + * @throws RuntimeException + */ + public function moveManyMessages(array $messages, string $folder, $uid = IMAP::ST_UID); + + /** + * Exchange identification information + * Ref.: https://datatracker.ietf.org/doc/html/rfc2971 + * + * @param null $ids + * @return array|bool|void|null + * + * @throws RuntimeException + */ + public function ID($ids = null); + + /** + * Create a new folder + * + * @param string $folder folder name + * @return bool success + * @throws RuntimeException + */ + public function createFolder(string $folder): bool; + + /** + * Rename an existing folder + * + * @param string $old old name + * @param string $new new name + * @return bool success + * @throws RuntimeException + */ + public function renameFolder(string $old, string $new): bool; + + /** + * Delete a folder + * + * @param string $folder folder name + * @return bool success + * @throws RuntimeException + */ + public function deleteFolder(string $folder): bool; + + /** + * Subscribe to a folder + * + * @param string $folder folder name + * @return bool success + * @throws RuntimeException + */ + public function subscribeFolder(string $folder): bool; + + /** + * Unsubscribe from a folder + * @param string $folder folder name + * + * @return bool success + * @throws RuntimeException + */ + public function unsubscribeFolder(string $folder): bool; + + /** + * Send idle command + * + * @throws RuntimeException + */ + public function idle(); + + /** + * Send done command + * @throws RuntimeException + */ + public function done(); + + /** + * Apply session saved changes to the server + * + * @return bool success + * @throws RuntimeException + */ + public function expunge(): bool; + + /** + * Retrieve the quota level settings, and usage statics per mailbox + * @param $username + * + * @return array + * @throws RuntimeException + */ + public function getQuota($username): array; + + /** + * Retrieve the quota settings per user + * + * @param string $quota_root + * + * @return array + * @throws ConnectionFailedException + */ + public function getQuotaRoot(string $quota_root = 'INBOX'): array; + + /** + * Send noop command + * + * @return bool success + * @throws RuntimeException + */ + public function noop(): bool; + + /** + * Do a search request + * + * @param array $params + * @param int|string $uid set to IMAP::ST_UID or any string representing the UID - set to IMAP::ST_MSGN to use + * message numbers instead. + * + * @return array message ids + * @throws RuntimeException + */ + public function search(array $params, $uid = IMAP::ST_UID): array; + + /** + * Get a message overview + * @param string $sequence uid sequence + * @param int|string $uid set to IMAP::ST_UID or any string representing the UID - set to IMAP::ST_MSGN to use + * message numbers instead. + * + * @return array + * @throws RuntimeException + * @throws MessageNotFoundException + * @throws InvalidMessageDateException + */ + public function overview(string $sequence, $uid = IMAP::ST_UID): array; + + /** + * Enable the debug mode + */ + public function enableDebug(); + + /** + * Disable the debug mode + */ + public function disableDebug(); + + /** + * Enable uid caching + */ + public function enableUidCache(); + + /** + * Disable uid caching + */ + public function disableUidCache(); + + /** + * Set the uid cache of current active folder + * + * @param array|null $uids + */ + public function setUidCache($uids); +} diff --git a/htdocs/includes/Webklex/php-imap/src/EncodingAliases.php b/htdocs/includes/Webklex/php-imap/src/EncodingAliases.php new file mode 100644 index 00000000000..9140640e168 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/EncodingAliases.php @@ -0,0 +1,482 @@ + "us-ascii", + "us-ascii" => "us-ascii", + "ansi_x3.4-1968" => "us-ascii", + "646" => "us-ascii", + "iso-8859-1" => "ISO-8859-1", + "iso-8859-2" => "ISO-8859-2", + "iso-8859-3" => "ISO-8859-3", + "iso-8859-4" => "ISO-8859-4", + "iso-8859-5" => "ISO-8859-5", + "iso-8859-6" => "ISO-8859-6", + "iso-8859-6-i" => "ISO-8859-6-I", + "iso-8859-6-e" => "ISO-8859-6-E", + "iso-8859-7" => "ISO-8859-7", + "iso-8859-8" => "ISO-8859-8", + "iso-8859-8-i" => "ISO-8859-8-I", + "iso-8859-8-e" => "ISO-8859-8-E", + "iso-8859-9" => "ISO-8859-9", + "iso-8859-10" => "ISO-8859-10", + "iso-8859-11" => "ISO-8859-11", + "iso-8859-13" => "ISO-8859-13", + "iso-8859-14" => "ISO-8859-14", + "iso-8859-15" => "ISO-8859-15", + "iso-8859-16" => "ISO-8859-16", + "iso-ir-111" => "ISO-IR-111", + "iso-2022-cn" => "ISO-2022-CN", + "iso-2022-cn-ext" => "ISO-2022-CN", + "iso-2022-kr" => "ISO-2022-KR", + "iso-2022-jp" => "ISO-2022-JP", + "utf-16be" => "UTF-16BE", + "utf-16le" => "UTF-16LE", + "utf-16" => "UTF-16", + "windows-1250" => "windows-1250", + "windows-1251" => "windows-1251", + "windows-1252" => "windows-1252", + "windows-1253" => "windows-1253", + "windows-1254" => "windows-1254", + "windows-1255" => "windows-1255", + "windows-1256" => "windows-1256", + "windows-1257" => "windows-1257", + "windows-1258" => "windows-1258", + "ibm866" => "IBM866", + "ibm850" => "IBM850", + "ibm852" => "IBM852", + "ibm855" => "IBM855", + "ibm857" => "IBM857", + "ibm862" => "IBM862", + "ibm864" => "IBM864", + "utf-8" => "UTF-8", + "utf-7" => "UTF-7", + "shift_jis" => "Shift_JIS", + "big5" => "Big5", + "euc-jp" => "EUC-JP", + "euc-kr" => "EUC-KR", + "gb2312" => "GB2312", + "gb18030" => "gb18030", + "viscii" => "VISCII", + "koi8-r" => "KOI8-R", + "koi8_r" => "KOI8-R", + "cskoi8r" => "KOI8-R", + "koi" => "KOI8-R", + "koi8" => "KOI8-R", + "koi8-u" => "KOI8-U", + "tis-620" => "TIS-620", + "t.61-8bit" => "T.61-8bit", + "hz-gb-2312" => "HZ-GB-2312", + "big5-hkscs" => "Big5-HKSCS", + "gbk" => "gbk", + "cns11643" => "x-euc-tw", + // + // Aliases for ISO-8859-1 + // + "latin1" => "ISO-8859-1", + "iso_8859-1" => "ISO-8859-1", + "iso8859-1" => "ISO-8859-1", + "iso8859-2" => "ISO-8859-2", + "iso8859-3" => "ISO-8859-3", + "iso8859-4" => "ISO-8859-4", + "iso8859-5" => "ISO-8859-5", + "iso8859-6" => "ISO-8859-6", + "iso8859-7" => "ISO-8859-7", + "iso8859-8" => "ISO-8859-8", + "iso8859-9" => "ISO-8859-9", + "iso8859-10" => "ISO-8859-10", + "iso8859-11" => "ISO-8859-11", + "iso8859-13" => "ISO-8859-13", + "iso8859-14" => "ISO-8859-14", + "iso8859-15" => "ISO-8859-15", + "iso_8859-1:1987" => "ISO-8859-1", + "iso-ir-100" => "ISO-8859-1", + "l1" => "ISO-8859-1", + "ibm819" => "ISO-8859-1", + "cp819" => "ISO-8859-1", + "csisolatin1" => "ISO-8859-1", + // + // Aliases for ISO-8859-2 + // + "latin2" => "ISO-8859-2", + "iso_8859-2" => "ISO-8859-2", + "iso_8859-2:1987" => "ISO-8859-2", + "iso-ir-101" => "ISO-8859-2", + "l2" => "ISO-8859-2", + "csisolatin2" => "ISO-8859-2", + // + // Aliases for ISO-8859-3 + // + "latin3" => "ISO-8859-3", + "iso_8859-3" => "ISO-8859-3", + "iso_8859-3:1988" => "ISO-8859-3", + "iso-ir-109" => "ISO-8859-3", + "l3" => "ISO-8859-3", + "csisolatin3" => "ISO-8859-3", + // + // Aliases for ISO-8859-4 + // + "latin4" => "ISO-8859-4", + "iso_8859-4" => "ISO-8859-4", + "iso_8859-4:1988" => "ISO-8859-4", + "iso-ir-110" => "ISO-8859-4", + "l4" => "ISO-8859-4", + "csisolatin4" => "ISO-8859-4", + // + // Aliases for ISO-8859-5 + // + "cyrillic" => "ISO-8859-5", + "iso_8859-5" => "ISO-8859-5", + "iso_8859-5:1988" => "ISO-8859-5", + "iso-ir-144" => "ISO-8859-5", + "csisolatincyrillic" => "ISO-8859-5", + // + // Aliases for ISO-8859-6 + // + "arabic" => "ISO-8859-6", + "iso_8859-6" => "ISO-8859-6", + "iso_8859-6:1987" => "ISO-8859-6", + "iso-ir-127" => "ISO-8859-6", + "ecma-114" => "ISO-8859-6", + "asmo-708" => "ISO-8859-6", + "csisolatinarabic" => "ISO-8859-6", + // + // Aliases for ISO-8859-6-I + // + "csiso88596i" => "ISO-8859-6-I", + // + // Aliases for ISO-8859-6-E", + // + "csiso88596e" => "ISO-8859-6-E", + // + // Aliases for ISO-8859-7", + // + "greek" => "ISO-8859-7", + "greek8" => "ISO-8859-7", + "sun_eu_greek" => "ISO-8859-7", + "iso_8859-7" => "ISO-8859-7", + "iso_8859-7:1987" => "ISO-8859-7", + "iso-ir-126" => "ISO-8859-7", + "elot_928" => "ISO-8859-7", + "ecma-118" => "ISO-8859-7", + "csisolatingreek" => "ISO-8859-7", + // + // Aliases for ISO-8859-8", + // + "hebrew" => "ISO-8859-8", + "iso_8859-8" => "ISO-8859-8", + "visual" => "ISO-8859-8", + "iso_8859-8:1988" => "ISO-8859-8", + "iso-ir-138" => "ISO-8859-8", + "csisolatinhebrew" => "ISO-8859-8", + // + // Aliases for ISO-8859-8-I", + // + "csiso88598i" => "ISO-8859-8-I", + "iso-8859-8i" => "ISO-8859-8-I", + "logical" => "ISO-8859-8-I", + // + // Aliases for ISO-8859-8-E", + // + "csiso88598e" => "ISO-8859-8-E", + // + // Aliases for ISO-8859-9", + // + "latin5" => "ISO-8859-9", + "iso_8859-9" => "ISO-8859-9", + "iso_8859-9:1989" => "ISO-8859-9", + "iso-ir-148" => "ISO-8859-9", + "l5" => "ISO-8859-9", + "csisolatin5" => "ISO-8859-9", + // + // Aliases for UTF-8", + // + "unicode-1-1-utf-8" => "UTF-8", + // nl_langinfo(CODESET) in HP/UX returns 'utf8' under UTF-8 locales", + "utf8" => "UTF-8", + // + // Aliases for Shift_JIS", + // + "x-sjis" => "Shift_JIS", + "shift-jis" => "Shift_JIS", + "ms_kanji" => "Shift_JIS", + "csshiftjis" => "Shift_JIS", + "windows-31j" => "Shift_JIS", + "cp932" => "Shift_JIS", + "sjis" => "Shift_JIS", + // + // Aliases for EUC_JP", + // + "cseucpkdfmtjapanese" => "EUC-JP", + "x-euc-jp" => "EUC-JP", + // + // Aliases for ISO-2022-JP", + // + "csiso2022jp" => "ISO-2022-JP", + // The following are really not aliases ISO-2022-JP, but sharing the same decoder", + "iso-2022-jp-2" => "ISO-2022-JP", + "csiso2022jp2" => "ISO-2022-JP", + // + // Aliases for Big5", + // + "csbig5" => "Big5", + "cn-big5" => "Big5", + // x-x-big5 is not really a alias for Big5, add it only for MS FrontPage", + "x-x-big5" => "Big5", + // Sun Solaris", + "zh_tw-big5" => "Big5", + // + // Aliases for EUC-KR", + // + "cseuckr" => "EUC-KR", + "ks_c_5601-1987" => "EUC-KR", + "iso-ir-149" => "EUC-KR", + "ks_c_5601-1989" => "EUC-KR", + "ksc_5601" => "EUC-KR", + "ksc5601" => "EUC-KR", + "korean" => "EUC-KR", + "csksc56011987" => "EUC-KR", + "5601" => "EUC-KR", + "windows-949" => "EUC-KR", + // + // Aliases for GB2312", + // + // The following are really not aliases GB2312, add them only for MS FrontPage", + "gb_2312-80" => "GB2312", + "iso-ir-58" => "GB2312", + "chinese" => "GB2312", + "csiso58gb231280" => "GB2312", + "csgb2312" => "GB2312", + "zh_cn.euc" => "GB2312", + // Sun Solaris", + "gb_2312" => "GB2312", + // + // Aliases for windows-125x ", + // + "x-cp1250" => "windows-1250", + "x-cp1251" => "windows-1251", + "x-cp1252" => "windows-1252", + "x-cp1253" => "windows-1253", + "x-cp1254" => "windows-1254", + "x-cp1255" => "windows-1255", + "x-cp1256" => "windows-1256", + "x-cp1257" => "windows-1257", + "x-cp1258" => "windows-1258", + // + // Aliases for windows-874 ", + // + "windows-874" => "windows-874", + "ibm874" => "windows-874", + "dos-874" => "windows-874", + // + // Aliases for macintosh", + // + "macintosh" => "macintosh", + "x-mac-roman" => "macintosh", + "mac" => "macintosh", + "csmacintosh" => "macintosh", + // + // Aliases for IBM866", + // + "cp866" => "IBM866", + "cp-866" => "IBM866", + "866" => "IBM866", + "csibm866" => "IBM866", + // + // Aliases for IBM850", + // + "cp850" => "IBM850", + "850" => "IBM850", + "csibm850" => "IBM850", + // + // Aliases for IBM852", + // + "cp852" => "IBM852", + "852" => "IBM852", + "csibm852" => "IBM852", + // + // Aliases for IBM855", + // + "cp855" => "IBM855", + "855" => "IBM855", + "csibm855" => "IBM855", + // + // Aliases for IBM857", + // + "cp857" => "IBM857", + "857" => "IBM857", + "csibm857" => "IBM857", + // + // Aliases for IBM862", + // + "cp862" => "IBM862", + "862" => "IBM862", + "csibm862" => "IBM862", + // + // Aliases for IBM864", + // + "cp864" => "IBM864", + "864" => "IBM864", + "csibm864" => "IBM864", + "ibm-864" => "IBM864", + // + // Aliases for T.61-8bit", + // + "t.61" => "T.61-8bit", + "iso-ir-103" => "T.61-8bit", + "csiso103t618bit" => "T.61-8bit", + // + // Aliases for UTF-7", + // + "x-unicode-2-0-utf-7" => "UTF-7", + "unicode-2-0-utf-7" => "UTF-7", + "unicode-1-1-utf-7" => "UTF-7", + "csunicode11utf7" => "UTF-7", + // + // Aliases for ISO-10646-UCS-2", + // + "csunicode" => "UTF-16BE", + "csunicode11" => "UTF-16BE", + "iso-10646-ucs-basic" => "UTF-16BE", + "csunicodeascii" => "UTF-16BE", + "iso-10646-unicode-latin1" => "UTF-16BE", + "csunicodelatin1" => "UTF-16BE", + "iso-10646" => "UTF-16BE", + "iso-10646-j-1" => "UTF-16BE", + // + // Aliases for ISO-8859-10", + // + "latin6" => "ISO-8859-10", + "iso-ir-157" => "ISO-8859-10", + "l6" => "ISO-8859-10", + // Currently .properties cannot handle : in key", + //iso_8859-10:1992" => "ISO-8859-10", + "csisolatin6" => "ISO-8859-10", + // + // Aliases for ISO-8859-15", + // + "iso_8859-15" => "ISO-8859-15", + "csisolatin9" => "ISO-8859-15", + "l9" => "ISO-8859-15", + // + // Aliases for ISO-IR-111", + // + "ecma-cyrillic" => "ISO-IR-111", + "csiso111ecmacyrillic" => "ISO-IR-111", + // + // Aliases for ISO-2022-KR", + // + "csiso2022kr" => "ISO-2022-KR", + // + // Aliases for VISCII", + // + "csviscii" => "VISCII", + // + // Aliases for x-euc-tw", + // + "zh_tw-euc" => "x-euc-tw", + // + // Following names appears in unix nl_langinfo(CODESET)", + // They can be compiled as platform specific if necessary", + // DONT put things here if it does not look generic enough (like hp15CN)", + // + "iso88591" => "ISO-8859-1", + "iso88592" => "ISO-8859-2", + "iso88593" => "ISO-8859-3", + "iso88594" => "ISO-8859-4", + "iso88595" => "ISO-8859-5", + "iso88596" => "ISO-8859-6", + "iso88597" => "ISO-8859-7", + "iso88598" => "ISO-8859-8", + "iso88599" => "ISO-8859-9", + "iso885910" => "ISO-8859-10", + "iso885911" => "ISO-8859-11", + "iso885912" => "ISO-8859-12", + "iso885913" => "ISO-8859-13", + "iso885914" => "ISO-8859-14", + "iso885915" => "ISO-8859-15", + "cp1250" => "windows-1250", + "cp1251" => "windows-1251", + "cp1252" => "windows-1252", + "cp1253" => "windows-1253", + "cp1254" => "windows-1254", + "cp1255" => "windows-1255", + "cp1256" => "windows-1256", + "cp1257" => "windows-1257", + "cp1258" => "windows-1258", + "x-gbk" => "gbk", + "windows-936" => "gbk", + "ansi-1251" => "windows-1251", + ]; + + /** + * Returns proper encoding mapping, if exsists. If it doesn't, return unchanged $encoding + * @param string|null $encoding + * @param string|null $fallback + * + * @return string + */ + public static function get($encoding, string $fallback = null): string { + if (isset(self::$aliases[strtolower($encoding ?? '')])) { + return self::$aliases[strtolower($encoding ?? '')]; + } + return $fallback !== null ? $fallback : $encoding; + } + +} diff --git a/htdocs/includes/Webklex/php-imap/src/Events/Event.php b/htdocs/includes/Webklex/php-imap/src/Events/Event.php new file mode 100644 index 00000000000..f9e3e8f6204 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/Events/Event.php @@ -0,0 +1,28 @@ +message = $arguments[0]; + $this->flag = $arguments[1]; + } +} diff --git a/htdocs/includes/Webklex/php-imap/src/Events/FolderDeletedEvent.php b/htdocs/includes/Webklex/php-imap/src/Events/FolderDeletedEvent.php new file mode 100644 index 00000000000..89b5083f975 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/Events/FolderDeletedEvent.php @@ -0,0 +1,22 @@ +old_folder = $folders[0]; + $this->new_folder = $folders[1]; + } +} diff --git a/htdocs/includes/Webklex/php-imap/src/Events/FolderNewEvent.php b/htdocs/includes/Webklex/php-imap/src/Events/FolderNewEvent.php new file mode 100644 index 00000000000..d16bbbd67b6 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/Events/FolderNewEvent.php @@ -0,0 +1,35 @@ +folder = $folders[0]; + } +} diff --git a/htdocs/includes/Webklex/php-imap/src/Events/MessageCopiedEvent.php b/htdocs/includes/Webklex/php-imap/src/Events/MessageCopiedEvent.php new file mode 100644 index 00000000000..a6a3a447f50 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/Events/MessageCopiedEvent.php @@ -0,0 +1,22 @@ +old_message = $messages[0]; + $this->new_message = $messages[1]; + } +} diff --git a/htdocs/includes/Webklex/php-imap/src/Events/MessageNewEvent.php b/htdocs/includes/Webklex/php-imap/src/Events/MessageNewEvent.php new file mode 100644 index 00000000000..1487e28d6bd --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/Events/MessageNewEvent.php @@ -0,0 +1,35 @@ +message = $messages[0]; + } +} diff --git a/htdocs/includes/Webklex/php-imap/src/Events/MessageRestoredEvent.php b/htdocs/includes/Webklex/php-imap/src/Events/MessageRestoredEvent.php new file mode 100644 index 00000000000..25b6520a740 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/Events/MessageRestoredEvent.php @@ -0,0 +1,22 @@ +client = $client; + + $this->events["message"] = $client->getDefaultEvents("message"); + $this->events["folder"] = $client->getDefaultEvents("folder"); + + $this->setDelimiter($delimiter); + $this->path = $folder_name; + $this->full_name = $this->decodeName($folder_name); + $this->name = $this->getSimpleName($this->delimiter, $this->full_name); + + $this->parseAttributes($attributes); + } + + /** + * Get a new search query instance + * @param string[] $extensions + * + * @return WhereQuery + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + public function query(array $extensions = []): WhereQuery { + $this->getClient()->checkConnection(); + $this->getClient()->openFolder($this->path); + $extensions = count($extensions) > 0 ? $extensions : $this->getClient()->extensions; + + return new WhereQuery($this->getClient(), $extensions); + } + + /** + * Get a new search query instance + * @param string[] $extensions + * + * @return WhereQuery + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + public function search(array $extensions = []): WhereQuery { + return $this->query($extensions); + } + + /** + * Get a new search query instance + * @param string[] $extensions + * + * @return WhereQuery + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + public function messages(array $extensions = []): WhereQuery { + return $this->query($extensions); + } + + /** + * Determine if folder has children. + * + * @return bool + */ + public function hasChildren(): bool { + return $this->has_children; + } + + /** + * Set children. + * @param FolderCollection|array $children + * + * @return self + */ + public function setChildren($children = []): Folder { + $this->children = $children; + + return $this; + } + + /** + * Decode name. + * It converts UTF7-IMAP encoding to UTF-8. + * @param $name + * + * @return array|false|string|string[]|null + */ + protected function decodeName($name) { + return mb_convert_encoding($name, "UTF-8", "UTF7-IMAP"); + } + + /** + * Get simple name (without parent folders). + * @param $delimiter + * @param $full_name + * + * @return mixed + */ + protected function getSimpleName($delimiter, $full_name) { + $arr = explode($delimiter, $full_name); + + return end($arr); + } + + /** + * Parse attributes and set it to object properties. + * @param $attributes + */ + protected function parseAttributes($attributes) { + $this->no_inferiors = in_array('\NoInferiors', $attributes); + $this->no_select = in_array('\NoSelect', $attributes); + $this->marked = in_array('\Marked', $attributes); + $this->referral = in_array('\Referral', $attributes); + $this->has_children = in_array('\HasChildren', $attributes); + } + + /** + * Move or rename the current folder + * @param string $new_name + * @param boolean $expunge + * + * @return bool + * @throws ConnectionFailedException + * @throws Exceptions\EventNotFoundException + * @throws Exceptions\FolderFetchingException + * @throws Exceptions\RuntimeException + */ + public function move(string $new_name, bool $expunge = true): bool { + $this->client->checkConnection(); + $status = $this->client->getConnection()->renameFolder($this->full_name, $new_name); + if($expunge) $this->client->expunge(); + + $folder = $this->client->getFolder($new_name); + $event = $this->getEvent("folder", "moved"); + $event::dispatch($this, $folder); + + return $status; + } + + /** + * Get a message overview + * @param string|null $sequence uid sequence + * + * @return array + * @throws ConnectionFailedException + * @throws Exceptions\InvalidMessageDateException + * @throws Exceptions\MessageNotFoundException + * @throws Exceptions\RuntimeException + */ + public function overview(string $sequence = null): array { + $this->client->openFolder($this->path); + $sequence = $sequence === null ? "1:*" : $sequence; + $uid = ClientManager::get('options.sequence', IMAP::ST_MSGN) == IMAP::ST_UID; + return $this->client->getConnection()->overview($sequence, $uid); + } + + /** + * Append a string message to the current mailbox + * @param string $message + * @param array|null $options + * @param string|null|Carbon $internal_date + * + * @return bool + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + public function appendMessage(string $message, array $options = null, $internal_date = null): bool { + /** + * Check if $internal_date is parsed. If it is null it should not be set. Otherwise the message can't be stored. + * If this parameter is set, it will set the INTERNALDATE on the appended message. The parameter should be a + * date string that conforms to the rfc2060 specifications for a date_time value or be a Carbon object. + */ + + if ($internal_date instanceof Carbon){ + $internal_date = $internal_date->format('d-M-Y H:i:s O'); + } + + return $this->client->getConnection()->appendMessage($this->full_name, $message, $options, $internal_date); + } + + /** + * Rename the current folder + * @param string $new_name + * @param boolean $expunge + * + * @return bool + * @throws ConnectionFailedException + * @throws Exceptions\EventNotFoundException + * @throws Exceptions\FolderFetchingException + * @throws Exceptions\RuntimeException + */ + public function rename(string $new_name, bool $expunge = true): bool { + return $this->move($new_name, $expunge); + } + + /** + * Delete the current folder + * @param boolean $expunge + * + * @return bool + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\RuntimeException + * @throws Exceptions\EventNotFoundException + */ + public function delete(bool $expunge = true): bool { + $status = $this->client->getConnection()->deleteFolder($this->path); + if($expunge) $this->client->expunge(); + + $event = $this->getEvent("folder", "deleted"); + $event::dispatch($this); + + return $status; + } + + /** + * Subscribe the current folder + * + * @return bool + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + public function subscribe(): bool { + $this->client->openFolder($this->path); + return $this->client->getConnection()->subscribeFolder($this->path); + } + + /** + * Unsubscribe the current folder + * + * @return bool + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + public function unsubscribe(): bool { + $this->client->openFolder($this->path); + return $this->client->getConnection()->unsubscribeFolder($this->path); + } + + /** + * Idle the current connection + * @param callable $callback + * @param integer $timeout max 1740 seconds - recommended by rfc2177 §3 + * @param boolean $auto_reconnect try to reconnect on connection close + * + * @throws ConnectionFailedException + * @throws Exceptions\InvalidMessageDateException + * @throws Exceptions\MessageContentFetchingException + * @throws Exceptions\MessageHeaderFetchingException + * @throws Exceptions\RuntimeException + * @throws Exceptions\EventNotFoundException + * @throws Exceptions\MessageFlagException + * @throws Exceptions\MessageNotFoundException + * @throws Exceptions\NotSupportedCapabilityException + */ + public function idle(callable $callback, int $timeout = 1200, bool $auto_reconnect = false) { + $this->client->getConnection()->setConnectionTimeout($timeout); + + $this->client->reconnect(); + if (!in_array("IDLE", $this->client->getConnection()->getCapabilities())) { + throw new NotSupportedCapabilityException("IMAP server does not support IDLE"); + } + $this->client->openFolder($this->path, true); + $connection = $this->client->getConnection(); + + $sequence = ClientManager::get('options.sequence', IMAP::ST_MSGN); + $connection->idle(); + + while (true) { + try { + $line = $connection->nextLine(); + if (($pos = strpos($line, "EXISTS")) !== false) { + $msgn = (int) substr($line, 2, $pos -2); + $connection->done(); + + $this->client->openFolder($this->path, true); + $message = $this->query()->getMessageByMsgn($msgn); + $message->setSequence($sequence); + $callback($message); + + $event = $this->getEvent("message", "new"); + $event::dispatch($message); + + $connection->idle(); + } + }catch (Exceptions\RuntimeException $e) { + if(strpos($e->getMessage(), "connection closed") === false) { + throw $e; + } + if ($auto_reconnect === true) { + $this->client->reconnect(); + $this->client->openFolder($this->path, true); + + $connection = $this->client->getConnection(); + $connection->idle(); + } + } + } + } + + /** + * Get folder status information + * + * @return array + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + public function getStatus(): array { + return $this->examine(); + } + + /** + * Examine the current folder + * + * @return array + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + public function examine(): array { + return $this->client->getConnection()->examineFolder($this->path); + } + + /** + * Get the current Client instance + * + * @return Client + */ + public function getClient(): Client { + return $this->client; + } + + /** + * Set the delimiter + * @param $delimiter + */ + public function setDelimiter($delimiter){ + if(in_array($delimiter, [null, '', ' ', false]) === true) { + $delimiter = ClientManager::get('options.delimiter', '/'); + } + + $this->delimiter = $delimiter; + } +} diff --git a/htdocs/includes/Webklex/php-imap/src/Header.php b/htdocs/includes/Webklex/php-imap/src/Header.php new file mode 100644 index 00000000000..d2962ef4208 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/Header.php @@ -0,0 +1,757 @@ +raw = $raw_header; + $this->config = ClientManager::get('options'); + $this->attributize = $attributize; + $this->parse(); + } + + /** + * Call dynamic attribute setter and getter methods + * @param string $method + * @param array $arguments + * + * @return Attribute|mixed + * @throws MethodNotFoundException + */ + public function __call(string $method, array $arguments) { + if (strtolower(substr($method, 0, 3)) === 'get') { + $name = preg_replace('/(.)(?=[A-Z])/u', '$1_', substr(strtolower($method), 3)); + + if (in_array($name, array_keys($this->attributes))) { + return $this->attributes[$name]; + } + + } + + throw new MethodNotFoundException("Method " . self::class . '::' . $method . '() is not supported'); + } + + /** + * Magic getter + * @param $name + * + * @return Attribute|null + */ + public function __get($name) { + return $this->get($name); + } + + /** + * Get a specific header attribute + * @param $name + * + * @return Attribute|mixed + */ + public function get($name) { + if (isset($this->attributes[$name])) { + return $this->attributes[$name]; + } + + return null; + } + + /** + * Set a specific attribute + * @param string $name + * @param array|mixed $value + * @param boolean $strict + * + * @return Attribute + */ + public function set(string $name, $value, bool $strict = false) { + if (isset($this->attributes[$name]) && $strict === false) { + if ($this->attributize) { + $this->attributes[$name]->add($value, true); + } else { + if (isset($this->attributes[$name])) { + if (is_array($this->attributes[$name]) == false) { + $this->attributes[$name] = [$this->attributes[$name], $value]; + } else { + $this->attributes[$name][] = $value; + } + } else { + $this->attributes[$name] = $value; + } + } + } elseif ($this->attributize == false) { + $this->attributes[$name] = $value; + } else { + $this->attributes[$name] = new Attribute($name, $value); + } + + return $this->attributes[$name]; + } + + /** + * Perform a regex match all on the raw header and return the first result + * @param $pattern + * + * @return mixed|null + */ + public function find($pattern) { + if (preg_match_all($pattern, $this->raw, $matches)) { + if (isset($matches[1])) { + if (count($matches[1]) > 0) { + return $matches[1][0]; + } + } + } + return null; + } + + /** + * Try to find a boundary if possible + * + * @return string|null + */ + public function getBoundary() { + $regex = $this->config["boundary"] ?? "/boundary=(.*?(?=;)|(.*))/i"; + $boundary = $this->find($regex); + + if ($boundary === null) { + return null; + } + + return $this->clearBoundaryString($boundary); + } + + /** + * Remove all unwanted chars from a given boundary + * @param string $str + * + * @return string + */ + private function clearBoundaryString(string $str): string { + return str_replace(['"', '\r', '\n', "\n", "\r", ";", "\s"], "", $str); + } + + /** + * Parse the raw headers + * + * @throws InvalidMessageDateException + */ + protected function parse() { + $header = $this->rfc822_parse_headers($this->raw); + + $this->extractAddresses($header); + + if (property_exists($header, 'subject')) { + $this->set("subject", $this->decode($header->subject)); + } + if (property_exists($header, 'references')) { + $this->set("references", $this->decode($header->references)); + } + if (property_exists($header, 'message_id')) { + $this->set("message_id", str_replace(['<', '>'], '', $header->message_id)); + } + + $this->parseDate($header); + foreach ($header as $key => $value) { + $key = trim(rtrim(strtolower($key))); + if (!isset($this->attributes[$key])) { + $this->set($key, $value); + } + } + + $this->extractHeaderExtensions(); + $this->findPriority(); + } + + /** + * Parse mail headers from a string + * @link https://php.net/manual/en/function.imap-rfc822-parse-headers.php + * @param $raw_headers + * + * @return object + */ + public function rfc822_parse_headers($raw_headers) { + $headers = []; + $imap_headers = []; + if (extension_loaded('imap') && $this->config["rfc822"]) { + $raw_imap_headers = (array)\imap_rfc822_parse_headers($this->raw); + foreach ($raw_imap_headers as $key => $values) { + $key = str_replace("-", "_", $key); + $imap_headers[$key] = $values; + } + } + $lines = explode("\r\n", str_replace("\r\n\t", ' ', $raw_headers)); + $prev_header = null; + foreach ($lines as $line) { + if (substr($line, 0, 1) === "\n") { + $line = substr($line, 1); + } + + if (substr($line, 0, 1) === "\t") { + $line = substr($line, 1); + $line = trim(rtrim($line)); + if ($prev_header !== null) { + $headers[$prev_header][] = $line; + } + } elseif (substr($line, 0, 1) === " ") { + $line = substr($line, 1); + $line = trim(rtrim($line)); + if ($prev_header !== null) { + if (!isset($headers[$prev_header])) { + $headers[$prev_header] = ""; + } + if (is_array($headers[$prev_header])) { + $headers[$prev_header][] = $line; + } else { + $headers[$prev_header] .= $line; + } + } + } else { + if (($pos = strpos($line, ":")) > 0) { + $key = trim(rtrim(strtolower(substr($line, 0, $pos)))); + $key = str_replace("-", "_", $key); + + $value = trim(rtrim(substr($line, $pos + 1))); + if (isset($headers[$key])) { + $headers[$key][] = $value; + } else { + $headers[$key] = [$value]; + } + $prev_header = $key; + } + } + } + + foreach ($headers as $key => $values) { + if (isset($imap_headers[$key])) continue; + $value = null; + switch ($key) { + case 'from': + case 'to': + case 'cc': + case 'bcc': + case 'reply_to': + case 'sender': + $value = $this->decodeAddresses($values); + $headers[$key . "address"] = implode(", ", $values); + break; + case 'subject': + $value = implode(" ", $values); + break; + default: + if (is_array($values)) { + foreach ($values as $k => $v) { + if ($v == "") { + unset($values[$k]); + } + } + $available_values = count($values); + if ($available_values === 1) { + $value = array_pop($values); + } elseif ($available_values === 2) { + $value = implode(" ", $values); + } elseif ($available_values > 2) { + $value = array_values($values); + } else { + $value = ""; + } + } + break; + } + $headers[$key] = $value; + } + + return (object)array_merge($headers, $imap_headers); + } + + /** + * Decode MIME header elements + * @link https://php.net/manual/en/function.imap-mime-header-decode.php + * @param string $text The MIME text + * + * @return array The decoded elements are returned in an array of objects, where each + * object has two properties, charset and text. + */ + public function mime_header_decode(string $text): array { + if (extension_loaded('imap')) { + return \imap_mime_header_decode($text); + } + $charset = $this->getEncoding($text); + return [(object)[ + "charset" => $charset, + "text" => $this->convertEncoding($text, $charset) + ]]; + } + + /** + * Check if a given pair of strings has ben decoded + * @param $encoded + * @param $decoded + * + * @return bool + */ + private function notDecoded($encoded, $decoded): bool { + return 0 === strpos($decoded, '=?') + && strlen($decoded) - 2 === strpos($decoded, '?=') + && false !== strpos($encoded, $decoded); + } + + /** + * Convert the encoding + * @param $str + * @param string $from + * @param string $to + * + * @return mixed|string + */ + public function convertEncoding($str, $from = "ISO-8859-2", $to = "UTF-8") { + + $from = EncodingAliases::get($from, $this->fallback_encoding); + $to = EncodingAliases::get($to, $this->fallback_encoding); + + if ($from === $to) { + return $str; + } + + // We don't need to do convertEncoding() if charset is ASCII (us-ascii): + // ASCII is a subset of UTF-8, so all ASCII files are already UTF-8 encoded + // https://stackoverflow.com/a/11303410 + // + // us-ascii is the same as ASCII: + // ASCII is the traditional name for the encoding system; the Internet Assigned Numbers Authority (IANA) + // prefers the updated name US-ASCII, which clarifies that this system was developed in the US and + // based on the typographical symbols predominantly in use there. + // https://en.wikipedia.org/wiki/ASCII + // + // convertEncoding() function basically means convertToUtf8(), so when we convert ASCII string into UTF-8 it gets broken. + if (strtolower($from) == 'us-ascii' && $to == 'UTF-8') { + return $str; + } + + try { + if (function_exists('iconv') && $from != 'UTF-7' && $to != 'UTF-7') { + return iconv($from, $to, $str); + } else { + if (!$from) { + return mb_convert_encoding($str, $to); + } + return mb_convert_encoding($str, $to, $from); + } + } catch (\Exception $e) { + if (strstr($from, '-')) { + $from = str_replace('-', '', $from); + return $this->convertEncoding($str, $from, $to); + } else { + return $str; + } + } + } + + /** + * Get the encoding of a given abject + * @param object|string $structure + * + * @return string + */ + public function getEncoding($structure): string { + if (property_exists($structure, 'parameters')) { + foreach ($structure->parameters as $parameter) { + if (strtolower($parameter->attribute) == "charset") { + return EncodingAliases::get($parameter->value, $this->fallback_encoding); + } + } + } elseif (property_exists($structure, 'charset')) { + return EncodingAliases::get($structure->charset, $this->fallback_encoding); + } elseif (is_string($structure) === true) { + return mb_detect_encoding($structure); + } + + return $this->fallback_encoding; + } + + /** + * Test if a given value is utf-8 encoded + * @param $value + * + * @return bool + */ + private function is_uft8($value): bool { + return strpos(strtolower($value), '=?utf-8?') === 0; + } + + /** + * Try to decode a specific header + * @param mixed $value + * + * @return mixed + */ + private function decode($value) { + if (is_array($value)) { + return $this->decodeArray($value); + } + $original_value = $value; + $decoder = $this->config['decoder']['message']; + + if ($value !== null) { + $is_utf8_base = $this->is_uft8($value); + + if ($decoder === 'utf-8' && extension_loaded('imap')) { + $value = \imap_utf8($value); + $is_utf8_base = $this->is_uft8($value); + if ($is_utf8_base) { + $value = mb_decode_mimeheader($value); + } + if ($this->notDecoded($original_value, $value)) { + $decoded_value = $this->mime_header_decode($value); + if (count($decoded_value) > 0) { + if (property_exists($decoded_value[0], "text")) { + $value = $decoded_value[0]->text; + } + } + } + } elseif ($decoder === 'iconv' && $is_utf8_base) { + $value = iconv_mime_decode($value); + } elseif ($is_utf8_base) { + $value = mb_decode_mimeheader($value); + } + + if ($this->is_uft8($value)) { + $value = mb_decode_mimeheader($value); + } + + if ($this->notDecoded($original_value, $value)) { + $value = $this->convertEncoding($original_value, $this->getEncoding($original_value)); + } + } + + return $value; + } + + /** + * Decode a given array + * @param array $values + * + * @return array + */ + private function decodeArray(array $values): array { + foreach ($values as $key => $value) { + $values[$key] = $this->decode($value); + } + return $values; + } + + /** + * Try to extract the priority from a given raw header string + */ + private function findPriority() { + if (($priority = $this->get("x_priority")) === null) return; + switch ((int)"$priority") { + case IMAP::MESSAGE_PRIORITY_HIGHEST; + $priority = IMAP::MESSAGE_PRIORITY_HIGHEST; + break; + case IMAP::MESSAGE_PRIORITY_HIGH; + $priority = IMAP::MESSAGE_PRIORITY_HIGH; + break; + case IMAP::MESSAGE_PRIORITY_NORMAL; + $priority = IMAP::MESSAGE_PRIORITY_NORMAL; + break; + case IMAP::MESSAGE_PRIORITY_LOW; + $priority = IMAP::MESSAGE_PRIORITY_LOW; + break; + case IMAP::MESSAGE_PRIORITY_LOWEST; + $priority = IMAP::MESSAGE_PRIORITY_LOWEST; + break; + default: + $priority = IMAP::MESSAGE_PRIORITY_UNKNOWN; + break; + } + + $this->set("priority", $priority); + } + + /** + * Extract a given part as address array from a given header + * @param $values + * + * @return array + */ + private function decodeAddresses($values): array { + $addresses = []; + + if (extension_loaded('mailparse') && $this->config["rfc822"]) { + foreach ($values as $address) { + foreach (\mailparse_rfc822_parse_addresses($address) as $parsed_address) { + if (isset($parsed_address['address'])) { + $mail_address = explode('@', $parsed_address['address']); + if (count($mail_address) == 2) { + $addresses[] = (object)[ + "personal" => $parsed_address['display'] ?? '', + "mailbox" => $mail_address[0], + "host" => $mail_address[1], + ]; + } + } + } + } + + return $addresses; + } + + foreach ($values as $address) { + foreach (preg_split('/, (?=(?:[^"]*"[^"]*")*[^"]*$)/', $address) as $split_address) { + $split_address = trim(rtrim($split_address)); + + if (strpos($split_address, ",") == strlen($split_address) - 1) { + $split_address = substr($split_address, 0, -1); + } + if (preg_match( + '/^(?:(?P.+)\s)?(?(name)<|[^\s]+?)(?(name)>|>?)$/', + $split_address, + $matches + )) { + $name = trim(rtrim($matches["name"])); + $email = trim(rtrim($matches["email"])); + list($mailbox, $host) = array_pad(explode("@", $email), 2, null); + $addresses[] = (object)[ + "personal" => $name, + "mailbox" => $mailbox, + "host" => $host, + ]; + } + } + } + + return $addresses; + } + + /** + * Extract a given part as address array from a given header + * @param object $header + */ + private function extractAddresses($header) { + foreach (['from', 'to', 'cc', 'bcc', 'reply_to', 'sender'] as $key) { + if (property_exists($header, $key)) { + $this->set($key, $this->parseAddresses($header->$key)); + } + } + } + + /** + * Parse Addresses + * @param $list + * + * @return array + */ + private function parseAddresses($list): array { + $addresses = []; + + if (is_array($list) === false) { + return $addresses; + } + + foreach ($list as $item) { + $address = (object)$item; + + if (!property_exists($address, 'mailbox')) { + $address->mailbox = false; + } + if (!property_exists($address, 'host')) { + $address->host = false; + } + if (!property_exists($address, 'personal')) { + $address->personal = false; + } else { + $personalParts = $this->mime_header_decode($address->personal); + + if (is_array($personalParts)) { + $address->personal = ''; + foreach ($personalParts as $p) { + $address->personal .= $this->convertEncoding($p->text, $this->getEncoding($p)); + } + } + + if (strpos($address->personal, "'") === 0) { + $address->personal = str_replace("'", "", $address->personal); + } + } + + $address->mail = ($address->mailbox && $address->host) ? $address->mailbox . '@' . $address->host : false; + $address->full = ($address->personal) ? $address->personal . ' <' . $address->mail . '>' : $address->mail; + + $addresses[] = new Address($address); + } + + return $addresses; + } + + /** + * Search and extract potential header extensions + */ + private function extractHeaderExtensions() { + foreach ($this->attributes as $key => $value) { + if (is_array($value)) { + $value = implode(", ", $value); + } else { + $value = (string)$value; + } + // Only parse strings and don't parse any attributes like the user-agent + if (($key == "user_agent") === false) { + if (($pos = strpos($value, ";")) !== false) { + $original = substr($value, 0, $pos); + $this->set($key, trim(rtrim($original)), true); + + // Get all potential extensions + $extensions = explode(";", substr($value, $pos + 1)); + foreach ($extensions as $extension) { + if (($pos = strpos($extension, "=")) !== false) { + $key = substr($extension, 0, $pos); + $key = trim(rtrim(strtolower($key))); + + if (isset($this->attributes[$key]) === false) { + $value = substr($extension, $pos + 1); + $value = str_replace('"', "", $value); + $value = trim(rtrim($value)); + + $this->set($key, $value); + } + } + } + } + } + } + } + + /** + * Exception handling for invalid dates + * + * Currently known invalid formats: + * ^ Datetime ^ Problem ^ Cause + * | Mon, 20 Nov 2017 20:31:31 +0800 (GMT+8:00) | Double timezone specification | A Windows feature + * | Thu, 8 Nov 2018 08:54:58 -0200 (-02) | + * | | and invalid timezone (max 6 char) | + * | 04 Jan 2018 10:12:47 UT | Missing letter "C" | Unknown + * | Thu, 31 May 2018 18:15:00 +0800 (added by) | Non-standard details added by the | Unknown + * | | mail server | + * | Sat, 31 Aug 2013 20:08:23 +0580 | Invalid timezone | PHPMailer bug https://sourceforge.net/p/phpmailer/mailman/message/6132703/ + * + * Please report any new invalid timestamps to [#45](https://github.com/Webklex/php-imap/issues) + * + * @param object $header + * + * @throws InvalidMessageDateException + */ + private function parseDate($header) { + + if (property_exists($header, 'date')) { + $date = $header->date; + + if (preg_match('/\+0580/', $date)) { + $date = str_replace('+0580', '+0530', $date); + } + + $date = trim(rtrim($date)); + try { + $parsed_date = Carbon::parse($date); + } catch (\Exception $e) { + switch (true) { + case preg_match('/([0-9]{1,2}\ [A-Z]{2,3}\ [0-9]{4}\ [0-9]{1,2}\:[0-9]{1,2}\:[0-9]{1,2}\ UT)+$/i', $date) > 0: + case preg_match('/([A-Z]{2,3}\,\ [0-9]{1,2}\ [A-Z]{2,3}\ [0-9]{4}\ [0-9]{1,2}\:[0-9]{1,2}\:[0-9]{1,2}\ UT)+$/i', $date) > 0: + $date .= 'C'; + break; + case preg_match('/([A-Z]{2,3}\,\ [0-9]{1,2}\ [A-Z]{2,3}\ [0-9]{4}\ [0-9]{1,2}\:[0-9]{1,2}\:[0-9]{1,2}\ \+[0-9]{2,4}\ \(\+[0-9]{1,2}\))+$/i', $date) > 0: + case preg_match('/([A-Z]{2,3}[\,|\ \,]\ [0-9]{1,2}\ [A-Z]{2,3}\ [0-9]{4}\ [0-9]{1,2}\:[0-9]{1,2}\:[0-9]{1,2}.*)+$/i', $date) > 0: + case preg_match('/([A-Z]{2,3}\,\ [0-9]{1,2}\ [A-Z]{2,3}\ [0-9]{4}\ [0-9]{1,2}\:[0-9]{1,2}\:[0-9]{1,2}\ [\-|\+][0-9]{4}\ \(.*)\)+$/i', $date) > 0: + case preg_match('/([A-Z]{2,3}\, \ [0-9]{1,2}\ [A-Z]{2,3}\ [0-9]{4}\ [0-9]{1,2}\:[0-9]{1,2}\:[0-9]{1,2}\ [\-|\+][0-9]{4}\ \(.*)\)+$/i', $date) > 0: + case preg_match('/([0-9]{1,2}\ [A-Z]{2,3}\ [0-9]{2,4}\ [0-9]{2}\:[0-9]{2}\:[0-9]{2}\ [A-Z]{2}\ \-[0-9]{2}\:[0-9]{2}\ \([A-Z]{2,3}\ \-[0-9]{2}:[0-9]{2}\))+$/i', $date) > 0: + $array = explode('(', $date); + $array = array_reverse($array); + $date = trim(array_pop($array)); + break; + } + try { + $parsed_date = Carbon::parse($date); + } catch (\Exception $_e) { + if (!isset($this->config["fallback_date"])) { + throw new InvalidMessageDateException("Invalid message date. ID:" . $this->get("message_id") . " Date:" . $header->date . "/" . $date, 1100, $e); + } else { + $parsed_date = Carbon::parse($this->config["fallback_date"]); + } + } + } + + $this->set("date", $parsed_date); + } + } + + /** + * Get all available attributes + * + * @return array + */ + public function getAttributes(): array { + return $this->attributes; + } + +} diff --git a/htdocs/includes/Webklex/php-imap/src/IMAP.php b/htdocs/includes/Webklex/php-imap/src/IMAP.php new file mode 100644 index 00000000000..41ae8248b61 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/IMAP.php @@ -0,0 +1,375 @@ +imap_close
+ * @link http://php.net/manual/en/imap.constants.php + */ + const CL_EXPUNGE = 32768; + + /** + * The parameter is a UID + * @link http://php.net/manual/en/imap.constants.php + */ + const FT_UID = 1; + + /** + * Do not set the \Seen flag if not already set + * @link http://php.net/manual/en/imap.constants.php + */ + const FT_PEEK = 2; + const FT_NOT = 4; + + /** + * The return string is in internal format, will not canonicalize to CRLF. + * @link http://php.net/manual/en/imap.constants.php + */ + const FT_INTERNAL = 8; + const FT_PREFETCHTEXT = 32; + + /** + * The sequence argument contains UIDs instead of sequence numbers + * @link http://php.net/manual/en/imap.constants.php + */ + const ST_UID = 1; + const ST_SILENT = 2; + const ST_MSGN = 3; + const ST_SET = 4; + + /** + * the sequence numbers contain UIDS + * @link http://php.net/manual/en/imap.constants.php + */ + const CP_UID = 1; + + /** + * Delete the messages from the current mailbox after copying + * with imap_mail_copy + * @link http://php.net/manual/en/imap.constants.php + */ + const CP_MOVE = 2; + + /** + * Return UIDs instead of sequence numbers + * @link http://php.net/manual/en/imap.constants.php + */ + const SE_UID = 1; + const SE_FREE = 2; + + /** + * Don't prefetch searched messages + * @link http://php.net/manual/en/imap.constants.php + */ + const SE_NOPREFETCH = 4; + const SO_FREE = 8; + const SO_NOSERVER = 16; + const SA_MESSAGES = 1; + const SA_RECENT = 2; + const SA_UNSEEN = 4; + const SA_UIDNEXT = 8; + const SA_UIDVALIDITY = 16; + const SA_ALL = 31; + + /** + * This mailbox has no "children" (there are no + * mailboxes below this one). + * @link http://php.net/manual/en/imap.constants.php + */ + const LATT_NOINFERIORS = 1; + + /** + * This is only a container, not a mailbox - you + * cannot open it. + * @link http://php.net/manual/en/imap.constants.php + */ + const LATT_NOSELECT = 2; + + /** + * This mailbox is marked. Only used by UW-IMAPD. + * @link http://php.net/manual/en/imap.constants.php + */ + const LATT_MARKED = 4; + + /** + * This mailbox is not marked. Only used by + * UW-IMAPD. + * @link http://php.net/manual/en/imap.constants.php + */ + const LATT_UNMARKED = 8; + const LATT_REFERRAL = 16; + const LATT_HASCHILDREN = 32; + const LATT_HASNOCHILDREN = 64; + + /** + * Sort criteria for imap_sort: + * message Date + * @link http://php.net/manual/en/imap.constants.php + */ + const SORTDATE = 0; + + /** + * Sort criteria for imap_sort: + * arrival date + * @link http://php.net/manual/en/imap.constants.php + */ + const SORTARRIVAL = 1; + + /** + * Sort criteria for imap_sort: + * mailbox in first From address + * @link http://php.net/manual/en/imap.constants.php + */ + const SORTFROM = 2; + + /** + * Sort criteria for imap_sort: + * message subject + * @link http://php.net/manual/en/imap.constants.php + */ + const SORTSUBJECT = 3; + + /** + * Sort criteria for imap_sort: + * mailbox in first To address + * @link http://php.net/manual/en/imap.constants.php + */ + const SORTTO = 4; + + /** + * Sort criteria for imap_sort: + * mailbox in first cc address + * @link http://php.net/manual/en/imap.constants.php + */ + const SORTCC = 5; + + /** + * Sort criteria for imap_sort: + * size of message in octets + * @link http://php.net/manual/en/imap.constants.php + */ + const SORTSIZE = 6; + const TYPETEXT = 0; + const TYPEMULTIPART = 1; + const TYPEMESSAGE = 2; + const TYPEAPPLICATION = 3; + const TYPEAUDIO = 4; + const TYPEIMAGE = 5; + const TYPEVIDEO = 6; + const TYPEMODEL = 7; + const TYPEOTHER = 8; + const ENC7BIT = 0; + const ENC8BIT = 1; + const ENCBINARY = 2; + const ENCBASE64 = 3; + const ENCQUOTEDPRINTABLE = 4; + const ENCOTHER = 5; + + /** + * Garbage collector, clear message cache elements. + * @link http://php.net/manual/en/imap.constants.php + */ + const IMAP_GC_ELT = 1; + + /** + * Garbage collector, clear envelopes and bodies. + * @link http://php.net/manual/en/imap.constants.php + */ + const IMAP_GC_ENV = 2; + + /** + * Garbage collector, clear texts. + * @link http://php.net/manual/en/imap.constants.php + */ + const IMAP_GC_TEXTS = 4; + +} \ No newline at end of file diff --git a/htdocs/includes/Webklex/php-imap/src/Message.php b/htdocs/includes/Webklex/php-imap/src/Message.php new file mode 100755 index 00000000000..0bfc1b34afa --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/Message.php @@ -0,0 +1,1431 @@ +boot(); + + $default_mask = $client->getDefaultMessageMask(); + if($default_mask != null) { + $this->mask = $default_mask; + } + $this->events["message"] = $client->getDefaultEvents("message"); + $this->events["flag"] = $client->getDefaultEvents("flag"); + + $this->folder_path = $client->getFolderPath(); + + $this->setSequence($sequence); + $this->setFetchOption($fetch_options); + $this->setFetchBodyOption($fetch_body); + $this->setFetchFlagsOption($fetch_flags); + + $this->client = $client; + $this->client->openFolder($this->folder_path); + + $this->setSequenceId($uid, $msglist); + + if ($this->fetch_options == IMAP::FT_PEEK) { + $this->parseFlags(); + } + + $this->parseHeader(); + + if ($this->getFetchBodyOption() === true) { + $this->parseBody(); + } + + if ($this->getFetchFlagsOption() === true && $this->fetch_options !== IMAP::FT_PEEK) { + $this->parseFlags(); + } + } + + /** + * Create a new instance without fetching the message header and providing them raw instead + * @param int $uid + * @param int|null $msglist + * @param Client $client + * @param string $raw_header + * @param string $raw_body + * @param array $raw_flags + * @param null $fetch_options + * @param null $sequence + * + * @return Message + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\EventNotFoundException + * @throws InvalidMessageDateException + * @throws MessageContentFetchingException + * @throws ReflectionException + * @throws MessageFlagException + * @throws Exceptions\RuntimeException + * @throws Exceptions\MessageNotFoundException + */ + public static function make(int $uid, $msglist, Client $client, string $raw_header, string $raw_body, array $raw_flags, $fetch_options = null, $sequence = null): Message { + $reflection = new ReflectionClass(self::class); + /** @var self $instance */ + $instance = $reflection->newInstanceWithoutConstructor(); + $instance->boot(); + + $default_mask = $client->getDefaultMessageMask(); + if($default_mask != null) { + $instance->setMask($default_mask); + } + $instance->setEvents([ + "message" => $client->getDefaultEvents("message"), + "flag" => $client->getDefaultEvents("flag"), + ]); + $instance->setFolderPath($client->getFolderPath()); + $instance->setSequence($sequence); + $instance->setFetchOption($fetch_options); + + $instance->setClient($client); + $instance->setSequenceId($uid, $msglist); + + $instance->parseRawHeader($raw_header); + $instance->parseRawFlags($raw_flags); + $instance->parseRawBody($raw_body); + $instance->peek(); + + return $instance; + } + + /** + * Boot a new instance + */ + public function boot(){ + $this->attributes = []; + + $this->config = ClientManager::get('options'); + $this->available_flags = ClientManager::get('flags'); + + $this->attachments = AttachmentCollection::make([]); + $this->flags = FlagCollection::make([]); + } + + /** + * Call dynamic attribute setter and getter methods + * @param string $method + * @param array $arguments + * + * @return mixed + * @throws MethodNotFoundException + */ + public function __call(string $method, array $arguments) { + if(strtolower(substr($method, 0, 3)) === 'get') { + $name = Str::snake(substr($method, 3)); + return $this->get($name); + }elseif (strtolower(substr($method, 0, 3)) === 'set') { + $name = Str::snake(substr($method, 3)); + + if(in_array($name, array_keys($this->attributes))) { + return $this->__set($name, array_pop($arguments)); + } + + } + + throw new MethodNotFoundException("Method ".self::class.'::'.$method.'() is not supported'); + } + + /** + * Magic setter + * @param $name + * @param $value + * + * @return mixed + */ + public function __set($name, $value) { + $this->attributes[$name] = $value; + + return $this->attributes[$name]; + } + + /** + * Magic getter + * @param $name + * + * @return Attribute|mixed|null + */ + public function __get($name) { + return $this->get($name); + } + + /** + * Get an available message or message header attribute + * @param $name + * + * @return Attribute|mixed|null + */ + public function get($name) { + if(isset($this->attributes[$name])) { + return $this->attributes[$name]; + } + + return $this->header->get($name); + } + + /** + * Check if the Message has a text body + * + * @return bool + */ + public function hasTextBody(): bool { + return isset($this->bodies['text']); + } + + /** + * Get the Message text body + * + * @return mixed + */ + public function getTextBody() { + if (!isset($this->bodies['text'])) { + return null; + } + + return $this->bodies['text']; + } + + /** + * Check if the Message has a html body + * + * @return bool + */ + public function hasHTMLBody(): bool { + return isset($this->bodies['html']); + } + + /** + * Get the Message html body + * + * @return string|null + */ + public function getHTMLBody() { + if (!isset($this->bodies['html'])) { + return null; + } + + return $this->bodies['html']; + } + + /** + * Parse all defined headers + * + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\RuntimeException + * @throws InvalidMessageDateException + * @throws MessageHeaderFetchingException + */ + private function parseHeader() { + $sequence_id = $this->getSequenceId(); + $headers = $this->client->getConnection()->headers([$sequence_id], "RFC822", $this->sequence === IMAP::ST_UID); + if (!isset($headers[$sequence_id])) { + throw new MessageHeaderFetchingException("no headers found", 0); + } + + $this->parseRawHeader($headers[$sequence_id]); + } + + /** + * @param string $raw_header + * + * @throws InvalidMessageDateException + */ + public function parseRawHeader(string $raw_header){ + $this->header = new Header($raw_header); + } + + /** + * Parse additional raw flags + * @param array $raw_flags + */ + public function parseRawFlags(array $raw_flags) { + $this->flags = FlagCollection::make([]); + + foreach($raw_flags as $flag) { + if (strpos($flag, "\\") === 0){ + $flag = substr($flag, 1); + } + $flag_key = strtolower($flag); + if ($this->available_flags === null || in_array($flag_key, $this->available_flags)) { + $this->flags->put($flag_key, $flag); + } + } + } + + /** + * Parse additional flags + * + * @return void + * @throws Exceptions\ConnectionFailedException + * @throws MessageFlagException + * @throws Exceptions\RuntimeException + */ + private function parseFlags() { + $this->client->openFolder($this->folder_path); + $this->flags = FlagCollection::make([]); + + $sequence_id = $this->getSequenceId(); + try { + $flags = $this->client->getConnection()->flags([$sequence_id], $this->sequence === IMAP::ST_UID); + } catch (Exceptions\RuntimeException $e) { + throw new MessageFlagException("flag could not be fetched", 0, $e); + } + + if (isset($flags[$sequence_id])) { + $this->parseRawFlags($flags[$sequence_id]); + } + } + + /** + * Parse the Message body + * + * @return $this + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\MessageContentFetchingException + * @throws InvalidMessageDateException + * @throws Exceptions\EventNotFoundException + * @throws MessageFlagException + * @throws Exceptions\RuntimeException + */ + public function parseBody(): Message { + $this->client->openFolder($this->folder_path); + + $sequence_id = $this->getSequenceId(); + try { + $contents = $this->client->getConnection()->content([$sequence_id], "RFC822", $this->sequence === IMAP::ST_UID); + } catch (Exceptions\RuntimeException $e) { + throw new MessageContentFetchingException("failed to fetch content", 0); + } + if (!isset($contents[$sequence_id])) { + throw new MessageContentFetchingException("no content found", 0); + } + $content = $contents[$sequence_id]; + + $body = $this->parseRawBody($content); + $this->peek(); + + return $body; + } + + /** + * Handle auto "Seen" flag handling + * + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\EventNotFoundException + * @throws MessageFlagException + * @throws Exceptions\RuntimeException + */ + public function peek(){ + if ($this->fetch_options == IMAP::FT_PEEK) { + if ($this->getFlags()->get("seen") == null) { + $this->unsetFlag("Seen"); + } + }elseif ($this->getFlags()->get("seen") != null) { + $this->setFlag("Seen"); + } + } + + /** + * Parse a given message body + * @param string $raw_body + * + * @return $this + * @throws Exceptions\ConnectionFailedException + * @throws InvalidMessageDateException + * @throws MessageContentFetchingException + * @throws Exceptions\RuntimeException + */ + public function parseRawBody(string $raw_body): Message { + $this->structure = new Structure($raw_body, $this->header); + $this->fetchStructure($this->structure); + + return $this; + } + + /** + * Fetch the Message structure + * @param Structure $structure + * + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + private function fetchStructure(Structure $structure) { + $this->client->openFolder($this->folder_path); + + foreach ($structure->parts as $part) { + $this->fetchPart($part); + } + } + + /** + * Fetch a given part + * @param Part $part + */ + private function fetchPart(Part $part) { + if ($part->isAttachment()) { + $this->fetchAttachment($part); + }else{ + $encoding = $this->getEncoding($part); + + $content = $this->decodeString($part->content, $part->encoding); + + // We don't need to do convertEncoding() if charset is ASCII (us-ascii): + // ASCII is a subset of UTF-8, so all ASCII files are already UTF-8 encoded + // https://stackoverflow.com/a/11303410 + // + // us-ascii is the same as ASCII: + // ASCII is the traditional name for the encoding system; the Internet Assigned Numbers Authority (IANA) + // prefers the updated name US-ASCII, which clarifies that this system was developed in the US and + // based on the typographical symbols predominantly in use there. + // https://en.wikipedia.org/wiki/ASCII + // + // convertEncoding() function basically means convertToUtf8(), so when we convert ASCII string into UTF-8 it gets broken. + if ($encoding != 'us-ascii') { + $content = $this->convertEncoding($content, $encoding); + } + + $subtype = strtolower($part->subtype ?? ''); + $subtype = $subtype == "plain" || $subtype == "" ? "text" : $subtype; + + if (isset($this->bodies[$subtype])) { + $this->bodies[$subtype] .= "\n".$content; + }else{ + $this->bodies[$subtype] = $content; + } + } + } + + /** + * Fetch the Message attachment + * @param Part $part + */ + protected function fetchAttachment(Part $part) { + $oAttachment = new Attachment($this, $part); + + if ($oAttachment->getName() !== null && $oAttachment->getSize() > 0) { + if ($oAttachment->getId() !== null) { + $this->attachments->put($oAttachment->getId(), $oAttachment); + } else { + $this->attachments->push($oAttachment); + } + } + } + + /** + * Fail proof setter for $fetch_option + * @param $option + * + * @return $this + */ + public function setFetchOption($option): Message { + if (is_long($option) === true) { + $this->fetch_options = $option; + } elseif (is_null($option) === true) { + $config = ClientManager::get('options.fetch', IMAP::FT_UID); + $this->fetch_options = is_long($config) ? $config : 1; + } + + return $this; + } + + /** + * Set the sequence type + * @param int|null $sequence + * + * @return $this + */ + public function setSequence($sequence): Message { + if (is_long($sequence)) { + $this->sequence = $sequence; + } elseif (is_null($sequence)) { + $config = ClientManager::get('options.sequence', IMAP::ST_MSGN); + $this->sequence = is_long($config) ? $config : IMAP::ST_MSGN; + } + + return $this; + } + + /** + * Fail proof setter for $fetch_body + * @param $option + * + * @return $this + */ + public function setFetchBodyOption($option): Message { + if (is_bool($option)) { + $this->fetch_body = $option; + } elseif (is_null($option)) { + $config = ClientManager::get('options.fetch_body', true); + $this->fetch_body = is_bool($config) ? $config : true; + } + + return $this; + } + + /** + * Fail proof setter for $fetch_flags + * @param $option + * + * @return $this + */ + public function setFetchFlagsOption($option): Message { + if (is_bool($option)) { + $this->fetch_flags = $option; + } elseif (is_null($option)) { + $config = ClientManager::get('options.fetch_flags', true); + $this->fetch_flags = is_bool($config) ? $config : true; + } + + return $this; + } + + /** + * Decode a given string + * @param $string + * @param $encoding + * + * @return string + */ + public function decodeString($string, $encoding): string { + switch ($encoding) { + case IMAP::MESSAGE_ENC_BINARY: + if (extension_loaded('imap')) { + return base64_decode(\imap_binary($string)); + } + return base64_decode($string); + case IMAP::MESSAGE_ENC_BASE64: + return base64_decode($string); + case IMAP::MESSAGE_ENC_QUOTED_PRINTABLE: + return quoted_printable_decode($string); + case IMAP::MESSAGE_ENC_8BIT: + case IMAP::MESSAGE_ENC_7BIT: + case IMAP::MESSAGE_ENC_OTHER: + default: + return $string; + } + } + + /** + * Convert the encoding + * @param $str + * @param string $from + * @param string $to + * + * @return mixed|string + */ + public function convertEncoding($str, string $from = "ISO-8859-2", string $to = "UTF-8") { + + $from = EncodingAliases::get($from); + $to = EncodingAliases::get($to); + + if ($from === $to) { + return $str; + } + + // We don't need to do convertEncoding() if charset is ASCII (us-ascii): + // ASCII is a subset of UTF-8, so all ASCII files are already UTF-8 encoded + // https://stackoverflow.com/a/11303410 + // + // us-ascii is the same as ASCII: + // ASCII is the traditional name for the encoding system; the Internet Assigned Numbers Authority (IANA) + // prefers the updated name US-ASCII, which clarifies that this system was developed in the US and + // based on the typographical symbols predominantly in use there. + // https://en.wikipedia.org/wiki/ASCII + // + // convertEncoding() function basically means convertToUtf8(), so when we convert ASCII string into UTF-8 it gets broken. + if (strtolower($from ?? '') == 'us-ascii' && $to == 'UTF-8') { + return $str; + } + + if (function_exists('iconv') && $from != 'UTF-7' && $to != 'UTF-7') { + return @iconv($from, $to.'//IGNORE', $str); + } else { + if (!$from) { + return mb_convert_encoding($str, $to); + } + return mb_convert_encoding($str, $to, $from); + } + } + + /** + * Get the encoding of a given abject + * @param string|object $structure + * + * @return string|null + */ + public function getEncoding($structure): string { + if (property_exists($structure, 'parameters')) { + foreach ($structure->parameters as $parameter) { + if (strtolower($parameter->attribute) == "charset") { + return EncodingAliases::get($parameter->value, "ISO-8859-2"); + } + } + }elseif (property_exists($structure, 'charset')){ + return EncodingAliases::get($structure->charset, "ISO-8859-2"); + }elseif (is_string($structure) === true){ + return mb_detect_encoding($structure); + } + + return 'UTF-8'; + } + + /** + * Get the messages folder + * + * @return mixed + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\FolderFetchingException + * @throws Exceptions\RuntimeException + */ + public function getFolder(){ + return $this->client->getFolderByPath($this->folder_path); + } + + /** + * Create a message thread based on the current message + * @param Folder|null $sent_folder + * @param MessageCollection|null $thread + * @param Folder|null $folder + * + * @return MessageCollection|null + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\FolderFetchingException + * @throws Exceptions\GetMessagesFailedException + * @throws Exceptions\RuntimeException + */ + public function thread(Folder $sent_folder = null, MessageCollection &$thread = null, Folder $folder = null): MessageCollection { + $thread = $thread ?: MessageCollection::make([]); + $folder = $folder ?: $this->getFolder(); + $sent_folder = $sent_folder ?: $this->client->getFolderByPath(ClientManager::get("options.common_folders.sent", "INBOX/Sent")); + + /** @var Message $message */ + foreach($thread as $message) { + if ($message->message_id->first() == $this->message_id->first()) { + return $thread; + } + } + $thread->push($this); + + $this->fetchThreadByInReplyTo($thread, $this->message_id, $folder, $folder, $sent_folder); + $this->fetchThreadByInReplyTo($thread, $this->message_id, $sent_folder, $folder, $sent_folder); + + if (is_array($this->in_reply_to)) { + foreach($this->in_reply_to as $in_reply_to) { + $this->fetchThreadByMessageId($thread, $in_reply_to, $folder, $folder, $sent_folder); + $this->fetchThreadByMessageId($thread, $in_reply_to, $sent_folder, $folder, $sent_folder); + } + } + + return $thread; + } + + /** + * Fetch a partial thread by message id + * @param MessageCollection $thread + * @param string $in_reply_to + * @param Folder $primary_folder + * @param Folder $secondary_folder + * @param Folder $sent_folder + * + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\GetMessagesFailedException + * @throws Exceptions\RuntimeException + * @throws Exceptions\FolderFetchingException + */ + protected function fetchThreadByInReplyTo(MessageCollection &$thread, string $in_reply_to, Folder $primary_folder, Folder $secondary_folder, Folder $sent_folder){ + $primary_folder->query()->inReplyTo($in_reply_to) + ->setFetchBody($this->getFetchBodyOption()) + ->leaveUnread()->get()->each(function($message) use(&$thread, $secondary_folder, $sent_folder){ + /** @var Message $message */ + $message->thread($sent_folder, $thread, $secondary_folder); + }); + } + + /** + * Fetch a partial thread by message id + * @param MessageCollection $thread + * @param string $message_id + * @param Folder $primary_folder + * @param Folder $secondary_folder + * @param Folder $sent_folder + * + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\GetMessagesFailedException + * @throws Exceptions\RuntimeException + * @throws Exceptions\FolderFetchingException + */ + protected function fetchThreadByMessageId(MessageCollection &$thread, string $message_id, Folder $primary_folder, Folder $secondary_folder, Folder $sent_folder){ + $primary_folder->query()->messageId($message_id) + ->setFetchBody($this->getFetchBodyOption()) + ->leaveUnread()->get()->each(function($message) use(&$thread, $secondary_folder, $sent_folder){ + /** @var Message $message */ + $message->thread($sent_folder, $thread, $secondary_folder); + }); + } + + /** + * Copy the current Messages to a mailbox + * @param string $folder_path + * @param boolean $expunge + * + * @return null|Message + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\FolderFetchingException + * @throws Exceptions\RuntimeException + * @throws InvalidMessageDateException + * @throws MessageContentFetchingException + * @throws MessageHeaderFetchingException + * @throws Exceptions\EventNotFoundException + * @throws MessageFlagException + * @throws Exceptions\MessageNotFoundException + */ + public function copy(string $folder_path, bool $expunge = false) { + $this->client->openFolder($folder_path); + $status = $this->client->getConnection()->examineFolder($folder_path); + + if (isset($status["uidnext"])) { + $next_uid = $status["uidnext"]; + + /** @var Folder $folder */ + $folder = $this->client->getFolderByPath($folder_path); + + $this->client->openFolder($this->folder_path); + if ($this->client->getConnection()->copyMessage($folder->path, $this->getSequenceId(), null, $this->sequence === IMAP::ST_UID) == true) { + return $this->fetchNewMail($folder, $next_uid, "copied", $expunge); + } + } + + return null; + } + + /** + * Move the current Messages to a mailbox + * @param string $folder_path + * @param boolean $expunge + * + * @return Message|null + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\FolderFetchingException + * @throws Exceptions\RuntimeException + * @throws InvalidMessageDateException + * @throws MessageContentFetchingException + * @throws MessageHeaderFetchingException + * @throws Exceptions\EventNotFoundException + * @throws MessageFlagException + * @throws Exceptions\MessageNotFoundException + */ + public function move(string $folder_path, bool $expunge = false) { + $this->client->openFolder($folder_path); + $status = $this->client->getConnection()->examineFolder($folder_path); + + if (isset($status["uidnext"])) { + $next_uid = $status["uidnext"]; + + /** @var Folder $folder */ + $folder = $this->client->getFolderByPath($folder_path); + + $this->client->openFolder($this->folder_path); + if ($this->client->getConnection()->moveMessage($folder->path, $this->getSequenceId(), null, $this->sequence === IMAP::ST_UID) == true) { + return $this->fetchNewMail($folder, $next_uid, "moved", $expunge); + } + } + + return null; + } + + /** + * Fetch a new message and fire a given event + * @param Folder $folder + * @param int $next_uid + * @param string $event + * @param boolean $expunge + * + * @return Message + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\EventNotFoundException + * @throws Exceptions\MessageNotFoundException + * @throws Exceptions\RuntimeException + * @throws InvalidMessageDateException + * @throws MessageContentFetchingException + * @throws MessageFlagException + * @throws MessageHeaderFetchingException + */ + protected function fetchNewMail(Folder $folder, int $next_uid, string $event, bool $expunge): Message { + if($expunge) $this->client->expunge(); + + $this->client->openFolder($folder->path); + + if ($this->sequence === IMAP::ST_UID) { + $sequence_id = $next_uid; + }else{ + $sequence_id = $this->client->getConnection()->getMessageNumber($next_uid); + } + + $message = $folder->query()->getMessage($sequence_id, null, $this->sequence); + $event = $this->getEvent("message", $event); + $event::dispatch($this, $message); + + return $message; + } + + /** + * Delete the current Message + * @param bool $expunge + * @param string|null $trash_path + * @param boolean $force_move + * + * @return bool + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\EventNotFoundException + * @throws Exceptions\FolderFetchingException + * @throws Exceptions\MessageNotFoundException + * @throws Exceptions\RuntimeException + * @throws InvalidMessageDateException + * @throws MessageContentFetchingException + * @throws MessageFlagException + * @throws MessageHeaderFetchingException + */ + public function delete(bool $expunge = true, string $trash_path = null, bool $force_move = false) { + $status = $this->setFlag("Deleted"); + if($force_move) { + $trash_path = $trash_path === null ? $this->config["common_folders"]["trash"]: $trash_path; + $status = $this->move($trash_path); + } + if($expunge) $this->client->expunge(); + + $event = $this->getEvent("message", "deleted"); + $event::dispatch($this); + + return $status; + } + + /** + * Restore a deleted Message + * @param boolean $expunge + * + * @return bool + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\EventNotFoundException + * @throws MessageFlagException + * @throws Exceptions\RuntimeException + */ + public function restore(bool $expunge = true): bool { + $status = $this->unsetFlag("Deleted"); + if($expunge) $this->client->expunge(); + + $event = $this->getEvent("message", "restored"); + $event::dispatch($this); + + return $status; + } + + /** + * Set a given flag + * @param string|array $flag + * + * @return bool + * @throws Exceptions\ConnectionFailedException + * @throws MessageFlagException + * @throws Exceptions\EventNotFoundException + * @throws Exceptions\RuntimeException + */ + public function setFlag($flag): bool { + $this->client->openFolder($this->folder_path); + $flag = "\\".trim(is_array($flag) ? implode(" \\", $flag) : $flag); + $sequence_id = $this->getSequenceId(); + try { + $status = $this->client->getConnection()->store([$flag], $sequence_id, $sequence_id, "+", true, $this->sequence === IMAP::ST_UID); + } catch (Exceptions\RuntimeException $e) { + throw new MessageFlagException("flag could not be set", 0, $e); + } + $this->parseFlags(); + + $event = $this->getEvent("flag", "new"); + $event::dispatch($this, $flag); + + return $status; + } + + /** + * Unset a given flag + * @param string|array $flag + * + * @return bool + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\EventNotFoundException + * @throws MessageFlagException + * @throws Exceptions\RuntimeException + */ + public function unsetFlag($flag): bool { + $this->client->openFolder($this->folder_path); + + $flag = "\\".trim(is_array($flag) ? implode(" \\", $flag) : $flag); + $sequence_id = $this->getSequenceId(); + try { + $status = $this->client->getConnection()->store([$flag], $sequence_id, $sequence_id, "-", true, $this->sequence === IMAP::ST_UID); + } catch (Exceptions\RuntimeException $e) { + throw new MessageFlagException("flag could not be removed", 0, $e); + } + $this->parseFlags(); + + $event = $this->getEvent("flag", "deleted"); + $event::dispatch($this, $flag); + + return $status; + } + + /** + * Set a given flag + * @param string|array $flag + * + * @return bool + * @throws Exceptions\ConnectionFailedException + * @throws MessageFlagException + * @throws Exceptions\EventNotFoundException + * @throws Exceptions\RuntimeException + */ + public function addFlag($flag): bool { + return $this->setFlag($flag); + } + + /** + * Unset a given flag + * @param string|array $flag + * + * @return bool + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\EventNotFoundException + * @throws MessageFlagException + * @throws Exceptions\RuntimeException + */ + public function removeFlag($flag): bool { + return $this->unsetFlag($flag); + } + + /** + * Get all message attachments. + * + * @return AttachmentCollection + */ + public function getAttachments(): AttachmentCollection { + return $this->attachments; + } + + /** + * Get all message attachments. + * + * @return AttachmentCollection + */ + public function attachments(): AttachmentCollection { + return $this->getAttachments(); + } + + /** + * Checks if there are any attachments present + * + * @return boolean + */ + public function hasAttachments(): bool { + return $this->attachments->isEmpty() === false; + } + + /** + * Get the raw body + * + * @return string + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + public function getRawBody() { + if ($this->raw_body === null) { + $this->client->openFolder($this->folder_path); + + $this->raw_body = $this->structure->raw; + } + + return $this->raw_body; + } + + /** + * Get the message header + * + * @return Header + */ + public function getHeader() { + return $this->header; + } + + /** + * Get the current client + * + * @return Client + */ + public function getClient(): Client { + return $this->client; + } + + /** + * Get the used fetch option + * + * @return integer + */ + public function getFetchOptions() { + return $this->fetch_options; + } + + /** + * Get the used fetch body option + * + * @return boolean + */ + public function getFetchBodyOption() { + return $this->fetch_body; + } + + /** + * Get the used fetch flags option + * + * @return boolean + */ + public function getFetchFlagsOption() { + return $this->fetch_flags; + } + + /** + * Get all available bodies + * + * @return array + */ + public function getBodies(): array { + return $this->bodies; + } + + /** + * Get all set flags + * + * @return FlagCollection + */ + public function getFlags(): FlagCollection { + return $this->flags; + } + + /** + * Get all set flags + * + * @return FlagCollection + */ + public function flags(): FlagCollection { + return $this->getFlags(); + } + + /** + * Get the fetched structure + * + * @return Structure|null + */ + public function getStructure(){ + return $this->structure; + } + + /** + * Check if a message matches an other by comparing basic attributes + * + * @param null|Message $message + * @return boolean + */ + public function is(Message $message = null): bool { + if (is_null($message)) { + return false; + } + + return $this->uid == $message->uid + && $this->message_id->first() == $message->message_id->first() + && $this->subject->first() == $message->subject->first() + && $this->date->toDate()->eq($message->date); + } + + /** + * Get all message attributes + * + * @return array + */ + public function getAttributes(): array { + return array_merge($this->attributes, $this->header->getAttributes()); + } + + /** + * Set the message mask + * @param $mask + * + * @return $this + */ + public function setMask($mask): Message { + if(class_exists($mask)){ + $this->mask = $mask; + } + + return $this; + } + + /** + * Get the used message mask + * + * @return string + */ + public function getMask(): string { + return $this->mask; + } + + /** + * Get a masked instance by providing a mask name + * @param string|mixed $mask + * + * @return mixed + * @throws MaskNotFoundException + */ + public function mask($mask = null){ + $mask = $mask !== null ? $mask : $this->mask; + if(class_exists($mask)){ + return new $mask($this); + } + + throw new MaskNotFoundException("Unknown mask provided: ".$mask); + } + + /** + * Get the message path aka folder path + * + * @return string + */ + public function getFolderPath(): string { + return $this->folder_path; + } + + /** + * Set the message path aka folder path + * @param $folder_path + * + * @return $this + */ + public function setFolderPath($folder_path): Message { + $this->folder_path = $folder_path; + + return $this; + } + + /** + * Set the config + * @param $config + * + * @return $this + */ + public function setConfig($config): Message { + $this->config = $config; + + return $this; + } + + /** + * Set the available flags + * @param $available_flags + * + * @return $this + */ + public function setAvailableFlags($available_flags): Message { + $this->available_flags = $available_flags; + + return $this; + } + + /** + * Set the attachment collection + * @param $attachments + * + * @return $this + */ + public function setAttachments($attachments): Message { + $this->attachments = $attachments; + + return $this; + } + + /** + * Set the flag collection + * @param $flags + * + * @return $this + */ + public function setFlags($flags): Message { + $this->flags = $flags; + + return $this; + } + + /** + * Set the client + * @param $client + * + * @return $this + * @throws Exceptions\RuntimeException + * @throws Exceptions\ConnectionFailedException + */ + public function setClient($client): Message { + $this->client = $client; + $this->client->openFolder($this->folder_path); + + return $this; + } + + /** + * Set the message number + * @param int $uid + * + * @return $this + * @throws Exceptions\MessageNotFoundException + * @throws Exceptions\ConnectionFailedException + */ + public function setUid(int $uid): Message { + $this->uid = $uid; + $this->msgn = $this->client->getConnection()->getMessageNumber($this->uid); + $this->msglist = null; + + return $this; + } + + /** + * Set the message number + * @param int $msgn + * @param int|null $msglist + * + * @return $this + * @throws Exceptions\MessageNotFoundException + * @throws Exceptions\ConnectionFailedException + */ + public function setMsgn(int $msgn, int $msglist = null): Message { + $this->msgn = $msgn; + $this->msglist = $msglist; + $this->uid = $this->client->getConnection()->getUid($this->msgn); + + return $this; + } + + /** + * Get the current sequence type + * + * @return int + */ + public function getSequence(): int { + return $this->sequence; + } + + /** + * Set the sequence type + * + * @return int + */ + public function getSequenceId(): int { + return $this->sequence === IMAP::ST_UID ? $this->uid : $this->msgn; + } + + /** + * Set the sequence id + * @param $uid + * @param int|null $msglist + * + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\MessageNotFoundException + */ + public function setSequenceId($uid, int $msglist = null){ + if ($this->getSequence() === IMAP::ST_UID) { + $this->setUid($uid); + $this->setMsglist($msglist); + }else{ + $this->setMsgn($uid, $msglist); + } + } +} diff --git a/htdocs/includes/Webklex/php-imap/src/Part.php b/htdocs/includes/Webklex/php-imap/src/Part.php new file mode 100644 index 00000000000..4f0985a6f2f --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/Part.php @@ -0,0 +1,312 @@ +raw = $raw_part; + $this->header = $header; + $this->part_number = $part_number; + $this->parse(); + } + + /** + * Parse the raw parts + * + * @throws InvalidMessageDateException + */ + protected function parse(){ + if ($this->header === null) { + $body = $this->findHeaders(); + }else{ + $body = $this->raw; + } + + $this->parseDisposition(); + $this->parseDescription(); + $this->parseEncoding(); + + $this->charset = $this->header->get("charset"); + $this->name = $this->header->get("name"); + $this->filename = $this->header->get("filename"); + + if(!empty($this->header->get("id"))) { + $this->id = $this->header->get("id"); + } else if(!empty($this->header->get("x_attachment_id"))){ + $this->id = $this->header->get("x_attachment_id"); + } else if(!empty($this->header->get("content_id"))){ + $this->id = strtr($this->header->get("content_id"), [ + '<' => '', + '>' => '' + ]); + } + + $content_types = $this->header->get("content_type"); + if(!empty($content_types)){ + $this->subtype = $this->parseSubtype($content_types); + $content_type = $content_types; + if (is_array($content_types)) { + $content_type = $content_types[0]; + } + $parts = explode(';', $content_type); + $this->content_type = trim($parts[0]); + } + + + $this->content = trim(rtrim($body)); + $this->bytes = strlen($this->content); + } + + /** + * Find all available headers and return the left over body segment + * + * @return string + * @throws InvalidMessageDateException + */ + private function findHeaders(): string { + $body = $this->raw; + while (($pos = strpos($body, "\r\n")) > 0) { + $body = substr($body, $pos + 2); + } + $headers = substr($this->raw, 0, strlen($body) * -1); + $body = substr($body, 0, -2); + + $this->header = new Header($headers); + + return (string) $body; + } + + /** + * Try to parse the subtype if any is present + * @param $content_type + * + * @return string + */ + private function parseSubtype($content_type){ + if (is_array($content_type)) { + foreach ($content_type as $part){ + if ((strpos($part, "/")) !== false){ + return $this->parseSubtype($part); + } + } + return null; + } + if (($pos = strpos($content_type, "/")) !== false){ + return substr($content_type, $pos + 1); + } + return null; + } + + /** + * Try to parse the disposition if any is present + */ + private function parseDisposition(){ + $content_disposition = $this->header->get("content_disposition"); + if($content_disposition !== null) { + $this->ifdisposition = true; + $this->disposition = (is_array($content_disposition)) ? implode(' ', $content_disposition) : $content_disposition; + } + } + + /** + * Try to parse the description if any is present + */ + private function parseDescription(){ + $content_description = $this->header->get("content_description"); + if($content_description !== null) { + $this->ifdescription = true; + $this->description = $content_description; + } + } + + /** + * Try to parse the encoding if any is present + */ + private function parseEncoding(){ + $encoding = $this->header->get("content_transfer_encoding"); + if($encoding !== null) { + switch (strtolower($encoding)) { + case "quoted-printable": + $this->encoding = IMAP::MESSAGE_ENC_QUOTED_PRINTABLE; + break; + case "base64": + $this->encoding = IMAP::MESSAGE_ENC_BASE64; + break; + case "7bit": + $this->encoding = IMAP::MESSAGE_ENC_7BIT; + break; + case "8bit": + $this->encoding = IMAP::MESSAGE_ENC_8BIT; + break; + case "binary": + $this->encoding = IMAP::MESSAGE_ENC_BINARY; + break; + default: + $this->encoding = IMAP::MESSAGE_ENC_OTHER; + break; + + } + } + } + + /** + * Check if the current part represents an attachment + * + * @return bool + */ + public function isAttachment(): bool { + $valid_disposition = in_array(strtolower($this->disposition ?? ''), ClientManager::get('options.dispositions')); + + if ($this->type == IMAP::MESSAGE_TYPE_TEXT && ($this->ifdisposition == 0 || empty($this->disposition) || !$valid_disposition)) { + if (($this->subtype == null || in_array((strtolower($this->subtype)), ["plain", "html"])) && $this->filename == null && $this->name == null) { + return false; + } + } + return true; + } + +} diff --git a/htdocs/includes/Webklex/php-imap/src/Query/Query.php b/htdocs/includes/Webklex/php-imap/src/Query/Query.php new file mode 100644 index 00000000000..2607c389b30 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/Query/Query.php @@ -0,0 +1,980 @@ +setClient($client); + + $this->sequence = ClientManager::get('options.sequence', IMAP::ST_MSGN); + if (ClientManager::get('options.fetch') === IMAP::FT_PEEK) $this->leaveUnread(); + + if (ClientManager::get('options.fetch_order') === 'desc') { + $this->fetch_order = 'desc'; + } else { + $this->fetch_order = 'asc'; + } + + $this->date_format = ClientManager::get('date_format', 'd M y'); + $this->soft_fail = ClientManager::get('options.soft_fail', false); + + $this->setExtensions($extensions); + $this->query = new Collection(); + $this->boot(); + } + + /** + * Instance boot method for additional functionality + */ + protected function boot() { + } + + /** + * Parse a given value + * @param mixed $value + * + * @return string + */ + protected function parse_value($value): string { + switch (true) { + case $value instanceof Carbon: + $value = $value->format($this->date_format); + break; + } + + return (string)$value; + } + + /** + * Check if a given date is a valid carbon object and if not try to convert it + * @param string|Carbon $date + * + * @return Carbon + * @throws MessageSearchValidationException + */ + protected function parse_date($date): Carbon { + if ($date instanceof Carbon) return $date; + + try { + $date = Carbon::parse($date); + } catch (Exception $e) { + throw new MessageSearchValidationException(); + } + + return $date; + } + + /** + * Get the raw IMAP search query + * + * @return string + */ + public function generate_query(): string { + $query = ''; + $this->query->each(function($statement) use (&$query) { + if (count($statement) == 1) { + $query .= $statement[0]; + } else { + if ($statement[1] === null) { + $query .= $statement[0]; + } else { + if (is_numeric($statement[1])) { + $query .= $statement[0] . ' ' . $statement[1]; + } else { + $query .= $statement[0] . ' "' . $statement[1] . '"'; + } + } + } + $query .= ' '; + + }); + + $this->raw_query = trim($query); + + return $this->raw_query; + } + + /** + * Perform an imap search request + * + * @return Collection + * @throws GetMessagesFailedException + */ + protected function search(): Collection { + $this->generate_query(); + + try { + $available_messages = $this->client->getConnection()->search([$this->getRawQuery()], $this->sequence); + return $available_messages !== false ? new Collection($available_messages) : new Collection(); + } catch (RuntimeException $e) { + throw new GetMessagesFailedException("failed to fetch messages", 0, $e); + } catch (ConnectionFailedException $e) { + throw new GetMessagesFailedException("failed to fetch messages", 0, $e); + } + } + + /** + * Count all available messages matching the current search criteria + * + * @return int + * @throws GetMessagesFailedException + */ + public function count(): int { + return $this->search()->count(); + } + + /** + * Fetch a given id collection + * @param Collection $available_messages + * + * @return array + * @throws ConnectionFailedException + * @throws RuntimeException + */ + protected function fetch(Collection $available_messages): array { + if ($this->fetch_order === 'desc') { + $available_messages = $available_messages->reverse(); + } + + $uids = $available_messages->forPage($this->page, $this->limit)->toArray(); + $extensions = []; + if (empty($this->getExtensions()) === false) { + $extensions = $this->client->getConnection()->fetch($this->getExtensions(), $uids, null, $this->sequence); + } + $flags = $this->client->getConnection()->flags($uids, $this->sequence); + $headers = $this->client->getConnection()->headers($uids, "RFC822", $this->sequence); + + $contents = []; + if ($this->getFetchBody()) { + $contents = $this->client->getConnection()->content($uids, "RFC822", $this->sequence); + } + + return [ + "uids" => $uids, + "flags" => $flags, + "headers" => $headers, + "contents" => $contents, + "extensions" => $extensions, + ]; + } + + /** + * Make a new message from given raw components + * @param integer $uid + * @param integer $msglist + * @param string $header + * @param string $content + * @param array $flags + * + * @return Message|null + * @throws ConnectionFailedException + * @throws EventNotFoundException + * @throws GetMessagesFailedException + * @throws ReflectionException + */ + protected function make(int $uid, int $msglist, string $header, string $content, array $flags) { + try { + return Message::make($uid, $msglist, $this->getClient(), $header, $content, $flags, $this->getFetchOptions(), $this->sequence); + } catch (MessageNotFoundException $e) { + $this->setError($uid, $e); + } catch (RuntimeException $e) { + $this->setError($uid, $e); + } catch (MessageFlagException $e) { + $this->setError($uid, $e); + } catch (InvalidMessageDateException $e) { + $this->setError($uid, $e); + } catch (MessageContentFetchingException $e) { + $this->setError($uid, $e); + } + + $this->handleException($uid); + + return null; + } + + /** + * Get the message key for a given message + * @param string $message_key + * @param integer $msglist + * @param Message $message + * + * @return string + */ + protected function getMessageKey(string $message_key, int $msglist, Message $message): string { + switch ($message_key) { + case 'number': + $key = $message->getMessageNo(); + break; + case 'list': + $key = $msglist; + break; + case 'uid': + $key = $message->getUid(); + break; + default: + $key = $message->getMessageId(); + break; + } + return (string)$key; + } + + /** + * Curates a given collection aof messages + * @param Collection $available_messages + * + * @return MessageCollection + * @throws GetMessagesFailedException + */ + public function curate_messages(Collection $available_messages): MessageCollection { + try { + if ($available_messages->count() > 0) { + return $this->populate($available_messages); + } + return MessageCollection::make([]); + } catch (Exception $e) { + throw new GetMessagesFailedException($e->getMessage(), 0, $e); + } + } + + /** + * Populate a given id collection and receive a fully fetched message collection + * @param Collection $available_messages + * + * @return MessageCollection + * @throws ConnectionFailedException + * @throws EventNotFoundException + * @throws GetMessagesFailedException + * @throws ReflectionException + * @throws RuntimeException + */ + protected function populate(Collection $available_messages): MessageCollection { + $messages = MessageCollection::make([]); + + $messages->total($available_messages->count()); + + $message_key = ClientManager::get('options.message_key'); + + $raw_messages = $this->fetch($available_messages); + + $msglist = 0; + foreach ($raw_messages["headers"] as $uid => $header) { + $content = $raw_messages["contents"][$uid] ?? ""; + $flag = $raw_messages["flags"][$uid] ?? []; + $extensions = $raw_messages["extensions"][$uid] ?? []; + + $message = $this->make($uid, $msglist, $header, $content, $flag); + foreach($extensions as $key => $extension) { + $message->getHeader()->set($key, $extension); + } + if ($message !== null) { + $key = $this->getMessageKey($message_key, $msglist, $message); + $messages->put("$key", $message); + } + $msglist++; + } + + return $messages; + } + + /** + * Fetch the current query and return all found messages + * + * @return MessageCollection + * @throws GetMessagesFailedException + */ + public function get(): MessageCollection { + return $this->curate_messages($this->search()); + } + + /** + * Fetch the current query as chunked requests + * @param callable $callback + * @param int $chunk_size + * @param int $start_chunk + * + * @throws ConnectionFailedException + * @throws EventNotFoundException + * @throws GetMessagesFailedException + * @throws ReflectionException + * @throws RuntimeException + */ + public function chunked(callable $callback, int $chunk_size = 10, int $start_chunk = 1) { + $available_messages = $this->search(); + if (($available_messages_count = $available_messages->count()) > 0) { + $old_limit = $this->limit; + $old_page = $this->page; + + $this->limit = $chunk_size; + $this->page = $start_chunk; + $handled_messages_count = 0; + do { + $messages = $this->populate($available_messages); + $handled_messages_count += $messages->count(); + $callback($messages, $this->page); + $this->page++; + } while ($handled_messages_count < $available_messages_count); + $this->limit = $old_limit; + $this->page = $old_page; + } + } + + /** + * Paginate the current query + * @param int $per_page Results you which to receive per page + * @param int|null $page The current page you are on (e.g. 0, 1, 2, ...) use `null` to enable auto mode + * @param string $page_name The page name / uri parameter used for the generated links and the auto mode + * + * @return LengthAwarePaginator + * @throws GetMessagesFailedException + */ + public function paginate(int $per_page = 5, $page = null, string $page_name = 'imap_page'): LengthAwarePaginator { + if ( + $page === null + && isset($_GET[$page_name]) + && $_GET[$page_name] > 0 + ) { + $this->page = intval($_GET[$page_name]); + } elseif ($page > 0) { + $this->page = $page; + } + + $this->limit = $per_page; + + return $this->get()->paginate($per_page, $this->page, $page_name, true); + } + + /** + * Get a new Message instance + * @param int $uid + * @param int|null $msglist + * @param int|string|null $sequence + * + * @return Message + * @throws ConnectionFailedException + * @throws RuntimeException + * @throws InvalidMessageDateException + * @throws MessageContentFetchingException + * @throws MessageHeaderFetchingException + * @throws EventNotFoundException + * @throws MessageFlagException + * @throws MessageNotFoundException + */ + public function getMessage(int $uid, $msglist = null, $sequence = null): Message { + return new Message($uid, $msglist, $this->getClient(), $this->getFetchOptions(), $this->getFetchBody(), $this->getFetchFlags(), $sequence ? $sequence : $this->sequence); + } + + /** + * Get a message by its message number + * @param $msgn + * @param int|null $msglist + * + * @return Message + * @throws ConnectionFailedException + * @throws InvalidMessageDateException + * @throws MessageContentFetchingException + * @throws MessageHeaderFetchingException + * @throws RuntimeException + * @throws EventNotFoundException + * @throws MessageFlagException + * @throws MessageNotFoundException + */ + public function getMessageByMsgn($msgn, $msglist = null): Message { + return $this->getMessage($msgn, $msglist, IMAP::ST_MSGN); + } + + /** + * Get a message by its uid + * @param $uid + * + * @return Message + * @throws ConnectionFailedException + * @throws InvalidMessageDateException + * @throws MessageContentFetchingException + * @throws MessageHeaderFetchingException + * @throws RuntimeException + * @throws EventNotFoundException + * @throws MessageFlagException + * @throws MessageNotFoundException + */ + public function getMessageByUid($uid): Message { + return $this->getMessage($uid, null, IMAP::ST_UID); + } + + /** + * Filter all available uids by a given closure and get a curated list of messages + * @param callable $closure + * + * @return MessageCollection + * @throws ConnectionFailedException + * @throws GetMessagesFailedException + * @throws MessageNotFoundException + */ + public function filter(callable $closure): MessageCollection { + $connection = $this->getClient()->getConnection(); + + $uids = $connection->getUid(); + $available_messages = new Collection(); + if (is_array($uids)) { + foreach ($uids as $id){ + if ($closure($id)) { + $available_messages->push($id); + } + } + } + + return $this->curate_messages($available_messages); + } + + /** + * Get all messages with an uid greater or equal to a given UID + * @param int $uid + * + * @return MessageCollection + * @throws ConnectionFailedException + * @throws GetMessagesFailedException + * @throws MessageNotFoundException + */ + public function getByUidGreaterOrEqual(int $uid): MessageCollection { + return $this->filter(function($id) use($uid){ + return $id >= $uid; + }); + } + + /** + * Get all messages with an uid greater than a given UID + * @param int $uid + * + * @return MessageCollection + * @throws ConnectionFailedException + * @throws GetMessagesFailedException + * @throws MessageNotFoundException + */ + public function getByUidGreater(int $uid): MessageCollection { + return $this->filter(function($id) use($uid){ + return $id > $uid; + }); + } + + /** + * Get all messages with an uid lower than a given UID + * @param int $uid + * + * @return MessageCollection + * @throws ConnectionFailedException + * @throws GetMessagesFailedException + * @throws MessageNotFoundException + */ + public function getByUidLower(int $uid): MessageCollection { + return $this->filter(function($id) use($uid){ + return $id < $uid; + }); + } + + /** + * Get all messages with an uid lower or equal to a given UID + * @param int $uid + * + * @return MessageCollection + * @throws ConnectionFailedException + * @throws GetMessagesFailedException + * @throws MessageNotFoundException + */ + public function getByUidLowerOrEqual(int $uid): MessageCollection { + return $this->filter(function($id) use($uid){ + return $id <= $uid; + }); + } + + /** + * Get all messages with an uid greater than a given UID + * @param int $uid + * + * @return MessageCollection + * @throws ConnectionFailedException + * @throws GetMessagesFailedException + * @throws MessageNotFoundException + */ + public function getByUidLowerThan(int $uid): MessageCollection { + return $this->filter(function($id) use($uid){ + return $id < $uid; + }); + } + + /** + * Don't mark messages as read when fetching + * + * @return $this + */ + public function leaveUnread(): Query { + $this->setFetchOptions(IMAP::FT_PEEK); + + return $this; + } + + /** + * Mark all messages as read when fetching + * + * @return $this + */ + public function markAsRead(): Query { + $this->setFetchOptions(IMAP::FT_UID); + + return $this; + } + + /** + * Set the sequence type + * @param int $sequence + * + * @return $this + */ + public function setSequence(int $sequence): Query { + $this->sequence = $sequence; + + return $this; + } + + /** + * Get the sequence type + * + * @return int|string + */ + public function getSequence() { + return $this->sequence; + } + + /** + * @return Client + * @throws ConnectionFailedException + */ + public function getClient(): Client { + $this->client->checkConnection(); + return $this->client; + } + + /** + * Set the limit and page for the current query + * @param int $limit + * @param int $page + * + * @return $this + */ + public function limit(int $limit, int $page = 1): Query { + if ($page >= 1) $this->page = $page; + $this->limit = $limit; + + return $this; + } + + /** + * @return Collection + */ + public function getQuery(): Collection { + return $this->query; + } + + /** + * @param array $query + * @return Query + */ + public function setQuery(array $query): Query { + $this->query = new Collection($query); + return $this; + } + + /** + * @return string + */ + public function getRawQuery(): string { + return $this->raw_query; + } + + /** + * @param string $raw_query + * @return Query + */ + public function setRawQuery(string $raw_query): Query { + $this->raw_query = $raw_query; + return $this; + } + + /** + * @return string[] + */ + public function getExtensions(): array { + return $this->extensions; + } + + /** + * @param string[] $extensions + * @return Query + */ + public function setExtensions(array $extensions): Query { + $this->extensions = $extensions; + if (count($this->extensions) > 0) { + if (in_array("UID", $this->extensions) === false) { + $this->extensions[] = "UID"; + } + } + return $this; + } + + /** + * @param Client $client + * @return Query + */ + public function setClient(Client $client): Query { + $this->client = $client; + return $this; + } + + /** + * @return int + */ + public function getLimit() { + return $this->limit; + } + + /** + * @param int $limit + * @return Query + */ + public function setLimit(int $limit): Query { + $this->limit = $limit <= 0 ? null : $limit; + return $this; + } + + /** + * @return int + */ + public function getPage(): int { + return $this->page; + } + + /** + * @param int $page + * @return Query + */ + public function setPage(int $page): Query { + $this->page = $page; + return $this; + } + + /** + * @param int $fetch_options + * @return Query + */ + public function setFetchOptions(int $fetch_options): Query { + $this->fetch_options = $fetch_options; + return $this; + } + + /** + * @param int $fetch_options + * @return Query + */ + public function fetchOptions(int $fetch_options): Query { + return $this->setFetchOptions($fetch_options); + } + + /** + * @return int + */ + public function getFetchOptions() { + return $this->fetch_options; + } + + /** + * @return boolean + */ + public function getFetchBody() { + return $this->fetch_body; + } + + /** + * @param boolean $fetch_body + * @return Query + */ + public function setFetchBody(bool $fetch_body): Query { + $this->fetch_body = $fetch_body; + return $this; + } + + /** + * @param boolean $fetch_body + * @return Query + */ + public function fetchBody(bool $fetch_body): Query { + return $this->setFetchBody($fetch_body); + } + + /** + * @return int + */ + public function getFetchFlags() { + return $this->fetch_flags; + } + + /** + * @param int $fetch_flags + * @return Query + */ + public function setFetchFlags(int $fetch_flags): Query { + $this->fetch_flags = $fetch_flags; + return $this; + } + + /** + * @param string $fetch_order + * @return Query + */ + public function setFetchOrder(string $fetch_order): Query { + $fetch_order = strtolower($fetch_order); + + if (in_array($fetch_order, ['asc', 'desc'])) { + $this->fetch_order = $fetch_order; + } + + return $this; + } + + /** + * @param string $fetch_order + * @return Query + */ + public function fetchOrder(string $fetch_order): Query { + return $this->setFetchOrder($fetch_order); + } + + /** + * @return string + */ + public function getFetchOrder(): string { + return $this->fetch_order; + } + + /** + * @return Query + */ + public function setFetchOrderAsc(): Query { + return $this->setFetchOrder('asc'); + } + + /** + * @return Query + */ + public function fetchOrderAsc(): Query { + return $this->setFetchOrderAsc(); + } + + /** + * @return Query + */ + public function setFetchOrderDesc(): Query { + return $this->setFetchOrder('desc'); + } + + /** + * @return Query + */ + public function fetchOrderDesc(): Query { + return $this->setFetchOrderDesc(); + } + + /** + * @return Query + * @var boolean $state + * + */ + public function softFail(bool $state = true): Query { + return $this->setSoftFail($state); + } + + /** + * @return Query + * @var boolean $state + * + */ + public function setSoftFail(bool $state = true): Query { + $this->soft_fail = $state; + + return $this; + } + + /** + * @return boolean + */ + public function getSoftFail(): bool { + return $this->soft_fail; + } + + /** + * Handle the exception for a given uid + * @param integer $uid + * + * @throws GetMessagesFailedException + */ + protected function handleException(int $uid) { + if ($this->soft_fail === false && $this->hasError($uid)) { + $error = $this->getError($uid); + throw new GetMessagesFailedException($error->getMessage(), 0, $error); + } + } + + /** + * Add a new error to the error holder + * @param integer $uid + * @param Exception $error + */ + protected function setError(int $uid, Exception $error) { + $this->errors[$uid] = $error; + } + + /** + * Check if there are any errors / exceptions present + * @return boolean + * @var integer|null $uid + * + */ + public function hasErrors($uid = null): bool { + if ($uid !== null) { + return $this->hasError($uid); + } + return count($this->errors) > 0; + } + + /** + * Check if there is an error / exception present + * @return boolean + * @var integer $uid + * + */ + public function hasError(int $uid): bool { + return isset($this->errors[$uid]); + } + + /** + * Get all available errors / exceptions + * + * @return array + */ + public function errors(): array { + return $this->getErrors(); + } + + /** + * Get all available errors / exceptions + * + * @return array + */ + public function getErrors(): array { + return $this->errors; + } + + /** + * Get a specific error / exception + * @return Exception|null + * @var integer $uid + * + */ + public function error(int $uid) { + return $this->getError($uid); + } + + /** + * Get a specific error / exception + * @return Exception|null + * @var integer $uid + * + */ + public function getError(int $uid) { + if ($this->hasError($uid)) { + return $this->errors[$uid]; + } + return null; + } +} diff --git a/htdocs/includes/Webklex/php-imap/src/Query/WhereQuery.php b/htdocs/includes/Webklex/php-imap/src/Query/WhereQuery.php new file mode 100755 index 00000000000..b6483f6de55 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/Query/WhereQuery.php @@ -0,0 +1,546 @@ +whereNot(); + $name = substr($name, 3); + } + + if (strpos(strtolower($name), "where") === false) { + $method = 'where' . ucfirst($name); + } else { + $method = lcfirst($name); + } + + if (method_exists($this, $method) === true) { + return call_user_func_array([$that, $method], $arguments); + } + + throw new MethodNotFoundException("Method " . self::class . '::' . $method . '() is not supported'); + } + + /** + * Validate a given criteria + * @param $criteria + * + * @return string + * @throws InvalidWhereQueryCriteriaException + */ + protected function validate_criteria($criteria): string { + $command = strtoupper($criteria); + if (substr($command, 0, 7) === "CUSTOM ") { + return substr($criteria, 7); + } + if (in_array($command, $this->available_criteria) === false) { + throw new InvalidWhereQueryCriteriaException("Invalid imap search criteria: $command"); + } + + return $criteria; + } + + /** + * Register search parameters + * @param mixed $criteria + * @param null $value + * + * @return $this + * @throws InvalidWhereQueryCriteriaException + * + * Examples: + * $query->from("someone@email.tld")->seen(); + * $query->whereFrom("someone@email.tld")->whereSeen(); + * $query->where([["FROM" => "someone@email.tld"], ["SEEN"]]); + * $query->where(["FROM" => "someone@email.tld"])->where(["SEEN"]); + * $query->where(["FROM" => "someone@email.tld", "SEEN"]); + * $query->where("FROM", "someone@email.tld")->where("SEEN"); + */ + public function where($criteria, $value = null): WhereQuery { + if (is_array($criteria)) { + foreach ($criteria as $key => $value) { + if (is_numeric($key)) { + $this->where($value); + }else{ + $this->where($key, $value); + } + } + } else { + $this->push_search_criteria($criteria, $value); + } + + return $this; + } + + /** + * Push a given search criteria and value pair to the search query + * @param $criteria string + * @param $value mixed + * + * @throws InvalidWhereQueryCriteriaException + */ + protected function push_search_criteria(string $criteria, $value){ + $criteria = $this->validate_criteria($criteria); + $value = $this->parse_value($value); + + if ($value === null || $value === '') { + $this->query->push([$criteria]); + } else { + $this->query->push([$criteria, $value]); + } + } + + /** + * @param Closure $closure + * + * @return $this + */ + public function orWhere(Closure $closure = null): WhereQuery { + $this->query->push(['OR']); + if ($closure !== null) $closure($this); + + return $this; + } + + /** + * @param Closure $closure + * + * @return $this + */ + public function andWhere(Closure $closure = null): WhereQuery { + $this->query->push(['AND']); + if ($closure !== null) $closure($this); + + return $this; + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereAll(): WhereQuery { + return $this->where('ALL'); + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereAnswered(): WhereQuery { + return $this->where('ANSWERED'); + } + + /** + * @param string $value + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereBcc(string $value): WhereQuery { + return $this->where('BCC', $value); + } + + /** + * @param mixed $value + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + * @throws MessageSearchValidationException + */ + public function whereBefore($value): WhereQuery { + $date = $this->parse_date($value); + return $this->where('BEFORE', $date); + } + + /** + * @param string $value + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereBody(string $value): WhereQuery { + return $this->where('BODY', $value); + } + + /** + * @param string $value + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereCc(string $value): WhereQuery { + return $this->where('CC', $value); + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereDeleted(): WhereQuery { + return $this->where('DELETED'); + } + + /** + * @param string $value + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereFlagged(string $value): WhereQuery { + return $this->where('FLAGGED', $value); + } + + /** + * @param string $value + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereFrom(string $value): WhereQuery { + return $this->where('FROM', $value); + } + + /** + * @param string $value + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereKeyword(string $value): WhereQuery { + return $this->where('KEYWORD', $value); + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereNew(): WhereQuery { + return $this->where('NEW'); + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereNot(): WhereQuery { + return $this->where('NOT'); + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereOld(): WhereQuery { + return $this->where('OLD'); + } + + /** + * @param mixed $value + * + * @return WhereQuery + * @throws MessageSearchValidationException + * @throws InvalidWhereQueryCriteriaException + */ + public function whereOn($value): WhereQuery { + $date = $this->parse_date($value); + return $this->where('ON', $date); + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereRecent(): WhereQuery { + return $this->where('RECENT'); + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereSeen(): WhereQuery { + return $this->where('SEEN'); + } + + /** + * @param mixed $value + * + * @return WhereQuery + * @throws MessageSearchValidationException + * @throws InvalidWhereQueryCriteriaException + */ + public function whereSince($value): WhereQuery { + $date = $this->parse_date($value); + return $this->where('SINCE', $date); + } + + /** + * @param string $value + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereSubject(string $value): WhereQuery { + return $this->where('SUBJECT', $value); + } + + /** + * @param string $value + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereText(string $value): WhereQuery { + return $this->where('TEXT', $value); + } + + /** + * @param string $value + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereTo(string $value): WhereQuery { + return $this->where('TO', $value); + } + + /** + * @param string $value + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereUnkeyword(string $value): WhereQuery { + return $this->where('UNKEYWORD', $value); + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereUnanswered(): WhereQuery { + return $this->where('UNANSWERED'); + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereUndeleted(): WhereQuery { + return $this->where('UNDELETED'); + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereUnflagged(): WhereQuery { + return $this->where('UNFLAGGED'); + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereUnseen(): WhereQuery { + return $this->where('UNSEEN'); + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereNoXSpam(): WhereQuery { + return $this->where("CUSTOM X-Spam-Flag NO"); + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereIsXSpam(): WhereQuery { + return $this->where("CUSTOM X-Spam-Flag YES"); + } + + /** + * Search for a specific header value + * @param $header + * @param $value + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereHeader($header, $value): WhereQuery { + return $this->where("CUSTOM HEADER $header $value"); + } + + /** + * Search for a specific message id + * @param $messageId + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereMessageId($messageId): WhereQuery { + return $this->whereHeader("Message-ID", $messageId); + } + + /** + * Search for a specific message id + * @param $messageId + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereInReplyTo($messageId): WhereQuery { + return $this->whereHeader("In-Reply-To", $messageId); + } + + /** + * @param $country_code + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereLanguage($country_code): WhereQuery { + return $this->where("Content-Language $country_code"); + } + + /** + * Get message be it UID. + * + * @param int|string $uid + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereUid($uid): WhereQuery { + return $this->where('UID', $uid); + } + + /** + * Get messages by their UIDs. + * + * @param array $uids + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereUidIn(array $uids): WhereQuery { + $uids = implode(',', $uids); + return $this->where('UID', $uids); + } + + /** + * Apply the callback if the given "value" is truthy. + * copied from @url https://github.com/laravel/framework/blob/8.x/src/Illuminate/Support/Traits/Conditionable.php + * + * @param mixed $value + * @param callable $callback + * @param callable|null $default + * @return $this|mixed + */ + public function when($value, callable $callback, $default = null) { + if ($value) { + return $callback($this, $value) ?: $this; + } elseif ($default) { + return $default($this, $value) ?: $this; + } + + return $this; + } + + /** + * Apply the callback if the given "value" is falsy. + * copied from @url https://github.com/laravel/framework/blob/8.x/src/Illuminate/Support/Traits/Conditionable.php + * + * @param mixed $value + * @param callable $callback + * @param callable|null $default + * @return $this|mixed + */ + public function unless($value, callable $callback, $default = null) { + if (!$value) { + return $callback($this, $value) ?: $this; + } elseif ($default) { + return $default($this, $value) ?: $this; + } + + return $this; + } +} \ No newline at end of file diff --git a/htdocs/includes/Webklex/php-imap/src/Structure.php b/htdocs/includes/Webklex/php-imap/src/Structure.php new file mode 100644 index 00000000000..682d7bff327 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/Structure.php @@ -0,0 +1,174 @@ +raw = $raw_structure; + $this->header = $header; + $this->config = ClientManager::get('options'); + $this->parse(); + } + + /** + * Parse the given raw structure + * + * @throws MessageContentFetchingException + * @throws InvalidMessageDateException + */ + protected function parse(){ + $this->findContentType(); + $this->parts = $this->find_parts(); + } + + /** + * Determine the message content type + */ + public function findContentType(){ + $content_type = $this->header->get("content_type"); + $content_type = (is_array($content_type)) ? implode(' ', $content_type) : $content_type; + if(stripos($content_type, 'multipart') === 0) { + $this->type = IMAP::MESSAGE_TYPE_MULTIPART; + }else{ + $this->type = IMAP::MESSAGE_TYPE_TEXT; + } + } + + /** + * Find all available headers and return the left over body segment + * @var string $context + * @var integer $part_number + * + * @return Part[] + * @throws InvalidMessageDateException + */ + private function parsePart(string $context, int $part_number = 0): array { + $body = $context; + while (($pos = strpos($body, "\r\n")) > 0) { + $body = substr($body, $pos + 2); + } + $headers = substr($context, 0, strlen($body) * -1); + $body = substr($body, 0, -2); + + $headers = new Header($headers); + if (($boundary = $headers->getBoundary()) !== null) { + return $this->detectParts($boundary, $body, $part_number); + } + return [new Part($body, $headers, $part_number)]; + } + + /** + * @param string $boundary + * @param string $context + * @param int $part_number + * + * @return array + * @throws InvalidMessageDateException + */ + private function detectParts(string $boundary, string $context, int $part_number = 0): array { + $base_parts = explode( $boundary, $context); + $final_parts = []; + foreach($base_parts as $ctx) { + $ctx = substr($ctx, 2); + if ($ctx !== "--" && $ctx != "") { + $parts = $this->parsePart($ctx, $part_number); + foreach ($parts as $part) { + $final_parts[] = $part; + $part_number = $part->part_number; + } + $part_number++; + } + } + return $final_parts; + } + + /** + * Find all available parts + * + * @return array + * @throws MessageContentFetchingException + * @throws InvalidMessageDateException + */ + public function find_parts(): array { + if($this->type === IMAP::MESSAGE_TYPE_MULTIPART) { + if (($boundary = $this->header->getBoundary()) === null) { + throw new MessageContentFetchingException("no content found", 0); + } + + return $this->detectParts($boundary, $this->raw); + } + + return [new Part($this->raw, $this->header)]; + } + + /** + * Try to find a boundary if possible + * + * @return string|null + * @Depricated since version 2.4.4 + */ + public function getBoundary(){ + return $this->header->getBoundary(); + } +} diff --git a/htdocs/includes/Webklex/php-imap/src/Support/AttachmentCollection.php b/htdocs/includes/Webklex/php-imap/src/Support/AttachmentCollection.php new file mode 100644 index 00000000000..8b3f9c32213 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/Support/AttachmentCollection.php @@ -0,0 +1,22 @@ +parent->content); + } + + /** + * Get a base64 image src string + * + * @return string|null + */ + public function getImageSrc() { + return 'data:'.$this->parent->content_type.';base64,'.$this->getContentBase64Encoded(); + } +} \ No newline at end of file diff --git a/htdocs/includes/Webklex/php-imap/src/Support/Masks/Mask.php b/htdocs/includes/Webklex/php-imap/src/Support/Masks/Mask.php new file mode 100755 index 00000000000..1ab17d5a808 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/Support/Masks/Mask.php @@ -0,0 +1,137 @@ +parent = $parent; + + if(method_exists($this->parent, 'getAttributes')){ + $this->attributes = array_merge($this->attributes, $this->parent->getAttributes()); + } + + $this->boot(); + } + + /** + * Boot method made to be used by any custom mask + */ + protected function boot(){} + + /** + * Call dynamic attribute setter and getter methods and inherit the parent calls + * @param string $method + * @param array $arguments + * + * @return mixed + * @throws MethodNotFoundException + */ + public function __call(string $method, array $arguments) { + if(strtolower(substr($method, 0, 3)) === 'get') { + $name = Str::snake(substr($method, 3)); + + if(isset($this->attributes[$name])) { + return $this->attributes[$name]; + } + + }elseif (strtolower(substr($method, 0, 3)) === 'set') { + $name = Str::snake(substr($method, 3)); + + if(isset($this->attributes[$name])) { + $this->attributes[$name] = array_pop($arguments); + + return $this->attributes[$name]; + } + + } + + if(method_exists($this->parent, $method) === true){ + return call_user_func_array([$this->parent, $method], $arguments); + } + + throw new MethodNotFoundException("Method ".self::class.'::'.$method.'() is not supported'); + } + + /** + * Magic setter + * @param $name + * @param $value + * + * @return mixed + */ + public function __set($name, $value) { + $this->attributes[$name] = $value; + + return $this->attributes[$name]; + } + + /** + * Magic getter + * @param $name + * + * @return mixed|null + */ + public function __get($name) { + if(isset($this->attributes[$name])) { + return $this->attributes[$name]; + } + + return null; + } + + /** + * Get the parent instance + * + * @return object + */ + public function getParent(){ + return $this->parent; + } + + /** + * Get all available attributes + * + * @return array + */ + public function getAttributes(): array { + return $this->attributes; + } + +} \ No newline at end of file diff --git a/htdocs/includes/Webklex/php-imap/src/Support/Masks/MessageMask.php b/htdocs/includes/Webklex/php-imap/src/Support/Masks/MessageMask.php new file mode 100644 index 00000000000..d072e8b6456 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/Support/Masks/MessageMask.php @@ -0,0 +1,86 @@ +parent->getBodies(); + if (!isset($bodies['html'])) { + return null; + } + + if(is_object($bodies['html']) && property_exists($bodies['html'], 'content')) { + return $bodies['html']->content; + } + return $bodies['html']; + } + + /** + * Get the Message html body filtered by an optional callback + * @param callable|bool $callback + * + * @return string|null + */ + public function getCustomHTMLBody($callback = false) { + $body = $this->getHtmlBody(); + if($body === null) return null; + + if ($callback !== false) { + $aAttachment = $this->parent->getAttachments(); + $aAttachment->each(function($oAttachment) use(&$body, $callback) { + /** @var Attachment $oAttachment */ + if(is_callable($callback)) { + $body = $callback($body, $oAttachment); + }elseif(is_string($callback)) { + call_user_func($callback, [$body, $oAttachment]); + } + }); + } + + return $body; + } + + /** + * Get the Message html body with embedded base64 images + * the resulting $body. + * + * @return string|null + */ + public function getHTMLBodyWithEmbeddedBase64Images() { + return $this->getCustomHTMLBody(function($body, $oAttachment){ + /** @var Attachment $oAttachment */ + if ($oAttachment->id) { + $body = str_replace('cid:'.$oAttachment->id, 'data:'.$oAttachment->getContentType().';base64, '.base64_encode($oAttachment->getContent()), $body); + } + + return $body; + }); + } +} \ No newline at end of file diff --git a/htdocs/includes/Webklex/php-imap/src/Support/MessageCollection.php b/htdocs/includes/Webklex/php-imap/src/Support/MessageCollection.php new file mode 100644 index 00000000000..6d1249fae52 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/Support/MessageCollection.php @@ -0,0 +1,22 @@ +total ?: $this->count(); + + $results = !$prepaginated && $total ? $this->forPage($page, $per_page) : $this->all(); + + return $this->paginator($results, $total, $per_page, $page, [ + 'path' => Paginator::resolveCurrentPath(), + 'pageName' => $page_name, + ]); + } + + /** + * Create a new length-aware paginator instance. + * @param array $items + * @param int $total + * @param int $per_page + * @param int|null $current_page + * @param array $options + * + * @return LengthAwarePaginator + */ + protected function paginator(array $items, int $total, int $per_page, $current_page, array $options): LengthAwarePaginator { + return new LengthAwarePaginator($items, $total, $per_page, $current_page, $options); + } + + /** + * Get and set the total amount + * @param null $total + * + * @return int|null + */ + public function total($total = null) { + if($total === null) { + return $this->total; + } + + return $this->total = $total; + } +} diff --git a/htdocs/includes/Webklex/php-imap/src/Traits/HasEvents.php b/htdocs/includes/Webklex/php-imap/src/Traits/HasEvents.php new file mode 100644 index 00000000000..1852b432ae1 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/Traits/HasEvents.php @@ -0,0 +1,77 @@ +events[$section])) { + $this->events[$section][$event] = $class; + } + } + + /** + * Set all events + * @param $events + */ + public function setEvents($events) { + $this->events = $events; + } + + /** + * Get a specific event callback + * @param $section + * @param $event + * + * @return Event + * @throws EventNotFoundException + */ + public function getEvent($section, $event): Event { + if (isset($this->events[$section])) { + return $this->events[$section][$event]; + } + throw new EventNotFoundException(); + } + + /** + * Get all events + * + * @return array + */ + public function getEvents(): array { + return $this->events; + } + +} \ No newline at end of file diff --git a/htdocs/includes/Webklex/php-imap/src/config/imap.php b/htdocs/includes/Webklex/php-imap/src/config/imap.php new file mode 100644 index 00000000000..590d27cbf33 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/src/config/imap.php @@ -0,0 +1,226 @@ + 'd-M-Y', + + /* + |-------------------------------------------------------------------------- + | Default account + |-------------------------------------------------------------------------- + | + | The default account identifier. It will be used as default for any missing account parameters. + | If however the default account is missing a parameter the package default will be used. + | Set to 'false' [boolean] to disable this functionality. + | + */ + 'default' => 'default', + + /* + |-------------------------------------------------------------------------- + | Available accounts + |-------------------------------------------------------------------------- + | + | Please list all IMAP accounts which you are planning to use within the + | array below. + | + */ + 'accounts' => [ + + 'default' => [// account identifier + 'host' => 'localhost', + 'port' => 993, + 'protocol' => 'imap', //might also use imap, [pop3 or nntp (untested)] + 'encryption' => 'ssl', // Supported: false, 'ssl', 'tls' + 'validate_cert' => true, + 'username' => 'root@example.com', + 'password' => '', + 'authentication' => null, + 'proxy' => [ + 'socket' => null, + 'request_fulluri' => false, + 'username' => null, + 'password' => null, + ], + "timeout" => 30, + "extensions" => [] + ], + + /* + 'gmail' => [ // account identifier + 'host' => 'imap.gmail.com', + 'port' => 993, + 'encryption' => 'ssl', + 'validate_cert' => true, + 'username' => 'example@gmail.com', + 'password' => 'PASSWORD', + 'authentication' => 'oauth', + ], + + 'another' => [ // account identifier + 'host' => '', + 'port' => 993, + 'encryption' => false, + 'validate_cert' => true, + 'username' => '', + 'password' => '', + 'authentication' => null, + ] + */ + ], + + /* + |-------------------------------------------------------------------------- + | Available IMAP options + |-------------------------------------------------------------------------- + | + | Available php imap config parameters are listed below + | -Delimiter (optional): + | This option is only used when calling $oClient-> + | You can use any supported char such as ".", "/", (...) + | -Fetch option: + | IMAP::FT_UID - Message marked as read by fetching the body message + | IMAP::FT_PEEK - Fetch the message without setting the "seen" flag + | -Fetch sequence id: + | IMAP::ST_UID - Fetch message components using the message uid + | IMAP::ST_MSGN - Fetch message components using the message number + | -Body download option + | Default TRUE + | -Flag download option + | Default TRUE + | -Soft fail + | Default FALSE - Set to TRUE if you want to ignore certain exception while fetching bulk messages + | -RFC822 + | Default TRUE - Set to FALSE to prevent the usage of \imap_rfc822_parse_headers(). + | See https://github.com/Webklex/php-imap/issues/115 for more information. + | -Debug enable to trace communication traffic + | -UID cache enable the UID cache + | -Fallback date is used if the given message date could not be parsed + | -Boundary regex used to detect message boundaries. If you are having problems with empty messages, missing + | attachments or anything like this. Be advised that it likes to break which causes new problems.. + | -Message key identifier option + | You can choose between the following: + | 'id' - Use the MessageID as array key (default, might cause hickups with yahoo mail) + | 'number' - Use the message number as array key (isn't always unique and can cause some interesting behavior) + | 'list' - Use the message list number as array key (incrementing integer (does not always start at 0 or 1) + | 'uid' - Use the message uid as array key (isn't always unique and can cause some interesting behavior) + | -Fetch order + | 'asc' - Order all messages ascending (probably results in oldest first) + | 'desc' - Order all messages descending (probably results in newest first) + | -Disposition types potentially considered an attachment + | Default ['attachment', 'inline'] + | -Common folders + | Default folder locations and paths assumed if none is provided + | -Open IMAP options: + | DISABLE_AUTHENTICATOR - Disable authentication properties. + | Use 'GSSAPI' if you encounter the following + | error: "Kerberos error: No credentials cache + | file found (try running kinit) (...)" + | or ['GSSAPI','PLAIN'] if you are using outlook mail + | -Decoder options (currently only the message subject and attachment name decoder can be set) + | 'utf-8' - Uses imap_utf8($string) to decode a string + | 'mimeheader' - Uses mb_decode_mimeheader($string) to decode a string + | + */ + 'options' => [ + 'delimiter' => '/', + 'fetch' => \Webklex\PHPIMAP\IMAP::FT_PEEK, + 'sequence' => \Webklex\PHPIMAP\IMAP::ST_UID, + 'fetch_body' => true, + 'fetch_flags' => true, + 'soft_fail' => false, + 'rfc822' => true, + 'debug' => false, + 'uid_cache' => true, + // 'fallback_date' => "01.01.1970 00:00:00", + 'boundary' => '/boundary=(.*?(?=;)|(.*))/i', + 'message_key' => 'list', + 'fetch_order' => 'asc', + 'dispositions' => ['attachment', 'inline'], + 'common_folders' => [ + "root" => "INBOX", + "junk" => "INBOX/Junk", + "draft" => "INBOX/Drafts", + "sent" => "INBOX/Sent", + "trash" => "INBOX/Trash", + ], + 'decoder' => [ + 'message' => 'utf-8', // mimeheader + 'attachment' => 'utf-8' // mimeheader + ], + 'open' => [ + // 'DISABLE_AUTHENTICATOR' => 'GSSAPI' + ] + ], + + /* + |-------------------------------------------------------------------------- + | Available flags + |-------------------------------------------------------------------------- + | + | List all available / supported flags. Set to null to accept all given flags. + */ + 'flags' => ['recent', 'flagged', 'answered', 'deleted', 'seen', 'draft'], + + /* + |-------------------------------------------------------------------------- + | Available events + |-------------------------------------------------------------------------- + | + */ + 'events' => [ + "message" => [ + 'new' => \Webklex\PHPIMAP\Events\MessageNewEvent::class, + 'moved' => \Webklex\PHPIMAP\Events\MessageMovedEvent::class, + 'copied' => \Webklex\PHPIMAP\Events\MessageCopiedEvent::class, + 'deleted' => \Webklex\PHPIMAP\Events\MessageDeletedEvent::class, + 'restored' => \Webklex\PHPIMAP\Events\MessageRestoredEvent::class, + ], + "folder" => [ + 'new' => \Webklex\PHPIMAP\Events\FolderNewEvent::class, + 'moved' => \Webklex\PHPIMAP\Events\FolderMovedEvent::class, + 'deleted' => \Webklex\PHPIMAP\Events\FolderDeletedEvent::class, + ], + "flag" => [ + 'new' => \Webklex\PHPIMAP\Events\FlagNewEvent::class, + 'deleted' => \Webklex\PHPIMAP\Events\FlagDeletedEvent::class, + ], + ], + + /* + |-------------------------------------------------------------------------- + | Available masking options + |-------------------------------------------------------------------------- + | + | By using your own custom masks you can implement your own methods for + | a better and faster access and less code to write. + | + | Checkout the two examples custom_attachment_mask and custom_message_mask + | for a quick start. + | + | The provided masks below are used as the default masks. + */ + 'masks' => [ + 'message' => \Webklex\PHPIMAP\Support\Masks\MessageMask::class, + 'attachment' => \Webklex\PHPIMAP\Support\Masks\AttachmentMask::class + ] +]; diff --git a/htdocs/includes/Webklex/php-imap/tests/InitialTest.php b/htdocs/includes/Webklex/php-imap/tests/InitialTest.php new file mode 100644 index 00000000000..fb854db4ad0 --- /dev/null +++ b/htdocs/includes/Webklex/php-imap/tests/InitialTest.php @@ -0,0 +1,26 @@ +cm = new ClientManager(); + } + + public function testConfigDefaultAccount() { + $this->assertEquals("default", ClientManager::get("default")); + } +} \ No newline at end of file From a3cf76cfd7d21d1148b0d457e34f405aed7bbd84 Mon Sep 17 00:00:00 2001 From: jpb Date: Thu, 4 Aug 2022 15:43:14 +0200 Subject: [PATCH 448/826] add token to link --- htdocs/mrp/mo_production.php | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/htdocs/mrp/mo_production.php b/htdocs/mrp/mo_production.php index f6aba7f2597..65019337b64 100644 --- a/htdocs/mrp/mo_production.php +++ b/htdocs/mrp/mo_production.php @@ -39,7 +39,7 @@ dol_include_once('/mrp/lib/mrp_mo.lib.php'); // Load translation files required by the page $langs->loadLangs(array("mrp", "stocks", "other", "product", "productbatch")); - +$newToken = function_exists('newToken') ? newToken() : $_SESSION['newtoken']; // Get parameters $id = GETPOST('id', 'int'); $ref = GETPOST('ref', 'alpha'); @@ -257,6 +257,7 @@ if (empty($reshook)) { // Process line to produce $pos = 0; + foreach ($object->lines as $line) { if ($line->role == 'toproduce') { $tmpproduct = new Product($db); @@ -588,7 +589,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea if ($object->status == $object::STATUS_DRAFT) { if ($permissiontoadd) { if (empty($object->table_element_line) || (is_array($object->lines) && count($object->lines) > 0)) { - print ''.$langs->trans("Validate").''; + print ''.$langs->trans("Validate").''; } else { $langs->load("errors"); print ''.$langs->trans("Validate").''; @@ -599,7 +600,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea // Consume or produce if ($object->status == Mo::STATUS_VALIDATED || $object->status == Mo::STATUS_INPROGRESS) { if ($permissiontoproduce) { - print ''.$langs->trans('ConsumeOrProduce').''; + print ''.$langs->trans('ConsumeOrProduce').''; } else { print ''.$langs->trans('ConsumeOrProduce').''; } @@ -610,7 +611,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea // ConsumeAndProduceAll if ($object->status == Mo::STATUS_VALIDATED || $object->status == Mo::STATUS_INPROGRESS) { if ($permissiontoproduce) { - print ''.$langs->trans('ConsumeAndProduceAll').''; + print ''.$langs->trans('ConsumeAndProduceAll').''; } else { print ''.$langs->trans('ConsumeAndProduceAll').''; } @@ -627,21 +628,21 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $nbProduced += $lineproduced['qty']; } if ($nbProduced > 0) { // If production has started, we can close it - print ''.$langs->trans("Close").''."\n"; + print ''.$langs->trans("Close").''."\n"; } else { print 'transnoentitiesnoconv("Production")).'">'.$langs->trans("Close").''."\n"; } - print ''.$langs->trans("Cancel").''."\n"; + print ''.$langs->trans("Cancel").''."\n"; } if ($object->status == $object::STATUS_CANCELED) { - print ''.$langs->trans("Re-Open").''."\n"; + print ''.$langs->trans("Re-Open").''."\n"; } if ($object->status == $object::STATUS_PRODUCED) { if ($permissiontoproduce) { - print ''.$langs->trans('ReOpen').''; + print ''.$langs->trans('ReOpen').''; } else { print ''.$langs->trans('ReOpen').''; } From 4a9c9a97e503b8e846f1c19352718bc47003c15e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 4 Aug 2022 15:58:00 +0200 Subject: [PATCH 449/826] WIP Implement a generic handler for OAuth. --- htdocs/admin/oauth.php | 61 +++++- htdocs/admin/oauthlogintokens.php | 71 ++++--- htdocs/core/lib/oauth.lib.php | 29 ++- .../modules/oauth/generic_oauthcallback.php | 193 ++++++++++++++++++ .../modules/oauth/github_oauthcallback.php | 4 +- .../modules/oauth/google_oauthcallback.php | 2 +- .../oauth/stripelive_oauthcallback.php | 2 +- .../oauth/stripetest_oauthcallback.php | 2 +- htdocs/langs/en_US/oauth.lang | 7 +- 9 files changed, 320 insertions(+), 51 deletions(-) create mode 100644 htdocs/core/modules/oauth/generic_oauthcallback.php diff --git a/htdocs/admin/oauth.php b/htdocs/admin/oauth.php index 772055f0809..ade561c4ef1 100644 --- a/htdocs/admin/oauth.php +++ b/htdocs/admin/oauth.php @@ -62,7 +62,7 @@ if ($action == 'add') { // $provider is OAUTH_XXX setEventMessages($langs->trans("AOAuthEntryForThisProviderAndLabelAlreadyHasAKey"), null, 'errors'); $error++; } else { - dolibarr_set_const($db, $constname, 'ToComplete', 'chaine', 0, '', $conf->entity); + dolibarr_set_const($db, $constname, $langs->trans('ToComplete'), 'chaine', 0, '', $conf->entity); setEventMessages($langs->trans("OAuthProviderAdded"), null); } } @@ -78,6 +78,16 @@ if ($action == 'update') { if (!dolibarr_set_const($db, $constvalue.'_SECRET', GETPOST($constvalue.'_ID') ? GETPOST($constvalue.'_SECRET') : '', 'chaine', 0, '', $conf->entity)) { $error++; } + if (GETPOSTISSET($constvalue.'_URLAUTHORIZE')) { + if (!dolibarr_set_const($db, $constvalue.'_URLAUTHORIZE', GETPOST($constvalue.'_URLAUTHORIZE'), 'chaine', 0, '', $conf->entity)) { + $error++; + } + } + if (GETPOSTISSET($constvalue.'_SCOPE')) { + if (!dolibarr_set_const($db, $constvalue.'_SCOPE', GETPOST($constvalue.'_SCOPE'), 'chaine', 0, '', $conf->entity)) { + $error++; + } + } } } @@ -147,11 +157,17 @@ print ''; $i = 0; -//var_dump($list); +// Define $listinsetup foreach ($conf->global as $key => $val) { if (!empty($val) && preg_match('/^OAUTH_.*_ID$/', $key)) { $provider = preg_replace('/_ID$/', '', $key); - $listinsetup[] = array($provider.'_NAME', $provider.'_ID', $provider.'_SECRET', 'OAUTH Provider '.str_replace('OAUTH_', '', $provider)); + $listinsetup[] = array( + $provider.'_NAME', + $provider.'_ID', + $provider.'_SECRET', + $provider.'_URLAUTHORIZE', // For custom oauth links + $provider.'_SCOPE' // For custom oauth links + ); } } @@ -178,12 +194,16 @@ foreach ($listinsetup as $key) { $i++; - print ''; // Api Name $label = $langs->trans($keyforsupportedoauth2array); + print ''; print ''; print ''; - print ''; + + if ($keyforsupportedoauth2array == 'OAUTH_OTHER_NAME') { + print ''; + print ''; + print ''; + } } else { print ''; print ''; @@ -213,14 +240,32 @@ foreach ($listinsetup as $key) { // Api Id print ''; print ''; - print ''; // Api Secret print ''; print ''; - print ''; + + // TODO Move this into token generation + if ($supported) { + if ($keyforsupportedoauth2array == 'OAUTH_OTHER_NAME') { + print ''; + print ''; + print ''; + } else { + print ''; + print ''; + print ''; + } + } } print '
'; print img_picto('', $supportedoauth2array[$keyforsupportedoauth2array]['picto'], 'class="pictofixedwidth"'); - print $label; + if ($label == $keyforsupportedoauth2array) { + print $supportedoauth2array[$keyforsupportedoauth2array]['name']; + } else { + print $label; + } if ($keyforprovider) { print ' ('.$keyforprovider.')'; } else { @@ -201,8 +221,15 @@ foreach ($listinsetup as $key) { $redirect_uri = $urlwithroot.'/core/modules/oauth/'.$supportedoauth2array[$keyforsupportedoauth2array]['callbackfile'].'_oauthcallback.php'; print '
'.$langs->trans("UseTheFollowingUrlAsRedirectURI").''; + print ''; print '
'.$langs->trans("URLOfServiceForAuthorization").''; + print '
'.$langs->trans("UseTheFollowingUrlAsRedirectURI").'
'; + print ''; print '
'; + print ''; print '
'.$langs->trans("Scopes").''; + print ''; + print '
'.$langs->trans("Scopes").''; + //print ''; + print $supportedoauth2array[$keyforsupportedoauth2array]['defaultscope']; + print '
'."\n"; diff --git a/htdocs/admin/oauthlogintokens.php b/htdocs/admin/oauthlogintokens.php index b2830f95743..00daaf01e27 100644 --- a/htdocs/admin/oauthlogintokens.php +++ b/htdocs/admin/oauthlogintokens.php @@ -138,11 +138,17 @@ if (GETPOST('error')) { if ($mode == 'setup' && $user->admin) { print ''.$langs->trans("OAuthSetupForLogin")."

\n"; - //var_dump($list); + // Define $listinsetup foreach ($conf->global as $key => $val) { if (!empty($val) && preg_match('/^OAUTH_.*_ID$/', $key)) { $provider = preg_replace('/_ID$/', '', $key); - $listinsetup[] = array($provider.'_NAME', $provider.'_ID', $provider.'_SECRET', 'OAUTH Provider '.str_replace('OAUTH_', '', $provider)); + $listinsetup[] = array( + $provider.'_NAME', + $provider.'_ID', + $provider.'_SECRET', + $provider.'_URLAUTHORIZE', // For custom oauth links + $provider.'_SCOPE' // For custom oauth links + ); } } @@ -165,46 +171,39 @@ if ($mode == 'setup' && $user->admin) { $OAUTH_SERVICENAME = (empty($supportedoauth2array[$keyforsupportedoauth2array]['name']) ? 'Unknown' : $supportedoauth2array[$keyforsupportedoauth2array]['name'].($keyforprovider ? '-'.$keyforprovider : '')); - // Define $shortscope, $urltorenew, $urltodelete, $urltocheckperms + $shortscope = $supportedoauth2array[$keyforsupportedoauth2array]['defaultscope']; + if (getDolGlobalString($key[4])) { + $shortscope = getDolGlobalString($key[4]); + } + $state = $shortscope; // TODO USe a better state + + // Define $urltorenew, $urltodelete, $urltocheckperms // TODO Use array $supportedoauth2array if ($keyforsupportedoauth2array == 'OAUTH_GITHUB_NAME') { // List of keys that will be converted into scopes (from constants 'SCOPE_state_in_uppercase' in file of service). // We pass this param list in to 'state' because we need it before and after the redirect. - $shortscope = 'user,public_repo'; - // Note: github does not accept csrf key inside the state parameter (only know values) - $urltorenew = $urlwithroot.'/core/modules/oauth/github_oauthcallback.php?shortscope='.$shortscope.'&state='.$shortscope.'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); + // Note: github does not accept csrf key inside the state parameter (only known values) + $urltorenew = $urlwithroot.'/core/modules/oauth/github_oauthcallback.php?shortscope='.urlencode($shortscope).'&state='.$shortscope.'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); $urltodelete = $urlwithroot.'/core/modules/oauth/github_oauthcallback.php?action=delete&token='.newToken().'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); $urltocheckperms = 'https://github.com/settings/applications/'; } elseif ($keyforsupportedoauth2array == 'OAUTH_GOOGLE_NAME') { // List of keys that will be converted into scopes (from constants 'SCOPE_state_in_uppercase' in file of service). // List of scopes for Google are here: https://developers.google.com/identity/protocols/oauth2/scopes // We pass this key list into the param 'state' because we need it before and after the redirect. - $shortscope = 'userinfo_email,userinfo_profile'; - $shortscope .= ',openid,email,profile'; // For openid connect - if (!empty($conf->printing->enabled)) { - $shortscope .= ',cloud_print'; - } - if (!empty($conf->global->OAUTH_GOOGLE_GSUITE)) { - $shortscope .= ',admin_directory_user'; - } - if (!empty($conf->global->OAUTH_GOOGLE_GMAIL)) { - $shortscope.=',gmail_full'; - } - - $urltorenew = $urlwithroot.'/core/modules/oauth/google_oauthcallback.php?shortscope='.$shortscope.'&state='.$shortscope.'-'.$oauthstateanticsrf.'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); + $urltorenew = $urlwithroot.'/core/modules/oauth/google_oauthcallback.php?shortscope='.urlencode($shortscope).'&state='.urlencode($state).'-'.$oauthstateanticsrf.'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); $urltodelete = $urlwithroot.'/core/modules/oauth/google_oauthcallback.php?action=delete&token='.newToken().'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); $urltocheckperms = 'https://security.google.com/settings/security/permissions'; } elseif ($keyforsupportedoauth2array == 'OAUTH_STRIPE_TEST_NAME') { - $shortscope = 'none'; - - $urltorenew = $urlwithroot.'/core/modules/oauth/stripetest_oauthcallback.php?backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); + $urltorenew = $urlwithroot.'/core/modules/oauth/stripetest_oauthcallback.php?shortscope='.urlencode($shortscope).'&state='.urlencode($state).'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); $urltodelete = ''; $urltocheckperms = ''; } elseif ($keyforsupportedoauth2array == 'OAUTH_STRIPE_LIVE_NAME') { - $shortscope = 'none'; - - $urltorenew = $urlwithroot.'/core/modules/oauth/stripelive_oauthcallback.php?backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); + $urltorenew = $urlwithroot.'/core/modules/oauth/stripelive_oauthcallback.php?shortscope='.urlencode($shortscope).'&state='.urlencode($state).'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); + $urltodelete = ''; + $urltocheckperms = ''; + } elseif ($keyforsupportedoauth2array = 'OAUTH_OTHER_NAME') { + $urltorenew = $urlwithroot.'/core/modules/oauth/generic_oauthcallback.php?shortscope='.urlencode($shortscope).'&state='.urlencode($state).'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); $urltodelete = ''; $urltocheckperms = ''; } else { @@ -212,7 +211,8 @@ if ($mode == 'setup' && $user->admin) { $urltodelete = ''; $urltocheckperms = ''; } - $urltorenew .= '&keyforprovider='.$keyforprovider; + + $urltorenew .= '&keyforprovider='.urlencode($keyforprovider); // Show value of token $tokenobj = null; @@ -246,7 +246,7 @@ if ($mode == 'setup' && $user->admin) { } elseif ($endoflife == $tokenobj::EOL_UNKNOWN) { $expiredat = $langs->trans("Unknown"); } else { - $expiredat = dol_print_date($endoflife, "dayhour"); + $expiredat = dol_print_date($endoflife, "dayhour", 'tzuserrel'); } } } @@ -260,10 +260,16 @@ if ($mode == 'setup' && $user->admin) { print '
'; print ''."\n"; + // Api Name + $label = $langs->trans($keyforsupportedoauth2array); print ''; print '",i.document[0]).appendTo(t)):"tr"===n?i._createTrPlaceholder(i.currentItem,t):"img"===n&&t.attr("src",i.currentItem.attr("src")),s||t.css("visibility","hidden"),t},update:function(t,e){s&&!o.forcePlaceholderSize||(e.height()&&(!o.forcePlaceholderSize||"tbody"!==n&&"tr"!==n)||e.height(i.currentItem.innerHeight()-parseInt(i.currentItem.css("paddingTop")||0,10)-parseInt(i.currentItem.css("paddingBottom")||0,10)),e.width()||e.width(i.currentItem.innerWidth()-parseInt(i.currentItem.css("paddingLeft")||0,10)-parseInt(i.currentItem.css("paddingRight")||0,10)))}}),i.placeholder=V(o.placeholder.element.call(i.element,i.currentItem)),i.currentItem.after(i.placeholder),o.placeholder.update(i,i.placeholder)},_createTrPlaceholder:function(t,e){var i=this;t.children().each(function(){V("",i.document[0]).attr("colspan",V(this).attr("colspan")||1).appendTo(e)})},_contactContainers:function(t){for(var e,i,s,n,o,a,r,l,h,c=null,u=null,d=this.containers.length-1;0<=d;d--)V.contains(this.currentItem[0],this.containers[d].element[0])||(this._intersectsWith(this.containers[d].containerCache)?c&&V.contains(this.containers[d].element[0],c.element[0])||(c=this.containers[d],u=d):this.containers[d].containerCache.over&&(this.containers[d]._trigger("out",t,this._uiHash(this)),this.containers[d].containerCache.over=0));if(c)if(1===this.containers.length)this.containers[u].containerCache.over||(this.containers[u]._trigger("over",t,this._uiHash(this)),this.containers[u].containerCache.over=1);else{for(i=1e4,s=null,n=(l=c.floating||this._isFloating(this.currentItem))?"left":"top",o=l?"width":"height",h=l?"pageX":"pageY",e=this.items.length-1;0<=e;e--)V.contains(this.containers[u].element[0],this.items[e].item[0])&&this.items[e].item[0]!==this.currentItem[0]&&(a=this.items[e].item.offset()[n],r=!1,t[h]-a>this.items[e][o]/2&&(r=!0),Math.abs(t[h]-a)this.containment[2]&&(i=this.containment[2]+this.offset.click.left),t.pageY-this.offset.click.top>this.containment[3]&&(s=this.containment[3]+this.offset.click.top)),e.grid&&(t=this.originalPageY+Math.round((s-this.originalPageY)/e.grid[1])*e.grid[1],s=!this.containment||t-this.offset.click.top>=this.containment[1]&&t-this.offset.click.top<=this.containment[3]?t:t-this.offset.click.top>=this.containment[1]?t-e.grid[1]:t+e.grid[1],t=this.originalPageX+Math.round((i-this.originalPageX)/e.grid[0])*e.grid[0],i=!this.containment||t-this.offset.click.left>=this.containment[0]&&t-this.offset.click.left<=this.containment[2]?t:t-this.offset.click.left>=this.containment[0]?t-e.grid[0]:t+e.grid[0])),{top:s-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():o?0:n.scrollTop()),left:i-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():o?0:n.scrollLeft())}},_rearrange:function(t,e,i,s){i?i[0].appendChild(this.placeholder[0]):e.item[0].parentNode.insertBefore(this.placeholder[0],"down"===this.direction?e.item[0]:e.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var n=this.counter;this._delay(function(){n===this.counter&&this.refreshPositions(!s)})},_clear:function(t,e){this.reverting=!1;var i,s=[];if(!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null,this.helper[0]===this.currentItem[0]){for(i in this._storedCSS)"auto"!==this._storedCSS[i]&&"static"!==this._storedCSS[i]||(this._storedCSS[i]="");this.currentItem.css(this._storedCSS),this._removeClass(this.currentItem,"ui-sortable-helper")}else this.currentItem.show();function n(e,i,s){return function(t){s._trigger(e,t,i._uiHash(i))}}for(this.fromOutside&&!e&&s.push(function(t){this._trigger("receive",t,this._uiHash(this.fromOutside))}),!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(".ui-sortable-helper")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||e||s.push(function(t){this._trigger("update",t,this._uiHash())}),this!==this.currentContainer&&(e||(s.push(function(t){this._trigger("remove",t,this._uiHash())}),s.push(function(e){return function(t){e._trigger("receive",t,this._uiHash(this))}}.call(this,this.currentContainer)),s.push(function(e){return function(t){e._trigger("update",t,this._uiHash(this))}}.call(this,this.currentContainer)))),i=this.containers.length-1;0<=i;i--)e||s.push(n("deactivate",this,this.containers[i])),this.containers[i].containerCache.over&&(s.push(n("out",this,this.containers[i])),this.containers[i].containerCache.over=0);if(this.storedCursor&&(this.document.find("body").css("cursor",this.storedCursor),this.storedStylesheet.remove()),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex","auto"===this._storedZIndex?"":this._storedZIndex),this.dragging=!1,e||this._trigger("beforeStop",t,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.cancelHelperRemoval||(this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null),!e){for(i=0;i",widgetEventPrefix:"spin",options:{classes:{"ui-spinner":"ui-corner-all","ui-spinner-down":"ui-corner-br","ui-spinner-up":"ui-corner-tr"},culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),""!==this.value()&&this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var s=this._super(),n=this.element;return V.each(["min","max","step"],function(t,e){var i=n.attr(e);null!=i&&i.length&&(s[e]=i)}),s},_events:{keydown:function(t){this._start(t)&&this._keydown(t)&&t.preventDefault()},keyup:"_stop",focus:function(){this.previous=this.element.val()},blur:function(t){this.cancelBlur?delete this.cancelBlur:(this._stop(),this._refresh(),this.previous!==this.element.val()&&this._trigger("change",t))},mousewheel:function(t,e){var i=V.ui.safeActiveElement(this.document[0]);if(this.element[0]===i&&e){if(!this.spinning&&!this._start(t))return!1;this._spin((0").parent().append("")},_draw:function(){this._enhance(),this._addClass(this.uiSpinner,"ui-spinner","ui-widget ui-widget-content"),this._addClass("ui-spinner-input"),this.element.attr("role","spinbutton"),this.buttons=this.uiSpinner.children("a").attr("tabIndex",-1).attr("aria-hidden",!0).button({classes:{"ui-button":""}}),this._removeClass(this.buttons,"ui-corner-all"),this._addClass(this.buttons.first(),"ui-spinner-button ui-spinner-up"),this._addClass(this.buttons.last(),"ui-spinner-button ui-spinner-down"),this.buttons.first().button({icon:this.options.icons.up,showLabel:!1}),this.buttons.last().button({icon:this.options.icons.down,showLabel:!1}),this.buttons.height()>Math.ceil(.5*this.uiSpinner.height())&&0e.max?e.max:null!==e.min&&t"},_buttonHtml:function(){return""}});var ct;V.ui.spinner;V.widget("ui.tabs",{version:"1.13.2",delay:300,options:{active:null,classes:{"ui-tabs":"ui-corner-all","ui-tabs-nav":"ui-corner-all","ui-tabs-panel":"ui-corner-bottom","ui-tabs-tab":"ui-corner-top"},collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_isLocal:(ct=/#.*$/,function(t){var e=t.href.replace(ct,""),i=location.href.replace(ct,"");try{e=decodeURIComponent(e)}catch(t){}try{i=decodeURIComponent(i)}catch(t){}return 1?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var t=this.options,e=this.tablist.children(":has(a[href])");t.disabled=V.map(e.filter(".ui-state-disabled"),function(t){return e.index(t)}),this._processTabs(),!1!==t.active&&this.anchors.length?this.active.length&&!V.contains(this.tablist[0],this.active[0])?this.tabs.length===t.disabled.length?(t.active=!1,this.active=V()):this._activate(this._findNextTab(Math.max(0,t.active-1),!1)):t.active=this.tabs.index(this.active):(t.active=!1,this.active=V()),this._refresh()},_refresh:function(){this._setOptionDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-hidden":"true"}),this.active.length?(this.active.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}),this._addClass(this.active,"ui-tabs-active","ui-state-active"),this._getPanelForTab(this.active).show().attr({"aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var l=this,t=this.tabs,e=this.anchors,i=this.panels;this.tablist=this._getList().attr("role","tablist"),this._addClass(this.tablist,"ui-tabs-nav","ui-helper-reset ui-helper-clearfix ui-widget-header"),this.tablist.on("mousedown"+this.eventNamespace,"> li",function(t){V(this).is(".ui-state-disabled")&&t.preventDefault()}).on("focus"+this.eventNamespace,".ui-tabs-anchor",function(){V(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this.tabs=this.tablist.find("> li:has(a[href])").attr({role:"tab",tabIndex:-1}),this._addClass(this.tabs,"ui-tabs-tab","ui-state-default"),this.anchors=this.tabs.map(function(){return V("a",this)[0]}).attr({tabIndex:-1}),this._addClass(this.anchors,"ui-tabs-anchor"),this.panels=V(),this.anchors.each(function(t,e){var i,s,n,o=V(e).uniqueId().attr("id"),a=V(e).closest("li"),r=a.attr("aria-controls");l._isLocal(e)?(n=(i=e.hash).substring(1),s=l.element.find(l._sanitizeSelector(i))):(n=a.attr("aria-controls")||V({}).uniqueId()[0].id,(s=l.element.find(i="#"+n)).length||(s=l._createPanel(n)).insertAfter(l.panels[t-1]||l.tablist),s.attr("aria-live","polite")),s.length&&(l.panels=l.panels.add(s)),r&&a.data("ui-tabs-aria-controls",r),a.attr({"aria-controls":n,"aria-labelledby":o}),s.attr("aria-labelledby",o)}),this.panels.attr("role","tabpanel"),this._addClass(this.panels,"ui-tabs-panel","ui-widget-content"),t&&(this._off(t.not(this.tabs)),this._off(e.not(this.anchors)),this._off(i.not(this.panels)))},_getList:function(){return this.tablist||this.element.find("ol, ul").eq(0)},_createPanel:function(t){return V("
").attr("id",t).data("ui-tabs-destroy",!0)},_setOptionDisabled:function(t){var e,i;for(Array.isArray(t)&&(t.length?t.length===this.anchors.length&&(t=!0):t=!1),i=0;e=this.tabs[i];i++)e=V(e),!0===t||-1!==V.inArray(i,t)?(e.attr("aria-disabled","true"),this._addClass(e,null,"ui-state-disabled")):(e.removeAttr("aria-disabled"),this._removeClass(e,null,"ui-state-disabled"));this.options.disabled=t,this._toggleClass(this.widget(),this.widgetFullName+"-disabled",null,!0===t)},_setupEvents:function(t){var i={};t&&V.each(t.split(" "),function(t,e){i[e]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(!0,this.anchors,{click:function(t){t.preventDefault()}}),this._on(this.anchors,i),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(t){var i,e=this.element.parent();"fill"===t?(i=e.height(),i-=this.element.outerHeight()-this.element.height(),this.element.siblings(":visible").each(function(){var t=V(this),e=t.css("position");"absolute"!==e&&"fixed"!==e&&(i-=t.outerHeight(!0))}),this.element.children().not(this.panels).each(function(){i-=V(this).outerHeight(!0)}),this.panels.each(function(){V(this).height(Math.max(0,i-V(this).innerHeight()+V(this).height()))}).css("overflow","auto")):"auto"===t&&(i=0,this.panels.each(function(){i=Math.max(i,V(this).height("").height())}).height(i))},_eventHandler:function(t){var e=this.options,i=this.active,s=V(t.currentTarget).closest("li"),n=s[0]===i[0],o=n&&e.collapsible,a=o?V():this._getPanelForTab(s),r=i.length?this._getPanelForTab(i):V(),i={oldTab:i,oldPanel:r,newTab:o?V():s,newPanel:a};t.preventDefault(),s.hasClass("ui-state-disabled")||s.hasClass("ui-tabs-loading")||this.running||n&&!e.collapsible||!1===this._trigger("beforeActivate",t,i)||(e.active=!o&&this.tabs.index(s),this.active=n?V():s,this.xhr&&this.xhr.abort(),r.length||a.length||V.error("jQuery UI Tabs: Mismatching fragment identifier."),a.length&&this.load(this.tabs.index(s),t),this._toggle(t,i))},_toggle:function(t,e){var i=this,s=e.newPanel,n=e.oldPanel;function o(){i.running=!1,i._trigger("activate",t,e)}function a(){i._addClass(e.newTab.closest("li"),"ui-tabs-active","ui-state-active"),s.length&&i.options.show?i._show(s,i.options.show,o):(s.show(),o())}this.running=!0,n.length&&this.options.hide?this._hide(n,this.options.hide,function(){i._removeClass(e.oldTab.closest("li"),"ui-tabs-active","ui-state-active"),a()}):(this._removeClass(e.oldTab.closest("li"),"ui-tabs-active","ui-state-active"),n.hide(),a()),n.attr("aria-hidden","true"),e.oldTab.attr({"aria-selected":"false","aria-expanded":"false"}),s.length&&n.length?e.oldTab.attr("tabIndex",-1):s.length&&this.tabs.filter(function(){return 0===V(this).attr("tabIndex")}).attr("tabIndex",-1),s.attr("aria-hidden","false"),e.newTab.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0})},_activate:function(t){var t=this._findActive(t);t[0]!==this.active[0]&&(t=(t=!t.length?this.active:t).find(".ui-tabs-anchor")[0],this._eventHandler({target:t,currentTarget:t,preventDefault:V.noop}))},_findActive:function(t){return!1===t?V():this.tabs.eq(t)},_getIndex:function(t){return t="string"==typeof t?this.anchors.index(this.anchors.filter("[href$='"+V.escapeSelector(t)+"']")):t},_destroy:function(){this.xhr&&this.xhr.abort(),this.tablist.removeAttr("role").off(this.eventNamespace),this.anchors.removeAttr("role tabIndex").removeUniqueId(),this.tabs.add(this.panels).each(function(){V.data(this,"ui-tabs-destroy")?V(this).remove():V(this).removeAttr("role tabIndex aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded")}),this.tabs.each(function(){var t=V(this),e=t.data("ui-tabs-aria-controls");e?t.attr("aria-controls",e).removeData("ui-tabs-aria-controls"):t.removeAttr("aria-controls")}),this.panels.show(),"content"!==this.options.heightStyle&&this.panels.css("height","")},enable:function(i){var t=this.options.disabled;!1!==t&&(t=void 0!==i&&(i=this._getIndex(i),Array.isArray(t)?V.map(t,function(t){return t!==i?t:null}):V.map(this.tabs,function(t,e){return e!==i?e:null})),this._setOptionDisabled(t))},disable:function(t){var e=this.options.disabled;if(!0!==e){if(void 0===t)e=!0;else{if(t=this._getIndex(t),-1!==V.inArray(t,e))return;e=Array.isArray(e)?V.merge([t],e).sort():[t]}this._setOptionDisabled(e)}},load:function(t,s){t=this._getIndex(t);function n(t,e){"abort"===e&&o.panels.stop(!1,!0),o._removeClass(i,"ui-tabs-loading"),a.removeAttr("aria-busy"),t===o.xhr&&delete o.xhr}var o=this,i=this.tabs.eq(t),t=i.find(".ui-tabs-anchor"),a=this._getPanelForTab(i),r={tab:i,panel:a};this._isLocal(t[0])||(this.xhr=V.ajax(this._ajaxSettings(t,s,r)),this.xhr&&"canceled"!==this.xhr.statusText&&(this._addClass(i,"ui-tabs-loading"),a.attr("aria-busy","true"),this.xhr.done(function(t,e,i){setTimeout(function(){a.html(t),o._trigger("load",s,r),n(i,e)},1)}).fail(function(t,e){setTimeout(function(){n(t,e)},1)})))},_ajaxSettings:function(t,i,s){var n=this;return{url:t.attr("href").replace(/#.*$/,""),beforeSend:function(t,e){return n._trigger("beforeLoad",i,V.extend({jqXHR:t,ajaxSettings:e},s))}}},_getPanelForTab:function(t){t=V(t).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+t))}}),!1!==V.uiBackCompat&&V.widget("ui.tabs",V.ui.tabs,{_processTabs:function(){this._superApply(arguments),this._addClass(this.tabs,"ui-tab")}});V.ui.tabs;V.widget("ui.tooltip",{version:"1.13.2",options:{classes:{"ui-tooltip":"ui-corner-all ui-widget-shadow"},content:function(){var t=V(this).attr("title");return V("").text(t).html()},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,track:!1,close:null,open:null},_addDescribedBy:function(t,e){var i=(t.attr("aria-describedby")||"").split(/\s+/);i.push(e),t.data("ui-tooltip-id",e).attr("aria-describedby",String.prototype.trim.call(i.join(" ")))},_removeDescribedBy:function(t){var e=t.data("ui-tooltip-id"),i=(t.attr("aria-describedby")||"").split(/\s+/),e=V.inArray(e,i);-1!==e&&i.splice(e,1),t.removeData("ui-tooltip-id"),(i=String.prototype.trim.call(i.join(" ")))?t.attr("aria-describedby",i):t.removeAttr("aria-describedby")},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.liveRegion=V("
").attr({role:"log","aria-live":"assertive","aria-relevant":"additions"}).appendTo(this.document[0].body),this._addClass(this.liveRegion,null,"ui-helper-hidden-accessible"),this.disabledTitles=V([])},_setOption:function(t,e){var i=this;this._super(t,e),"content"===t&&V.each(this.tooltips,function(t,e){i._updateContent(e.element)})},_setOptionDisabled:function(t){this[t?"_disable":"_enable"]()},_disable:function(){var s=this;V.each(this.tooltips,function(t,e){var i=V.Event("blur");i.target=i.currentTarget=e.element[0],s.close(i,!0)}),this.disabledTitles=this.disabledTitles.add(this.element.find(this.options.items).addBack().filter(function(){var t=V(this);if(t.is("[title]"))return t.data("ui-tooltip-title",t.attr("title")).removeAttr("title")}))},_enable:function(){this.disabledTitles.each(function(){var t=V(this);t.data("ui-tooltip-title")&&t.attr("title",t.data("ui-tooltip-title"))}),this.disabledTitles=V([])},open:function(t){var i=this,e=V(t?t.target:this.element).closest(this.options.items);e.length&&!e.data("ui-tooltip-id")&&(e.attr("title")&&e.data("ui-tooltip-title",e.attr("title")),e.data("ui-tooltip-open",!0),t&&"mouseover"===t.type&&e.parents().each(function(){var t,e=V(this);e.data("ui-tooltip-open")&&((t=V.Event("blur")).target=t.currentTarget=this,i.close(t,!0)),e.attr("title")&&(e.uniqueId(),i.parents[this.id]={element:this,title:e.attr("title")},e.attr("title",""))}),this._registerCloseHandlers(t,e),this._updateContent(e,t))},_updateContent:function(e,i){var t=this.options.content,s=this,n=i?i.type:null;if("string"==typeof t||t.nodeType||t.jquery)return this._open(i,e,t);(t=t.call(e[0],function(t){s._delay(function(){e.data("ui-tooltip-open")&&(i&&(i.type=n),this._open(i,e,t))})}))&&this._open(i,e,t)},_open:function(t,e,i){var s,n,o,a=V.extend({},this.options.position);function r(t){a.of=t,n.is(":hidden")||n.position(a)}i&&((s=this._find(e))?s.tooltip.find(".ui-tooltip-content").html(i):(e.is("[title]")&&(t&&"mouseover"===t.type?e.attr("title",""):e.removeAttr("title")),s=this._tooltip(e),n=s.tooltip,this._addDescribedBy(e,n.attr("id")),n.find(".ui-tooltip-content").html(i),this.liveRegion.children().hide(),(i=V("
").html(n.find(".ui-tooltip-content").html())).removeAttr("name").find("[name]").removeAttr("name"),i.removeAttr("id").find("[id]").removeAttr("id"),i.appendTo(this.liveRegion),this.options.track&&t&&/^mouse/.test(t.type)?(this._on(this.document,{mousemove:r}),r(t)):n.position(V.extend({of:e},this.options.position)),n.hide(),this._show(n,this.options.show),this.options.track&&this.options.show&&this.options.show.delay&&(o=this.delayedShow=setInterval(function(){n.is(":visible")&&(r(a.of),clearInterval(o))},13)),this._trigger("open",t,{tooltip:n})))},_registerCloseHandlers:function(t,e){var i={keyup:function(t){t.keyCode===V.ui.keyCode.ESCAPE&&((t=V.Event(t)).currentTarget=e[0],this.close(t,!0))}};e[0]!==this.element[0]&&(i.remove=function(){var t=this._find(e);t&&this._removeTooltip(t.tooltip)}),t&&"mouseover"!==t.type||(i.mouseleave="close"),t&&"focusin"!==t.type||(i.focusout="close"),this._on(!0,e,i)},close:function(t){var e,i=this,s=V(t?t.currentTarget:this.element),n=this._find(s);n?(e=n.tooltip,n.closing||(clearInterval(this.delayedShow),s.data("ui-tooltip-title")&&!s.attr("title")&&s.attr("title",s.data("ui-tooltip-title")),this._removeDescribedBy(s),n.hiding=!0,e.stop(!0),this._hide(e,this.options.hide,function(){i._removeTooltip(V(this))}),s.removeData("ui-tooltip-open"),this._off(s,"mouseleave focusout keyup"),s[0]!==this.element[0]&&this._off(s,"remove"),this._off(this.document,"mousemove"),t&&"mouseleave"===t.type&&V.each(this.parents,function(t,e){V(e.element).attr("title",e.title),delete i.parents[t]}),n.closing=!0,this._trigger("close",t,{tooltip:e}),n.hiding||(n.closing=!1))):s.removeData("ui-tooltip-open")},_tooltip:function(t){var e=V("
").attr("role","tooltip"),i=V("
").appendTo(e),s=e.uniqueId().attr("id");return this._addClass(i,"ui-tooltip-content"),this._addClass(e,"ui-tooltip","ui-widget ui-widget-content"),e.appendTo(this._appendTo(t)),this.tooltips[s]={element:t,tooltip:e}},_find:function(t){t=t.data("ui-tooltip-id");return t?this.tooltips[t]:null},_removeTooltip:function(t){clearInterval(this.delayedShow),t.remove(),delete this.tooltips[t.attr("id")]},_appendTo:function(t){t=t.closest(".ui-front, dialog");return t=!t.length?this.document[0].body:t},_destroy:function(){var s=this;V.each(this.tooltips,function(t,e){var i=V.Event("blur"),e=e.element;i.target=i.currentTarget=e[0],s.close(i,!0),V("#"+t).remove(),e.data("ui-tooltip-title")&&(e.attr("title")||e.attr("title",e.data("ui-tooltip-title")),e.removeData("ui-tooltip-title"))}),this.liveRegion.remove()}}),!1!==V.uiBackCompat&&V.widget("ui.tooltip",V.ui.tooltip,{options:{tooltipClass:null},_tooltip:function(){var t=this._superApply(arguments);return this.options.tooltipClass&&t.tooltip.addClass(this.options.tooltipClass),t}});V.ui.tooltip}); \ No newline at end of file From cee88c0a61ea8cc6142588589db1c24d8574ccd9 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 10 Aug 2022 18:45:06 +0200 Subject: [PATCH 499/826] Fix missing header --- htdocs/compta/bank/card.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/htdocs/compta/bank/card.php b/htdocs/compta/bank/card.php index 2751947c023..3dfe18a3581 100644 --- a/htdocs/compta/bank/card.php +++ b/htdocs/compta/bank/card.php @@ -846,6 +846,9 @@ if ($action == 'create') { $object = new Account($db); $object->fetch(GETPOST('id', 'int')); + $title = $object->ref." - ".$langs->trans("Card"); + llxHeader("", $title, $help_url); + print load_fiche_titre($langs->trans("EditFinancialAccount"), '', 'bank_account'); if ($conf->use_javascript_ajax) { @@ -1014,7 +1017,7 @@ if ($action == 'create') { $tdextra = ' class="fieldrequired titlefieldcreate"'; } - print '
'.$langs->trans("AccountancyCode").''; + print ''.$langs->trans("AccountancyCode").''; print ' + + + + + + + + + + + + diff --git a/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/file.html.dist b/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/file.html.dist new file mode 100644 index 00000000000..59a06843018 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/file.html.dist @@ -0,0 +1,90 @@ + + + + + Code Coverage for {{full_path}} + + + + + + +
+
+
+
+ +
+
+
+
+
+
'; print img_picto('', $supportedoauth2array[$keyforsupportedoauth2array]['picto'], 'class="pictofixedwidth"'); - print $langs->trans($keyforsupportedoauth2array); + if ($label == $keyforsupportedoauth2array) { + print $supportedoauth2array[$keyforsupportedoauth2array]['name']; + } else { + print $label; + } if ($keyforprovider) { print ' ('.$keyforprovider.')'; } else { @@ -292,7 +298,8 @@ if ($mode == 'setup' && $user->admin) { print ''; print ''; if (is_object($tokenobj)) { - print $langs->trans("HasAccessToken"); + // TODO Read in database to get the date of creation of token + print $form->textwithpicto(yn(1), $langs->trans("HasAccessToken").' : '); } else { print ''.$langs->trans("NoAccessToken").''; } @@ -305,7 +312,9 @@ if ($mode == 'setup' && $user->admin) { } // Request remote token if ($urltorenew) { - print ''.$langs->trans('RequestAccess').'
'; + print ''.$langs->trans('GetAccess').''; + print $form->textwithpicto('', $langs->trans('RequestAccess')); + print '
'; } // Check remote access if ($urltocheckperms) { @@ -378,8 +387,8 @@ if ($mode == 'setup' && $user->admin) { } } - print ''; + print '
'; } } diff --git a/htdocs/core/lib/oauth.lib.php b/htdocs/core/lib/oauth.lib.php index f99266db178..bacd8135739 100644 --- a/htdocs/core/lib/oauth.lib.php +++ b/htdocs/core/lib/oauth.lib.php @@ -23,16 +23,30 @@ */ +$shortscopegoogle = 'userinfo_email,userinfo_profile'; +$shortscopegoogle .= ',openid,email,profile'; // For openid connect +if (!empty($conf->printing->enabled)) { + $shortscopegoogle .= ',cloud_print'; +} +if (!empty($conf->global->OAUTH_GOOGLE_GSUITE)) { + $shortscopegoogle .= ',admin_directory_user'; +} +if (!empty($conf->global->OAUTH_GOOGLE_GMAIL)) { + $shortscopegoogle.=',gmail_full'; +} + // Supported OAUTH (a provider is supported when a file xxx_oauthcallback.php is available into htdocs/core/modules/oauth) $supportedoauth2array = array( - 'OAUTH_GOOGLE_NAME'=>array('callbackfile' => 'google', 'picto' => 'google', 'urlforapp' => 'OAUTH_GOOGLE_DESC', 'name'=>'Google', 'urlforcredentials'=>'https://console.developers.google.com/'), + 'OAUTH_GOOGLE_NAME'=>array('callbackfile' => 'google', 'picto' => 'google', 'urlforapp' => 'OAUTH_GOOGLE_DESC', 'name'=>'Google', 'urlforcredentials'=>'https://console.developers.google.com/', 'defaultscope'=>$shortscopegoogle), ); if (!empty($conf->stripe->enabled)) { - $supportedoauth2array['OAUTH_STRIPE_TEST_NAME'] = array('callbackfile' => 'stripetest', 'picto' => 'stripe', 'urlforapp' => '', 'name'=>'StripeTest', 'urlforcredentials'=>''); - $supportedoauth2array['OAUTH_STRIPE_LIVE_NAME'] = array('callbackfile' => 'stripelive', 'picto' => 'stripe', 'urlforapp' => '', 'name'=>'StripeLive', 'urlforcredentials'=>''); + $supportedoauth2array['OAUTH_STRIPE_TEST_NAME'] = array('callbackfile' => 'stripetest', 'picto' => 'stripe', 'urlforapp' => '', 'name'=>'StripeTest', 'urlforcredentials'=>'', 'defaultscope'=>'read_write'); + $supportedoauth2array['OAUTH_STRIPE_LIVE_NAME'] = array('callbackfile' => 'stripelive', 'picto' => 'stripe', 'urlforapp' => '', 'name'=>'StripeLive', 'urlforcredentials'=>'', 'defaultscope'=>'read_write'); +} +$supportedoauth2array['OAUTH_GITHUB_NAME'] = array('callbackfile' => 'github', 'picto' => 'github', 'urlforapp' => 'OAUTH_GITHUB_DESC', 'name'=>'GitHub', 'urlforcredentials'=>'https://github.com/settings/developers', 'defaultscope'=>'user,public_repo'); +if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) { + $supportedoauth2array['OAUTH_OTHER_NAME'] = array('callbackfile' => 'generic', 'picto' => 'generic', 'urlforapp' => 'OAUTH_OTHER_DESC', 'name'=>'Other', 'urlforcredentials'=>'', 'defaultscope'=>'ToComplete'); } -$supportedoauth2array['OAUTH_GITHUB_NAME'] = array('callbackfile' => 'github', 'picto' => 'github', 'urlforapp' => 'OAUTH_GITHUB_DESC', 'name'=>'GitHub', 'urlforcredentials'=>'https://github.com/settings/developers'); - // API access parameters OAUTH @@ -259,6 +273,11 @@ $list = array( 'OAUTH_YAMMER_ID', 'OAUTH_YAMMER_SECRET', ), + array( + 'OAUTH_OTHER_NAME', + 'OAUTH_OTHER_ID', + 'OAUTH_OTHER_SECRET', + ), ); diff --git a/htdocs/core/modules/oauth/generic_oauthcallback.php b/htdocs/core/modules/oauth/generic_oauthcallback.php new file mode 100644 index 00000000000..9d66bb07302 --- /dev/null +++ b/htdocs/core/modules/oauth/generic_oauthcallback.php @@ -0,0 +1,193 @@ + + * Copyright (C) 2015 Frederic France + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/core/modules/oauth/generic_oauthcallback.php + * \ingroup oauth + * \brief Page to get oauth callback + */ + +require '../../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/includes/OAuth/bootstrap.php'; +use OAuth\Common\Storage\DoliStorage; +use OAuth\Common\Consumer\Credentials; +use OAuth\OAuth2\Service\GitHub; + +// Define $urlwithroot +$urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root)); +$urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file +//$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current + + +$action = GETPOST('action', 'aZ09'); +$backtourl = GETPOST('backtourl', 'alpha'); +$keyforprovider = GETPOST('keyforprovider', 'aZ09'); +if (empty($keyforprovider) && !empty($_SESSION["oauthkeyforproviderbeforeoauthjump"]) && (GETPOST('code') || $action == 'delete')) { + $keyforprovider = $_SESSION["oauthkeyforproviderbeforeoauthjump"]; +} +$genericstring = 'OTHER'; + + +/** + * Create a new instance of the URI class with the current URI, stripping the query string + */ +$uriFactory = new \OAuth\Common\Http\Uri\UriFactory(); +//$currentUri = $uriFactory->createFromSuperGlobalArray($_SERVER); +//$currentUri->setQuery(''); +$currentUri = $uriFactory->createFromAbsolute($urlwithroot.'/core/modules/oauth/generic_oauthcallback.php'); + + +/** + * Load the credential for the service + */ + +/** @var $serviceFactory \OAuth\ServiceFactory An OAuth service factory. */ +$serviceFactory = new \OAuth\ServiceFactory(); +$httpClient = new \OAuth\Common\Http\Client\CurlClient(); +// TODO Set options for proxy and timeout +// $params=array('CURLXXX'=>value, ...) +//$httpClient->setCurlParameters($params); +$serviceFactory->setHttpClient($httpClient); + +// Dolibarr storage +$storage = new DoliStorage($db, $conf); + +// Setup the credentials for the requests +$keyforparamid = 'OAUTH_'.$genericstring.($keyforprovider ? '-'.$keyforprovider : '').'_ID'; +$keyforparamsecret = 'OAUTH_'.$genericstring.($keyforprovider ? '-'.$keyforprovider : '').'_SECRET'; +$credentials = new Credentials( + getDolGlobalString($keyforparamid), + getDolGlobalString($keyforparamsecret), + $currentUri->getAbsoluteUri() +); + +$requestedpermissionsarray = array(); +if (GETPOST('state')) { + $requestedpermissionsarray = explode(',', GETPOST('state')); // Example: 'user'. 'state' parameter is standard to retrieve some parameters back +} +if ($action != 'delete' && empty($requestedpermissionsarray)) { + print 'Error, parameter state is not defined'; + exit; +} +//var_dump($requestedpermissionsarray);exit; + +// Instantiate the Api service using the credentials, http client and storage mechanism for the token +$apiService = $serviceFactory->createService($genericstring, $credentials, $storage, $requestedpermissionsarray); + +/* +var_dump($genericstring.($keyforprovider ? '-'.$keyforprovider : '')); +var_dump($credentials); +var_dump($storage); +var_dump($requestedpermissionsarray); +*/ + +if (empty($apiService)) { + print 'Error, failed to create serviceFactory'; + exit; +} + +// access type needed to have oauth provider refreshing token +//$apiService->setAccessType('offline'); + +$langs->load("oauth"); + +if (!getDolGlobalString($keyforparamid)) { + accessforbidden('Setup of service is not complete. Customer ID is missing'); +} +if (!getDolGlobalString($keyforparamsecret)) { + accessforbidden('Setup of service is not complete. Secret key is missing'); +} + + +/* + * Actions + */ + +if ($action == 'delete') { + $storage->clearToken($genericstring); + + setEventMessages($langs->trans('TokenDeleted'), null, 'mesgs'); + + header('Location: '.$backtourl); + exit(); +} + +if (GETPOST('code')) { // We are coming from oauth provider page + // We should have + //$_GET=array('code' => string 'aaaaaaaaaaaaaa' (length=20), 'state' => string 'user,public_repo' (length=16)) + + dol_syslog("We are coming from the oauth provider page"); + //llxHeader('',$langs->trans("OAuthSetup")); + + //$linkback=''.$langs->trans("BackToModuleList").''; + //print load_fiche_titre($langs->trans("OAuthSetup"),$linkback,'title_setup'); + + //print dol_get_fiche_head(); + // retrieve the CSRF state parameter + $state = GETPOSTISSET('state') ? GETPOST('state') : null; + //print ''; + + // This was a callback request from service, get the token + try { + //var_dump($_GET['code']); + //var_dump($state); + //var_dump($apiService); // OAuth\OAuth2\Service\GitHub + + //$token = $apiService->requestAccessToken(GETPOST('code'), $state); + $token = $apiService->requestAccessToken(GETPOST('code')); + // Github is a service that does not need state to be stored. + // Into constructor of GitHub, the call + // parent::__construct($credentials, $httpClient, $storage, $scopes, $baseApiUri) + // has not the ending parameter to true like the Google class constructor. + + setEventMessages($langs->trans('NewTokenStored'), null, 'mesgs'); // Stored into object managed by class DoliStorage so into table oauth_token + + $backtourl = $_SESSION["backtourlsavedbeforeoauthjump"]; + unset($_SESSION["backtourlsavedbeforeoauthjump"]); + + header('Location: '.$backtourl); + exit(); + } catch (Exception $e) { + print $e->getMessage(); + } +} else { // If entry on page with no parameter, we arrive here + $_SESSION["backtourlsavedbeforeoauthjump"] = $backtourl; + $_SESSION["oauthkeyforproviderbeforeoauthjump"] = $keyforprovider; + $_SESSION['oauthstateanticsrf'] = $state; + + // This may create record into oauth_state before the header redirect. + // Creation of record with state in this tables depend on the Provider used (see its constructor). + if (GETPOST('state')) { + $url = $apiService->getAuthorizationUri(array('state' => GETPOST('state'))); + } else { + $url = $apiService->getAuthorizationUri(); // Parameter state will be randomly generated + } + + // we go on oauth provider authorization page + header('Location: '.$url); + exit(); +} + + +/* + * View + */ + +// No view at all, just actions + +$db->close(); diff --git a/htdocs/core/modules/oauth/github_oauthcallback.php b/htdocs/core/modules/oauth/github_oauthcallback.php index 5c24e23aafa..f496c42d0ac 100644 --- a/htdocs/core/modules/oauth/github_oauthcallback.php +++ b/htdocs/core/modules/oauth/github_oauthcallback.php @@ -1,5 +1,5 @@ * Copyright (C) 2015 Frederic France * * This program is free software; you can redistribute it and/or modify @@ -86,7 +86,7 @@ if ($action != 'delete' && empty($requestedpermissionsarray)) { //var_dump($requestedpermissionsarray);exit; // Instantiate the Api service using the credentials, http client and storage mechanism for the token -$apiService = $serviceFactory->createService('GitHub'.($keyforprovider ? '-'.$keyforprovider : ''), $credentials, $storage, $requestedpermissionsarray); +$apiService = $serviceFactory->createService('GitHub', $credentials, $storage, $requestedpermissionsarray); // access type needed to have oauth provider refreshing token //$apiService->setAccessType('offline'); diff --git a/htdocs/core/modules/oauth/google_oauthcallback.php b/htdocs/core/modules/oauth/google_oauthcallback.php index 2812c4f7163..9208a6110a9 100644 --- a/htdocs/core/modules/oauth/google_oauthcallback.php +++ b/htdocs/core/modules/oauth/google_oauthcallback.php @@ -1,5 +1,5 @@ * Copyright (C) 2015 Frederic France * * This program is free software; you can redistribute it and/or modify diff --git a/htdocs/core/modules/oauth/stripelive_oauthcallback.php b/htdocs/core/modules/oauth/stripelive_oauthcallback.php index bf9656df783..f24921faf83 100644 --- a/htdocs/core/modules/oauth/stripelive_oauthcallback.php +++ b/htdocs/core/modules/oauth/stripelive_oauthcallback.php @@ -1,5 +1,5 @@ * Copyright (C) 2019 Thibault FOUCART * * This program is free software; you can redistribute it and/or modify diff --git a/htdocs/core/modules/oauth/stripetest_oauthcallback.php b/htdocs/core/modules/oauth/stripetest_oauthcallback.php index 64d55fba760..b41b579857e 100644 --- a/htdocs/core/modules/oauth/stripetest_oauthcallback.php +++ b/htdocs/core/modules/oauth/stripetest_oauthcallback.php @@ -1,5 +1,5 @@ * Copyright (C) 2015 Frederic France * * This program is free software; you can redistribute it and/or modify diff --git a/htdocs/langs/en_US/oauth.lang b/htdocs/langs/en_US/oauth.lang index 08f7956f455..b7f7c0c2c1a 100644 --- a/htdocs/langs/en_US/oauth.lang +++ b/htdocs/langs/en_US/oauth.lang @@ -9,8 +9,9 @@ HasAccessToken=A token was generated and saved into local database NewTokenStored=Token received and saved ToCheckDeleteTokenOnProvider=Click here to check/delete authorization saved by %s OAuth provider TokenDeleted=Token deleted +GetAccess=Click here to get a token RequestAccess=Click here to request/renew access and receive a new token -DeleteAccess=Click here to delete token +DeleteAccess=Click here to delete the token UseTheFollowingUrlAsRedirectURI=Use the following URL as the Redirect URI when creating your credentials with your OAuth provider: ListOfSupportedOauthProviders=Add your OAuth2 token providers. Then, go on your OAuth provider admin page to create/get an OAuth ID and Secret and save them here. Once done, switch on the other tab to generate your token. OAuthSetupForLogin=Page to manage (generate/delete) OAuth tokens @@ -33,4 +34,6 @@ OAUTH_STRIPE_LIVE_NAME=OAuth Stripe Live OAUTH_ID=OAuth ID OAUTH_SECRET=OAuth secret OAuthProviderAdded=OAuth provider added -AOAuthEntryForThisProviderAndLabelAlreadyHasAKey=An OAuth entry for this provider and label already exists \ No newline at end of file +AOAuthEntryForThisProviderAndLabelAlreadyHasAKey=An OAuth entry for this provider and label already exists +URLOfServiceForAuthorization=URL provided by OAuth service for authentication +Scopes=Scopes \ No newline at end of file From 8e572d605e7e12b091630ad6e8f179db85667b5c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 4 Aug 2022 16:16:46 +0200 Subject: [PATCH 450/826] Fix php8 --- htdocs/includes/tecnickcom/tcpdf/tcpdf_barcodes_1d.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/includes/tecnickcom/tcpdf/tcpdf_barcodes_1d.php b/htdocs/includes/tecnickcom/tcpdf/tcpdf_barcodes_1d.php index 78bfc5b5bf4..2fea49ef4ce 100644 --- a/htdocs/includes/tecnickcom/tcpdf/tcpdf_barcodes_1d.php +++ b/htdocs/includes/tecnickcom/tcpdf/tcpdf_barcodes_1d.php @@ -1337,14 +1337,14 @@ class TCPDFBarcode { // calculate check digit $sum_a = 0; for ($i = 1; $i < $data_len; $i+=2) { - $sum_a += $code[$i]; + $sum_a += (int) $code[$i]; } if ($len > 12) { $sum_a *= 3; } $sum_b = 0; for ($i = 0; $i < $data_len; $i+=2) { - $sum_b += ($code[$i]); + $sum_b += (int) ($code[$i]); } if ($len < 13) { $sum_b *= 3; @@ -2171,7 +2171,7 @@ class TCPDFBarcode { /** * IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200 - * + * * @param $code (string) pre-formatted IMB barcode (65 chars "FADT") * @return array barcode representation. * @protected From f56abb1e5f676e3e7b3114f0833a54545999f9ba Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 4 Aug 2022 16:17:07 +0200 Subject: [PATCH 451/826] Fix limit on nb of stickers --- htdocs/barcode/printsheet.php | 35 ++++++++++++++++++---------------- htdocs/langs/en_US/errors.lang | 1 + 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/htdocs/barcode/printsheet.php b/htdocs/barcode/printsheet.php index 763463d6fb8..c55db4ef2a1 100644 --- a/htdocs/barcode/printsheet.php +++ b/htdocs/barcode/printsheet.php @@ -203,25 +203,30 @@ if ($action == 'builddoc') { $forceimgscalewidth = (empty($conf->global->BARCODE_FORCEIMGSCALEWIDTH) ? 1 : $conf->global->BARCODE_FORCEIMGSCALEWIDTH); $forceimgscaleheight = (empty($conf->global->BARCODE_FORCEIMGSCALEHEIGHT) ? 1 : $conf->global->BARCODE_FORCEIMGSCALEHEIGHT); - for ($i = 0; $i < $numberofsticker; $i++) { - $arrayofrecords[] = array( - 'textleft'=>$textleft, - 'textheader'=>$textheader, - 'textfooter'=>$textfooter, - 'textright'=>$textright, - 'code'=>$code, - 'encoding'=>$encoding, - 'is2d'=>$is2d, - 'photo'=>$barcodeimage // Photo must be a file that exists with format supported by TCPDF - ); + $MAXSTICKERS = 1000; + if ($numberofsticker <= $MAXSTICKERS) { + for ($i = 0; $i < $numberofsticker; $i++) { + $arrayofrecords[] = array( + 'textleft'=>$textleft, + 'textheader'=>$textheader, + 'textfooter'=>$textfooter, + 'textright'=>$textright, + 'code'=>$code, + 'encoding'=>$encoding, + 'is2d'=>$is2d, + 'photo'=>$barcodeimage // Photo must be a file that exists with format supported by TCPDF + ); + } + } else { + $mesg = $langs->trans("ErrorQuantityIsLimitedTo", $MAXSTICKERS); + $error++; } } $i++; - $mesg = ''; // Build and output PDF - if ($mode == 'label') { + if (!$error && $mode == 'label') { if (!count($arrayofrecords)) { $mesg = $langs->trans("ErrorRecordNotFound"); } @@ -240,7 +245,7 @@ if ($action == 'builddoc') { } } - if ($result <= 0 || $mesg) { + if ($result <= 0 || $mesg || $error) { if (empty($mesg)) { $mesg = 'Error '.$result; } @@ -272,8 +277,6 @@ print '
'; print ''.$langs->trans("PageToGenerateBarCodeSheets", $langs->transnoentitiesnoconv("BuildPageToPrint")).'
'; print '
'; -dol_htmloutput_errors($mesg); - //print img_picto('','puce').' '.$langs->trans("PrintsheetForOneBarCode").'
'; //print '
'; diff --git a/htdocs/langs/en_US/errors.lang b/htdocs/langs/en_US/errors.lang index a280228a46d..ebdb359a66e 100644 --- a/htdocs/langs/en_US/errors.lang +++ b/htdocs/langs/en_US/errors.lang @@ -290,6 +290,7 @@ ErrorDeleteLineNotAllowedByObjectStatus=Delete line is not allowed by current ob ErrorAjaxRequestFailed=Request failed ErrorThirpdartyOrMemberidIsMandatory=Third party or Member of partnership is mandatory ErrorFailedToWriteInTempDirectory=Failed to write in temp directory +ErrorQuantityIsLimitedTo=Quantity is limited to %s # Warnings WarningParamUploadMaxFileSizeHigherThanPostMaxSize=Your PHP parameter upload_max_filesize (%s) is higher than PHP parameter post_max_size (%s). This is not a consistent setup. From 9955e51956fc5bc5bc5c9a2b520009fb7c2d12c1 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Fri, 5 Aug 2022 09:39:31 +0200 Subject: [PATCH 452/826] NEW - FTP Function mkdir --- htdocs/core/lib/ftp.lib.php | 5 ++--- htdocs/ftp/index.php | 40 +++++++++++++++++++++++++++++++---- htdocs/langs/en_US/other.lang | 3 +++ 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/htdocs/core/lib/ftp.lib.php b/htdocs/core/lib/ftp.lib.php index 4a9f5a894d4..361904e3bd1 100644 --- a/htdocs/core/lib/ftp.lib.php +++ b/htdocs/core/lib/ftp.lib.php @@ -296,9 +296,8 @@ function dol_ftp_mkdir($connect_id, $newdir, $newsection) } // Remote file - $filename = $file; - $remotefile = $newsection.(preg_match('@[\\\/]$@', $newsection) ? '' : '/').$file; - $newremotefileiso = utf8_decode($remotefile); + $newremotefileiso = $newsection.(preg_match('@[\\\/]$@', $newsection) ? '' : '/').$newdir; + $newremotefileiso = utf8_decode($newremotefileiso); if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) { return ssh2_sftp_mkdir($connect_id, $newremotefileiso); diff --git a/htdocs/ftp/index.php b/htdocs/ftp/index.php index 4df7e1512a6..20389ade79e 100644 --- a/htdocs/ftp/index.php +++ b/htdocs/ftp/index.php @@ -41,6 +41,7 @@ $result = restrictedArea($user, 'ftp', ''); // Get parameters $action = GETPOST('action', 'aZ09'); $section = GETPOST('section'); +$newfolder = GETPOST('newfolder'); if (!$section) { $section = '/'; } @@ -141,11 +142,8 @@ if ($action == 'uploadfile') { $mesg = $resultarray['mesg']; } if ($conn_id && $ok && !$mesg) { - // var_dump($_FILES['userfile']['name']); $nbfile = count($_FILES['userfile']['name']); - $i = 0; - for (; $i < $nbfile; $i++) { - var_dump($i); + for ($i = 0; $i < $nbfile; $i++) { $newsection = $newsectioniso; $fileupload = $_FILES['userfile']['name'][$i]; $fileuploadpath = $_FILES['userfile']['tmp_name'][$i]; @@ -164,6 +162,30 @@ if ($action == 'uploadfile') { } } +if ($action == 'addfolder') { + // set up a connection or die + if (!$conn_id) { + $newsectioniso = utf8_decode($section); + $resultarray = dol_ftp_connect($ftp_server, $ftp_port, $ftp_user, $ftp_password, $newsectioniso, $ftp_passive); + $conn_id = $resultarray['conn_id']; + $ok = $resultarray['ok']; + $mesg = $resultarray['mesg']; + } + if ($conn_id && $ok && !$mesg) { + $result = dol_ftp_mkdir($conn_id, $newfolder, $newsectioniso); + + if ($result) { + setEventMessages($langs->trans("FileWasCreateFolder", $newfolder), null, 'mesgs'); + } else { + dol_syslog("ftp/index.php ftp_delete", LOG_ERR); + setEventMessages($langs->trans("FTPFailedToCreateFolder", $newfolder), null, 'errors'); + } + $action = ''; + } else { + dol_print_error('', $mesg); + } +} + // Action ajout d'un rep if ($action == 'add' && $user->rights->ftp->setup) { $ecmdir->ref = GETPOST("ref"); @@ -633,6 +655,16 @@ if (!function_exists('ftp_connect')) { print '
'; print ''; print ''; + print load_fiche_titre($langs->trans("AddFolder"), null, null); + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; } } else { $foundsetup = false; diff --git a/htdocs/langs/en_US/other.lang b/htdocs/langs/en_US/other.lang index daa52aac9fe..8be37bd0f9a 100644 --- a/htdocs/langs/en_US/other.lang +++ b/htdocs/langs/en_US/other.lang @@ -328,3 +328,6 @@ FailedToGetFile=Failed to get files %s ErrorFTPNodisconnect=Error to disconnect FTP/SFTP server FileWasUpload=File %s was upload FTPFailedToUploadFile=Failed to upload file %s. +AddFolder=Create folder +FileWasCreateFolder=Folder %s was create +FTPFailedToCreateFolder=Failed to create folder %s. From 17483eb08222c6d50a04cc0e9f57352cb84d2449 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Fri, 5 Aug 2022 10:47:00 +0200 Subject: [PATCH 453/826] Fix --- htdocs/core/lib/ftp.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/ftp.lib.php b/htdocs/core/lib/ftp.lib.php index 361904e3bd1..118c85e9b74 100644 --- a/htdocs/core/lib/ftp.lib.php +++ b/htdocs/core/lib/ftp.lib.php @@ -300,7 +300,7 @@ function dol_ftp_mkdir($connect_id, $newdir, $newsection) $newremotefileiso = utf8_decode($newremotefileiso); if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) { - return ssh2_sftp_mkdir($connect_id, $newremotefileiso); + return ssh2_sftp_mkdir($connect_id, $newremotefileiso, 0777); } else { return @ftp_mkdir($connect_id, $newremotefileiso); } From 5f32d17158117a5ba5802bef20b8fe3868ad896e Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Fri, 5 Aug 2022 16:21:01 +0200 Subject: [PATCH 454/826] Fix : permission error on category view --- htdocs/categories/viewcat.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/htdocs/categories/viewcat.php b/htdocs/categories/viewcat.php index 5450127bff3..3fc42bb2818 100644 --- a/htdocs/categories/viewcat.php +++ b/htdocs/categories/viewcat.php @@ -952,7 +952,7 @@ if ($type == Categorie::TYPE_ACCOUNT) { } // List of Project -if ($type == Categorie::TYPE_PROJECT) { +if ($type == Categorie::TYPE_PROJECT ) { require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; $permission = $user->rights->projet->creer; @@ -1030,7 +1030,7 @@ if ($type == Categorie::TYPE_PROJECT) { } // List of users -if ($type == Categorie::TYPE_USER) { +if ($type == Categorie::TYPE_USER && $user->hasRight("user", "user", "read")) { require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; $users = $object->getObjectsInCateg($type); @@ -1099,6 +1099,9 @@ if ($type == Categorie::TYPE_USER) { print ''."\n"; } +} else { + print_barre_liste($langs->trans("Users"), null, $_SERVER["PHP_SELF"], '', '', '', '', '', '', 'user'); + accessforbidden($langs->trans("NotEnoughPermissions"), 0, 0); } From bfe28bfda3dcae049599d578d4b05484000f9ddc Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Fri, 5 Aug 2022 16:22:03 +0200 Subject: [PATCH 455/826] remove artefacts --- htdocs/categories/viewcat.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/categories/viewcat.php b/htdocs/categories/viewcat.php index 3fc42bb2818..5405b33d994 100644 --- a/htdocs/categories/viewcat.php +++ b/htdocs/categories/viewcat.php @@ -952,7 +952,7 @@ if ($type == Categorie::TYPE_ACCOUNT) { } // List of Project -if ($type == Categorie::TYPE_PROJECT ) { +if ($type == Categorie::TYPE_PROJECT) { require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; $permission = $user->rights->projet->creer; From e9e5163789085544c9ae71cf4fb9e3be4d7f71bf Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Fri, 5 Aug 2022 17:43:33 +0200 Subject: [PATCH 456/826] yesno --- htdocs/core/class/html.formsetup.class.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/html.formsetup.class.php b/htdocs/core/class/html.formsetup.class.php index 3ff36b356da..a6b4c96e7ad 100644 --- a/htdocs/core/class/html.formsetup.class.php +++ b/htdocs/core/class/html.formsetup.class.php @@ -835,7 +835,11 @@ class FormSetupItem } elseif ($this->type== 'color') { $out.= $this->generateInputFieldColor(); } elseif ($this->type == 'yesno') { - $out.= $this->form->selectyesno($this->confKey, $this->fieldValue, 1); + if (!empty($conf->use_javascript_ajax)) { + $out.= ajax_constantonoff($this->confKey); + } else { + $out.= $this->form->selectyesno($this->confKey, $this->fieldValue, 1); + } } elseif (preg_match('/emailtemplate:/', $this->type)) { $out.= $this->generateInputFieldEmailTemplate(); } elseif (preg_match('/category:/', $this->type)) { @@ -1057,7 +1061,15 @@ class FormSetupItem } elseif ($this->type== 'color') { $out.= $this->generateOutputFieldColor(); } elseif ($this->type == 'yesno') { - $out.= ajax_constantonoff($this->confKey); + if (!empty($conf->use_javascript_ajax)) { + $out.= ajax_constantonoff($this->confKey); + } else { + if ($this->confKey == 1) { + $out.= $this->langs('yes'); + } else { + $out.= $this->langs('no'); + } + } } elseif (preg_match('/emailtemplate:/', $this->type)) { include_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php'; $formmail = new FormMail($this->db); From 93fd5c9e7db2fb05ce7688b24dd7dc48d110da0d Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Fri, 5 Aug 2022 17:55:39 +0200 Subject: [PATCH 457/826] corection lang --- htdocs/core/class/html.formsetup.class.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/core/class/html.formsetup.class.php b/htdocs/core/class/html.formsetup.class.php index a6b4c96e7ad..87fc937429c 100644 --- a/htdocs/core/class/html.formsetup.class.php +++ b/htdocs/core/class/html.formsetup.class.php @@ -1036,7 +1036,7 @@ class FormSetupItem */ public function generateOutputField() { - global $conf, $user; + global $conf, $user, $langs; if (!empty($this->fieldOverride)) { return $this->fieldOverride; @@ -1064,10 +1064,10 @@ class FormSetupItem if (!empty($conf->use_javascript_ajax)) { $out.= ajax_constantonoff($this->confKey); } else { - if ($this->confKey == 1) { - $out.= $this->langs('yes'); + if ($this->fieldValue == 1) { + $out.= $langs->trans('yes'); } else { - $out.= $this->langs('no'); + $out.= $langs->trans('no'); } } } elseif (preg_match('/emailtemplate:/', $this->type)) { From 1fac6e0ee47d69caf28badc9bc062e98e3e69c4a Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sat, 6 Aug 2022 14:50:53 +0200 Subject: [PATCH 458/826] New filter by category for knowledgemanagement API --- .../class/api_knowledgemanagement.class.php | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php b/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php index b95a5717932..ccf54b1d6d9 100644 --- a/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php +++ b/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php @@ -125,18 +125,19 @@ class KnowledgeManagement extends DolibarrApi * * Get a list of knowledgerecords * - * @param string $sortfield Sort field - * @param string $sortorder Sort order - * @param int $limit Limit for list - * @param int $page Page number - * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')" + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * @param int $category Use this param to filter list by category + * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')" * @return array Array of order objects * * @throws RestException * * @url GET /knowledgerecords/ */ - public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $sqlfilters = '') + public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $category = 0, $sqlfilters = '') { global $db, $conf; @@ -166,6 +167,9 @@ class KnowledgeManagement extends DolibarrApi if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale } + if ($category > 0) { + $sql .= ", ".$this->db->prefix()."categorie_knowledgemanagement as c"; + } $sql .= " WHERE 1 = 1"; // Example of use $mode @@ -188,6 +192,11 @@ class KnowledgeManagement extends DolibarrApi if ($restrictonsocid && $search_sale > 0) { $sql .= " AND sc.fk_user = ".((int) $search_sale); } + // Select products of given category + if ($category > 0) { + $sql .= " AND c.fk_categorie = ".((int) $category); + $sql .= " AND c.fk_knowledgemanagement = t.rowid"; + } if ($sqlfilters) { $errormessage = ''; if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { From ed9cadac7e6ad2768d84cc7b7440b62d06efe556 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sat, 6 Aug 2022 18:47:41 +0200 Subject: [PATCH 459/826] NEW default_lang for members --- htdocs/install/mysql/migration/16.0.0-17.0.0.sql | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql index e72fc1b8dcd..c1f96ca9d3e 100644 --- a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql +++ b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql @@ -77,3 +77,5 @@ ALTER TABLE llx_recruitment_recruitmentcandidature ADD email_date datetime after ALTER TABLE llx_ticket ADD email_date datetime after email_msgid; INSERT INTO llx_const (name, entity, value, type, visible) VALUES ('MAIN_SECURITY_MAX_IMG_IN_HTML_CONTENT', 1, 1000, 'int', 0); + +ALTER TABLE `llx_adherent` ADD default_lang VARCHAR(6) NULL DEFAULT NULL AFTER datefin; From 1ffbf1e56b1396febf2df03b2a2957260e3dd71b Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sat, 6 Aug 2022 18:49:18 +0200 Subject: [PATCH 460/826] Update llx_adherent.sql --- htdocs/install/mysql/tables/llx_adherent.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/install/mysql/tables/llx_adherent.sql b/htdocs/install/mysql/tables/llx_adherent.sql index 01a87167411..e0ba93554b8 100644 --- a/htdocs/install/mysql/tables/llx_adherent.sql +++ b/htdocs/install/mysql/tables/llx_adherent.sql @@ -71,6 +71,7 @@ create table llx_adherent statut smallint NOT NULL DEFAULT 0, public smallint NOT NULL DEFAULT 0, -- certain champ de la fiche sont ils public ou pas ? datefin datetime, -- end date of validity of the contribution / date de fin de validite de la cotisation + default_lang varchar(6) NULL, note_private text DEFAULT NULL, note_public text DEFAULT NULL, model_pdf varchar(255), From d91c90bba1d886d4103db4ad62cad0951a394744 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sat, 6 Aug 2022 19:49:03 +0200 Subject: [PATCH 461/826] FIX lang label & flag in user/card.php --- htdocs/user/card.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/user/card.php b/htdocs/user/card.php index 8e375933a91..988f508550b 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -1642,6 +1642,7 @@ if ($action == 'create' || $action == 'adduserldap') { //$s=picto_from_langcode($object->default_lang); //print ($s?$s.' ':''); $labellang = ($object->lang ? $langs->trans('Language_'.$object->lang) : ''); + print picto_from_langcode($object->lang, 'class="paddingrightonly saturatemedium opacitylow"'); print $labellang; print ''; } From 1a1c5d9110b45a1fb064aa613e652987391da4c1 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sun, 7 Aug 2022 10:14:05 +0200 Subject: [PATCH 462/826] Update user.class.php --- htdocs/user/class/user.class.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 4c044f329b2..008aaae5007 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -2073,6 +2073,8 @@ class User extends CommonObject $adh->phone = $this->office_phone; $adh->phone_mobile = $this->user_mobile; + $adh->default_lang = $this->lang; + $adh->user_id = $this->id; $adh->user_login = $this->login; @@ -2117,6 +2119,8 @@ class User extends CommonObject $tmpobj->phone_mobile = $this->user_mobile; $tmpobj->fax = $this->office_fax; + $tmpobj->default_lang = $this->lang; + $tmpobj->address = $this->address; $tmpobj->town = $this->town; $tmpobj->zip = $this->zip; From 65629121f8e9687c5ee32baa3278ab8ed3fa61ab Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sun, 7 Aug 2022 10:14:40 +0200 Subject: [PATCH 463/826] update --- htdocs/adherents/card.php | 30 ++++++++++++++++++++--- htdocs/adherents/class/adherent.class.php | 17 ++++++++++++- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php index 44a12293e67..f7b900feaa4 100644 --- a/htdocs/adherents/card.php +++ b/htdocs/adherents/card.php @@ -40,6 +40,7 @@ require_once DOL_DOCUMENT_ROOT.'/adherents/class/subscription.class.php'; require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; @@ -311,8 +312,8 @@ if (empty($reshook)) { //$object->twitter = trim(GETPOST("twitter", 'alpha')); //$object->facebook = trim(GETPOST("facebook", 'alpha')); //$object->linkedin = trim(GETPOST("linkedin", 'alpha')); - $object->birth = $birthdate; - + $object->birth = $birthdate; + $object->default_lang = GETPOST('default_lang', 'alpha'); $object->typeid = GETPOST("typeid", 'int'); //$object->note = trim(GETPOST("comment","alpha")); $object->morphy = GETPOST("morphy", 'alpha'); @@ -457,6 +458,7 @@ if (empty($reshook)) { $userid = GETPOST("userid", 'int'); $socid = GETPOST("socid", 'int'); + $default_lang = GETPOST('default_lang', 'alpha'); $object->civility_id = $civility_id; $object->firstname = $firstname; @@ -498,7 +500,7 @@ if (empty($reshook)) { $object->user_id = $userid; $object->socid = $socid; $object->public = $public; - + $object->default_lang = $default_lang; // Fill array 'array_options' with data from add form $ret = $extrafields->setOptionalsFromPost(null, $object); if ($ret < 0) { @@ -899,6 +901,7 @@ if (empty($reshook)) { $form = new Form($db); $formfile = new FormFile($db); +$formadmin = new FormAdmin($db); $formcompany = new FormCompany($db); $title = $langs->trans("Member")." - ".$langs->trans("Card"); @@ -1363,6 +1366,14 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print $form->selectDate(($object->birth ? $object->birth : -1), 'birth', '', '', 1, 'formsoc'); print "\n"; + // Default language + if (!empty($conf->global->MAIN_MULTILANGS)) { + print ''; + print ''; + } + // Public profil print "'; + // Default language + if (!empty($conf->global->MAIN_MULTILANGS)) { + require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; + print ''; + } + // Public print ''; diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index dec7584b68e..318dc4ac794 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -215,6 +215,12 @@ class Adherent extends CommonObject */ public $public; + /** + * Default language code of member (en_US, ...) + * @var string + */ + public $default_lang; + /** * @var string photo of member */ @@ -328,6 +334,7 @@ class Adherent extends CommonObject 'photo' => array('type' => 'varchar(255)', 'label' => 'Photo', 'enabled' => 1, 'visible' => -1, 'position' => 135), 'public' => array('type' => 'smallint(6)', 'label' => 'Public', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 145), 'datefin' => array('type' => 'datetime', 'label' => 'DateEnd', 'enabled' => 1, 'visible' => -1, 'position' => 150), + 'default_lang' =>array('type'=>'varchar(6)', 'label'=>'Default lang', 'enabled'=>1, 'visible'=>-1, 'position'=> 153), 'note_private' => array('type' => 'text', 'label' => 'NotePublic', 'enabled' => 1, 'visible' => 0, 'position' => 155), 'note_public' => array('type' => 'text', 'label' => 'NotePrivate', 'enabled' => 1, 'visible' => 0, 'position' => 160), 'datevalid' => array('type' => 'datetime', 'label' => 'DateValidation', 'enabled' => 1, 'visible' => -1, 'position' => 165), @@ -710,9 +717,11 @@ class Adherent extends CommonObject $sql .= ", photo = ".($this->photo ? "'".$this->db->escape($this->photo)."'" : "null"); $sql .= ", public = '".$this->db->escape($this->public)."'"; $sql .= ", statut = ".$this->db->escape($this->statut); + $sql .= ", default_lang = ".(!empty($this->default_lang) ? "'".$this->db->escape($this->default_lang)."'" : "null"); $sql .= ", fk_adherent_type = ".$this->db->escape($this->typeid); $sql .= ", morphy = '".$this->db->escape($this->morphy)."'"; $sql .= ", birth = ".($this->birth ? "'".$this->db->idate($this->birth)."'" : "null"); + if ($this->datefin) { $sql .= ", datefin = '".$this->db->idate($this->datefin)."'"; // Must be modified only when deleting a subscription } @@ -833,6 +842,8 @@ class Adherent extends CommonObject $luser->office_phone = $this->phone; $luser->user_mobile = $this->phone_mobile; + $luser->lang = $this->default_lang; + $luser->fk_member = $this->id; $result = $luser->update($user, 0, 1, 1); // Use nosync to 1 to avoid cyclic updates @@ -868,6 +879,7 @@ class Adherent extends CommonObject $lthirdparty->state_id = $this->state_id; $lthirdparty->country_id = $this->country_id; //$lthirdparty->phone_mobile=$this->phone_mobile; + $lthirdparty->default_lang = $this->default_lang; $result = $lthirdparty->update($this->fk_soc, $user, 0, 1, 1, 'update'); // Use sync to 0 to avoid cyclic updates @@ -1314,7 +1326,7 @@ class Adherent extends CommonObject $sql .= " d.photo, d.fk_adherent_type, d.morphy, d.entity,"; $sql .= " d.datec as datec,"; $sql .= " d.tms as datem,"; - $sql .= " d.datefin as datefin,"; + $sql .= " d.datefin as datefin, d.default_lang,"; $sql .= " d.birth as birthday,"; $sql .= " d.datevalid as datev,"; $sql .= " d.country,"; @@ -1407,6 +1419,8 @@ class Adherent extends CommonObject $this->date_validation = $this->db->jdate($obj->datev); $this->birth = $this->db->jdate($obj->birthday); + $this->default_lang = $obj->default_lang; + $this->note_private = $obj->note_private; $this->note_public = $obj->note_public; $this->morphy = $obj->morphy; @@ -2556,6 +2570,7 @@ class Adherent extends CommonObject $this->datefin = $now; $this->datevalid = $now; + $this->default_lang = ''; $this->typeid = 1; // Id type adherent $this->type = 'Type adherent'; // Libelle type adherent From 6aedbc5445a4d65938231e3140d7c804ad144925 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sun, 7 Aug 2022 12:59:58 +0200 Subject: [PATCH 464/826] Update llx_adherent.sql --- htdocs/install/mysql/tables/llx_adherent.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/install/mysql/tables/llx_adherent.sql b/htdocs/install/mysql/tables/llx_adherent.sql index e0ba93554b8..be29e82d013 100644 --- a/htdocs/install/mysql/tables/llx_adherent.sql +++ b/htdocs/install/mysql/tables/llx_adherent.sql @@ -71,7 +71,7 @@ create table llx_adherent statut smallint NOT NULL DEFAULT 0, public smallint NOT NULL DEFAULT 0, -- certain champ de la fiche sont ils public ou pas ? datefin datetime, -- end date of validity of the contribution / date de fin de validite de la cotisation - default_lang varchar(6) NULL, + default_lang varchar(6) DEFAULT NULL, note_private text DEFAULT NULL, note_public text DEFAULT NULL, model_pdf varchar(255), From d7e114aa60b8daea21592db040090938d4f1f39f Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sun, 7 Aug 2022 13:00:48 +0200 Subject: [PATCH 465/826] Update 16.0.0-17.0.0.sql --- htdocs/install/mysql/migration/16.0.0-17.0.0.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql index c1f96ca9d3e..b0f9dc6ce56 100644 --- a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql +++ b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql @@ -78,4 +78,4 @@ ALTER TABLE llx_ticket ADD email_date datetime after email_msgid; INSERT INTO llx_const (name, entity, value, type, visible) VALUES ('MAIN_SECURITY_MAX_IMG_IN_HTML_CONTENT', 1, 1000, 'int', 0); -ALTER TABLE `llx_adherent` ADD default_lang VARCHAR(6) NULL DEFAULT NULL AFTER datefin; +ALTER TABLE llx_adherent ADD COLUMN default_lang VARCHAR(6) DEFAULT NULL AFTER datefin; From 6ff002405ef524d16adc8bf73cd39716917be281 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sun, 7 Aug 2022 19:37:15 +0200 Subject: [PATCH 466/826] NEW manage virtual stock at future date --- htdocs/product/class/api_products.class.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/htdocs/product/class/api_products.class.php b/htdocs/product/class/api_products.class.php index 2566ca24919..e34b270562e 100644 --- a/htdocs/product/class/api_products.class.php +++ b/htdocs/product/class/api_products.class.php @@ -253,7 +253,7 @@ class Products extends DolibarrApi if (!$ids_only) { $product_static = new Product($this->db); if ($product_static->fetch($obj->rowid)) { - if ($includestockdata && DolibarrApiAccess::$user->rights->stock->lire) { + if (!empty($includestockdata) && DolibarrApiAccess::$user->rights->stock->lire) { $product_static->load_stock(); if (is_array($product_static->stock_warehouse)) { @@ -1644,10 +1644,10 @@ class Products extends DolibarrApi $combinations[$key]->attributes = $prodc2vp->fetchByFkCombination((int) $combination->id); $combinations[$key] = $this->_cleanObjectDatas($combinations[$key]); - if ($includestock==1 && DolibarrApiAccess::$user->rights->stock->lire) { + if (!empty($includestock) && DolibarrApiAccess::$user->rights->stock->lire) { $productModel = new Product($this->db); $productModel->fetch((int) $combination->fk_product_child); - $productModel->load_stock(); + $productModel->load_stock($includestock); $combinations[$key]->stock_warehouse = $this->_cleanObjectDatas($productModel)->stock_warehouse; } } @@ -2040,8 +2040,8 @@ class Products extends DolibarrApi throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } - if ($includestockdata && DolibarrApiAccess::$user->rights->stock->lire) { - $this->product->load_stock(); + if (!empty($includestockdata) && DolibarrApiAccess::$user->rights->stock->lire) { + $this->product->load_stock($includestockdata); if (is_array($this->product->stock_warehouse)) { foreach ($this->product->stock_warehouse as $keytmp => $valtmp) { From e55b45cdc8f1691b3d9ee82282163ed2c4f58849 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sun, 7 Aug 2022 19:52:06 +0200 Subject: [PATCH 467/826] Update stockatdate.php --- htdocs/product/stock/stockatdate.php | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/htdocs/product/stock/stockatdate.php b/htdocs/product/stock/stockatdate.php index d4f1bbf4861..ef774081017 100644 --- a/htdocs/product/stock/stockatdate.php +++ b/htdocs/product/stock/stockatdate.php @@ -518,13 +518,9 @@ while ($i < ($limit ? min($num, $limit) : $num)) { } if ($mode == 'future') { - $prod->load_stock('warehouseopen, warehouseinternal', 0); // This call also ->load_virtual_stock() - - //$result = $prod->load_stats_reception(0, '4'); - //print $prod->stats_commande_fournisseur['qty'].'
'."\n"; - //print $prod->stats_reception['qty']; - - $stock = ''.$langs->trans("FeatureNotYetAvailable").''; + $prod->load_stock('warehouseopen, warehouseinternal', 0, $dateendofday); + $stock = $prod->stock_theorique; + $prod->load_stock('warehouseopen, warehouseinternal', 0); $virtualstock = $prod->stock_theorique; } else { if ($fk_warehouse > 0) { From 07f6ae34dcba035ffdbfd344557565ef690ca808 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Sun, 7 Aug 2022 17:52:32 +0000 Subject: [PATCH 468/826] Fixing style errors. --- htdocs/product/stock/stockatdate.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/product/stock/stockatdate.php b/htdocs/product/stock/stockatdate.php index ef774081017..82d818af2c9 100644 --- a/htdocs/product/stock/stockatdate.php +++ b/htdocs/product/stock/stockatdate.php @@ -518,7 +518,7 @@ while ($i < ($limit ? min($num, $limit) : $num)) { } if ($mode == 'future') { - $prod->load_stock('warehouseopen, warehouseinternal', 0, $dateendofday); + $prod->load_stock('warehouseopen, warehouseinternal', 0, $dateendofday); $stock = $prod->stock_theorique; $prod->load_stock('warehouseopen, warehouseinternal', 0); $virtualstock = $prod->stock_theorique; From fcff96d43f85a5edd52fe7fbb108838700214782 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sun, 7 Aug 2022 20:00:25 +0200 Subject: [PATCH 469/826] Update product.class.php --- htdocs/product/class/product.class.php | 56 ++++++++++++++++---------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 6c249e6b3bd..f2611e80000 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -3038,12 +3038,13 @@ class Product extends CommonObject /** * Charge tableau des stats commande fournisseur pour le produit/service * - * @param int $socid Id societe pour filtrer sur une societe - * @param string $filtrestatut Id des statuts pour filtrer sur des statuts - * @param int $forVirtualStock Ignore rights filter for virtual stock calculation. - * @return int Array of stats in $this->stats_commande_fournisseur, <0 if ko or >0 if ok + * @param int $socid Id societe pour filtrer sur une societe + * @param string $filtrestatut Id des statuts pour filtrer sur des statuts + * @param int $forVirtualStock Ignore rights filter for virtual stock calculation. + * @param int $dateofvirtualstock Date of virtual stock + * @return int Array of stats in $this->stats_commande_fournisseur, <0 if ko or >0 if ok */ - public function load_stats_commande_fournisseur($socid = 0, $filtrestatut = '', $forVirtualStock = 0) + public function load_stats_commande_fournisseur($socid = 0, $filtrestatut = '', $forVirtualStock = 0, $dateofvirtualstock = null) { // phpcs:enable global $conf, $user, $hookmanager, $action; @@ -3069,6 +3070,9 @@ class Product extends CommonObject if ($filtrestatut != '') { $sql .= " AND c.fk_statut in (".$this->db->sanitize($filtrestatut).")"; // Peut valoir 0 } + if (!empty($dateofvirtualstock)) { + $sql .= " AND c.date_livraison <= '".$this->db->idate($dateofvirtualstock)."'"; + } $result = $this->db->query($sql); if ($result) { @@ -3181,12 +3185,13 @@ class Product extends CommonObject /** * Charge tableau des stats réception fournisseur pour le produit/service * - * @param int $socid Id societe pour filtrer sur une societe - * @param string $filtrestatut Id statut pour filtrer sur un statut - * @param int $forVirtualStock Ignore rights filter for virtual stock calculation. + * @param int $socid Id societe pour filtrer sur une societe + * @param string $filtrestatut Id statut pour filtrer sur un statut + * @param int $forVirtualStock Ignore rights filter for virtual stock calculation. + * @param int $dateofvirtualstock Date of virtual stock * @return int Array of stats in $this->stats_reception, <0 if ko or >0 if ok */ - public function load_stats_reception($socid = 0, $filtrestatut = '', $forVirtualStock = 0) + public function load_stats_reception($socid = 0, $filtrestatut = '', $forVirtualStock = 0, $dateofvirtualstock = null) { // phpcs:enable global $conf, $user, $hookmanager, $action; @@ -3212,6 +3217,9 @@ class Product extends CommonObject if ($filtrestatut <> '') { $sql .= " AND cf.fk_statut IN (".$this->db->sanitize($filtrestatut).")"; } + if (!empty($dateofvirtualstock)) { + $sql .= " AND fd.datec <= '".$this->db->idate($dateofvirtualstock)."'"; + } $result = $this->db->query($sql); if ($result) { @@ -3238,12 +3246,13 @@ class Product extends CommonObject /** * Charge tableau des stats production pour le produit/service * - * @param int $socid Id societe pour filtrer sur une societe - * @param string $filtrestatut Id statut pour filtrer sur un statut - * @param int $forVirtualStock Ignore rights filter for virtual stock calculation. + * @param int $socid Id societe pour filtrer sur une societe + * @param string $filtrestatut Id statut pour filtrer sur un statut + * @param int $forVirtualStock Ignore rights filter for virtual stock calculation. + * @param int $dateofvirtualstock Date of virtual stock * @return integer Array of stats in $this->stats_mrptoproduce (nb=nb of order, qty=qty ordered), <0 if ko or >0 if ok */ - public function load_stats_inproduction($socid = 0, $filtrestatut = '', $forVirtualStock = 0) + public function load_stats_inproduction($socid = 0, $filtrestatut = '', $forVirtualStock = 0, $dateofvirtualstock = null) { // phpcs:enable global $conf, $user, $hookmanager, $action; @@ -3268,6 +3277,9 @@ class Product extends CommonObject if ($filtrestatut <> '') { $sql .= " AND m.status IN (".$this->db->sanitize($filtrestatut).")"; } + if (!empty($dateofvirtualstock)) { + $sql .= " AND m.date_valid <= '".$this->db->idate($dateofvirtualstock)."'"; // better date to code ? end of production ? + } $sql .= " GROUP BY role"; $this->stats_mrptoconsume['customers'] = 0; @@ -5346,10 +5358,11 @@ class Product extends CommonObject * @param string $option '' = Load all stock info, also from closed and internal warehouses, 'nobatch', 'novirtual' * You can also filter on 'warehouseclosed', 'warehouseopen', 'warehouseinternal' * @param int $includedraftpoforvirtual Include draft status of PO for virtual stock calculation + * @param int $dateofvirtualstock Date of virtual stock * @return int < 0 if KO, > 0 if OK * @see load_virtual_stock(), loadBatchInfo() */ - public function load_stock($option = '', $includedraftpoforvirtual = null) + public function load_stock($option = '', $includedraftpoforvirtual = null, $dateofvirtualstock = null) { // phpcs:enable global $conf; @@ -5407,7 +5420,7 @@ class Product extends CommonObject $this->db->free($result); if (!preg_match('/novirtual/', $option)) { - $this->load_virtual_stock($includedraftpoforvirtual); // This also load all arrays stats_xxx... + $this->load_virtual_stock($includedraftpoforvirtual, $dateofvirtualstock); // This also load all arrays stats_xxx... } return 1; @@ -5424,10 +5437,11 @@ class Product extends CommonObject * This function need a lot of load. If you use it on list, use a cache to execute it one for each product id. * * @param int $includedraftpoforvirtual Include draft status and not yet approved Purchase Orders for virtual stock calculation + * @param int $dateofvirtualstock Date of virtual stock * @return int < 0 if KO, > 0 if OK * @see load_stock(), loadBatchInfo() */ - public function load_virtual_stock($includedraftpoforvirtual = null) + public function load_virtual_stock($includedraftpoforvirtual = null, $dateofvirtualstock = null) { // phpcs:enable global $conf, $hookmanager, $action; @@ -5466,7 +5480,7 @@ class Product extends CommonObject if (isset($includedraftpoforvirtual)) { $filterStatus = '0,1,2,'.$filterStatus; // 1,2 may have already been inside $filterStatus but it is better to have twice than missing $filterStatus does not include them } - $result = $this->load_stats_commande_fournisseur(0, $filterStatus, 1); + $result = $this->load_stats_commande_fournisseur(0, $filterStatus, 1, $dateofvirtualstock); if ($result < 0) { dol_print_error($this->db, $this->error); } @@ -5478,7 +5492,7 @@ class Product extends CommonObject if (isset($includedraftpoforvirtual)) { $filterStatus = '0,'.$filterStatus; } - $result = $this->load_stats_reception(0, $filterStatus, 1); + $result = $this->load_stats_reception(0, $filterStatus, 1, $dateofvirtualstock); if ($result < 0) { dol_print_error($this->db, $this->error); } @@ -5490,14 +5504,14 @@ class Product extends CommonObject if (isset($includedraftpoforvirtual)) { $filterStatus = '0,'.$filterStatus; } - $result = $this->load_stats_reception(0, $filterStatus, 1); // Use same tables than when module reception is not used. + $result = $this->load_stats_reception(0, $filterStatus, 1, $dateofvirtualstock); // Use same tables than when module reception is not used. if ($result < 0) { dol_print_error($this->db, $this->error); } $stock_reception_fournisseur = $this->stats_reception['qty']; } if (!empty($conf->mrp->enabled)) { - $result = $this->load_stats_inproduction(0, '1,2', 1); + $result = $this->load_stats_inproduction(0, '1,2', 1, $dateofvirtualstock); if ($result < 0) { dol_print_error($this->db, $this->error); } @@ -6196,8 +6210,6 @@ class Product extends CommonObject } } - - /** * Class to manage products or services. * Do not use 'Service' as class name since it is already used by APIs. From 0e0c297ed59f49d5a474164e835aed5f73dc0a0d Mon Sep 17 00:00:00 2001 From: lvessiller Date: Mon, 8 Aug 2022 14:56:28 +0200 Subject: [PATCH 470/826] NEW filter on reception dates (from / to) in cheque paiement card --- htdocs/compta/paiement/cheque/card.php | 38 +++++++++++++++++++++----- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/htdocs/compta/paiement/cheque/card.php b/htdocs/compta/paiement/cheque/card.php index 8c859e6e689..f41ecd820ad 100644 --- a/htdocs/compta/paiement/cheque/card.php +++ b/htdocs/compta/paiement/cheque/card.php @@ -59,8 +59,15 @@ $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; $offset = $limit * $page; $upload_dir = $conf->bank->multidir_output[$object->entity ? $object->entity : $conf->entity]."/checkdeposits"; - -$filterdate = dol_mktime(0, 0, 0, GETPOST('fdmonth'), GETPOST('fdday'), GETPOST('fdyear')); +// filter by dates from / to +$search_date_start_day = GETPOST('search_date_start_day', 'int'); +$search_date_start_month = GETPOST('search_date_start_month', 'int'); +$search_date_start_year = GETPOST('search_date_start_year', 'int'); +$search_date_end_day = GETPOST('search_date_end_day', 'int'); +$search_date_end_month = GETPOST('search_date_end_month', 'int'); +$search_date_end_year = GETPOST('search_date_end_year', 'int'); +$search_date_start = dol_mktime(0, 0, 0, $search_date_start_month, $search_date_start_day, $search_date_start_year); +$search_date_end = dol_mktime(23, 59, 59, $search_date_end_month, $search_date_end_day, $search_date_end_year); $filteraccountid = GETPOST('accountid', 'int'); // Security check @@ -265,7 +272,15 @@ if ($action == 'builddoc' && $user->rights->banque->cheque) { */ if (GETPOST('removefilter')) { - $filterdate = ''; + // filter by dates from / to + $search_date_start_day = ''; + $search_date_start_month = ''; + $search_date_start_year = ''; + $search_date_end_day = ''; + $search_date_end_month = ''; + $search_date_end_year = ''; + $search_date_start = ''; + $search_date_end = ''; $filteraccountid = 0; } @@ -352,7 +367,13 @@ if ($action == 'new') { //print '
'; // Filter print ''; print ''; } // SMTPS PW - if (isset($conf->global->MAIN_MAIL_SENDMODE) && (in_array($conf->global->MAIN_MAIL_SENDMODE, array('swiftmailer')) || (in_array($conf->global->MAIN_MAIL_SENDMODE, array('smtps')) && (isset($conf->global->MAIN_MAIL_SMTPS_AUTH_TYPE) && $conf->global->MAIN_MAIL_SMTPS_AUTH_TYPE === "LOGIN")))) { + if (isset($conf->global->MAIN_MAIL_SENDMODE) && (in_array($conf->global->MAIN_MAIL_SENDMODE, array('swiftmailer')) || (in_array($conf->global->MAIN_MAIL_SENDMODE, array('smtps')) && getDolGlobalString('MAIN_MAIL_SMTPS_AUTH_TYPE') === "LOGIN"))) { print ''; } // SMTPS oauth service - if (isset($conf->global->MAIN_MAIL_SENDMODE) && in_array($conf->global->MAIN_MAIL_SENDMODE, array('smtps')) && isset($conf->global->MAIN_MAIL_SMTPS_AUTH_TYPE) && $conf->global->MAIN_MAIL_SMTPS_AUTH_TYPE === "XOAUTH2") { + if (isset($conf->global->MAIN_MAIL_SENDMODE) && in_array($conf->global->MAIN_MAIL_SENDMODE, array('smtps')) && getDolGlobalString('MAIN_MAIL_SMTPS_AUTH_TYPE') === "XOAUTH2") { $text = $oauthservices[$conf->global->MAIN_MAIL_SMTPS_OAUTH_SERVICE]; if (empty($text)) { $text = $langs->trans("Undefined").img_warning(); diff --git a/htdocs/langs/fr_FR/admin.lang b/htdocs/langs/fr_FR/admin.lang index 42d973e8e06..18c2dfc615d 100644 --- a/htdocs/langs/fr_FR/admin.lang +++ b/htdocs/langs/fr_FR/admin.lang @@ -2291,5 +2291,5 @@ OauthNotAvailableForAllAndHadToBeCreatedBefore=L'authentification OAUTH2 n'est p MAIN_MAIL_SMTPS_OAUTH_SERVICE=Service d'authentification OAUTH2 DontForgetCreateTokenOauthMod=Un jeton avec les bonnes permissions doit avoir été créé en amont avec le module OAUTH MAIN_MAIL_SMTPS_AUTH_TYPE=Méthode d'authentication -UsePassword=Utiliser un mot de pass -UseOauth=Utiliser un jeton d'authentification OAUTH \ No newline at end of file +UsePassword=Utiliser un mot de passe +UseOauth=Utiliser un jeton d'authentification OAUTH From 32c617b78617a5c32c078d43a118b03278a22f11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 10 Aug 2022 09:54:14 +0200 Subject: [PATCH 482/826] add oauth2 for swiftmailer --- htdocs/admin/mails.php | 12 +++++----- htdocs/core/class/CMailFile.class.php | 34 +++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/htdocs/admin/mails.php b/htdocs/admin/mails.php index 03b4387b255..0504315075d 100644 --- a/htdocs/admin/mails.php +++ b/htdocs/admin/mails.php @@ -682,7 +682,7 @@ if ($action == 'edit') { print ''; // Host server - if ($linuxlike && (isset($conf->global->MAIN_MAIL_SENDMODE) && $conf->global->MAIN_MAIL_SENDMODE == 'mail')) { + if ($linuxlike && (getDolGlobalString('MAIN_MAIL_SENDMODE') == 'mail')) { print ''; } else { print ''; @@ -690,31 +690,31 @@ if ($action == 'edit') { // Port - if ($linuxlike && (isset($conf->global->MAIN_MAIL_SENDMODE) && $conf->global->MAIN_MAIL_SENDMODE == 'mail')) { + if ($linuxlike && (getDolGlobalString('MAIN_MAIL_SENDMODE') == 'mail')) { print ''; } else { print ''; } // SMTPS ID - if (isset($conf->global->MAIN_MAIL_SENDMODE) && in_array($conf->global->MAIN_MAIL_SENDMODE, array('smtps', 'swiftmailer'))) { + if (in_array(getDolGlobalString('MAIN_MAIL_SENDMODE'), array('smtps', 'swiftmailer'))) { print ''; } // AUTH method - if (isset($conf->global->MAIN_MAIL_SENDMODE) && in_array($conf->global->MAIN_MAIL_SENDMODE, array('smtps', 'swiftmailer'))) { + if (in_array(getDolGlobalString('MAIN_MAIL_SENDMODE'), array('smtps', 'swiftmailer'))) { $authtype = getDolGlobalString('MAIN_MAIL_SMTPS_AUTH_TYPE', 'LOGIN'); $text = ($authtype === "LOGIN") ? $langs->trans("UsePassword") : ($authtype === "XOAUTH2" ? $langs->trans("UseOauth") : '') ; print ''; } // SMTPS PW - if (isset($conf->global->MAIN_MAIL_SENDMODE) && (in_array($conf->global->MAIN_MAIL_SENDMODE, array('swiftmailer')) || (in_array($conf->global->MAIN_MAIL_SENDMODE, array('smtps')) && getDolGlobalString('MAIN_MAIL_SMTPS_AUTH_TYPE') === "LOGIN"))) { + if (in_array(getDolGlobalString('MAIN_MAIL_SENDMODE'), array('smtps', 'swiftmailer')) && getDolGlobalString('MAIN_MAIL_SMTPS_AUTH_TYPE') != "XOAUTH2") { print ''; } // SMTPS oauth service - if (isset($conf->global->MAIN_MAIL_SENDMODE) && in_array($conf->global->MAIN_MAIL_SENDMODE, array('smtps')) && getDolGlobalString('MAIN_MAIL_SMTPS_AUTH_TYPE') === "XOAUTH2") { + if (in_array(getDolGlobalString('MAIN_MAIL_SENDMODE'), array('smtps', 'swiftmailer')) && getDolGlobalString('MAIN_MAIL_SMTPS_AUTH_TYPE') === "XOAUTH2") { $text = $oauthservices[$conf->global->MAIN_MAIL_SMTPS_OAUTH_SERVICE]; if (empty($text)) { $text = $langs->trans("Undefined").img_warning(); diff --git a/htdocs/core/class/CMailFile.class.php b/htdocs/core/class/CMailFile.class.php index 1b03ed0d604..b991b4542f9 100644 --- a/htdocs/core/class/CMailFile.class.php +++ b/htdocs/core/class/CMailFile.class.php @@ -847,7 +847,7 @@ class CMailFile $this->smtps->setPW($loginpass); } - if (!empty($conf->global->$keyforsmtpauthtype) && $conf->global->$keyforsmtpauthtype === "XOAUTH2") { + if (getDolGlobalString($keyforsmtpauthtype) === "XOAUTH2") { require_once DOL_DOCUMENT_ROOT.'/core/lib/oauth.lib.php'; // define $supportedoauth2array $keyforsupportedoauth2array = $conf->global->$keyforsmtpoauthservice; if (preg_match('/^.*-/', $keyforsupportedoauth2array)) { @@ -943,9 +943,39 @@ class CMailFile if (!empty($conf->global->$keyforsmtpid)) { $this->transport->setUsername($conf->global->$keyforsmtpid); } - if (!empty($conf->global->$keyforsmtppw)) { + if (!empty($conf->global->$keyforsmtppw) && getDolGlobalString($keyforsmtpauthtype) != "XOAUTH2") { $this->transport->setPassword($conf->global->$keyforsmtppw); } + if (getDolGlobalString($keyforsmtpauthtype) === "XOAUTH2") { + require_once DOL_DOCUMENT_ROOT.'/core/lib/oauth.lib.php'; // define $supportedoauth2array + $keyforsupportedoauth2array = getDolGlobalString($keyforsmtpoauthservice); + if (preg_match('/^.*-/', $keyforsupportedoauth2array)) { + $keyforprovider = preg_replace('/^.*-/', '', $keyforsupportedoauth2array); + } else { + $keyforprovider = ''; + } + $keyforsupportedoauth2array = preg_replace('/-.*$/', '', $keyforsupportedoauth2array); + $keyforsupportedoauth2array = 'OAUTH_'.$keyforsupportedoauth2array.'_NAME'; + + $OAUTH_SERVICENAME = (empty($supportedoauth2array[$keyforsupportedoauth2array]['name']) ? 'Unknown' : $supportedoauth2array[$keyforsupportedoauth2array]['name'].($keyforprovider ? '-'.$keyforprovider : '')); + + require_once DOL_DOCUMENT_ROOT.'/includes/OAuth/bootstrap.php'; + + $storage = new DoliStorage($db, $conf); + try { + $tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME); + if (is_object($tokenobj)) { + $this->transport->setAuthMode('XOAUTH2'); + $this->transport->setPassword($tokenobj->getAccessToken()); + } else { + $this->errors[] = "Token not found"; + } + } catch (Exception $e) { + // Return an error if token not found + $this->errors[] = $e->getMessage(); + dol_syslog("CMailFile::sendfile: mail end error=".$this->error, LOG_ERR); + } + } if (!empty($conf->global->$keyforsslseflsigned)) { $this->transport->setStreamOptions(array('ssl' => array('allow_self_signed' => true, 'verify_peer' => false))); } From 4237f902a3aa3e1524a98f9d371955a14331e89f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 10 Aug 2022 10:09:52 +0200 Subject: [PATCH 483/826] add oauth2 for swiftmailer --- htdocs/core/actions_sendmails.inc.php | 9 +++++++-- htdocs/core/class/CMailFile.class.php | 6 +++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/htdocs/core/actions_sendmails.inc.php b/htdocs/core/actions_sendmails.inc.php index 7494f5a3668..3749b403469 100644 --- a/htdocs/core/actions_sendmails.inc.php +++ b/htdocs/core/actions_sendmails.inc.php @@ -427,9 +427,14 @@ if (($action == 'send' || $action == 'relance') && !GETPOST('addfile') && !GETPO } else { $langs->load("other"); $mesg = '
'; - if ($mailfile->error) { + if (!empty($mailfile->error) || !empty($mailfile->errors)) { $mesg .= $langs->transnoentities('ErrorFailedToSendMail', dol_escape_htmltag($from), dol_escape_htmltag($sendto)); - $mesg .= '
'.$mailfile->error; + if (!empty($mailfile->error)) { + $mesg .= '
'.$mailfile->error; + } + if (!empty($mailfile->errors) && is_array($mailfile->errors)) { + $mesg .= '
'.implode('
', $mailfile->errors); + } } else { $mesg .= $langs->transnoentities('ErrorFailedToSendMail', dol_escape_htmltag($from), dol_escape_htmltag($sendto)); if (!empty($conf->global->MAIN_DISABLE_ALL_MAILS)) { diff --git a/htdocs/core/class/CMailFile.class.php b/htdocs/core/class/CMailFile.class.php index b991b4542f9..f299ecf9a88 100644 --- a/htdocs/core/class/CMailFile.class.php +++ b/htdocs/core/class/CMailFile.class.php @@ -1008,16 +1008,16 @@ class CMailFile try { $result = $this->mailer->send($this->message, $failedRecipients); } catch (Exception $e) { - $this->error = $e->getMessage(); + $this->errors[] = $e->getMessage(); } if (!empty($conf->global->MAIN_MAIL_DEBUG)) { $this->dump_mail(); } $res = true; - if (!empty($this->error) || !$result) { + if (!empty($this->error) || !empty($this->errors) || !$result) { if (!empty($failedRecipients)) { - $this->error = 'Transport failed for the following addresses: "' . join('", "', $failedRecipients) . '".'; + $this->errors[] = 'Transport failed for the following addresses: "' . join('", "', $failedRecipients) . '".'; } dol_syslog("CMailFile::sendfile: mail end error=".$this->error, LOG_ERR); $res = false; From 8581156402eb2421bbd3753050007086b709f436 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 10 Aug 2022 10:59:57 +0200 Subject: [PATCH 484/826] add oauth2 for swiftmailer --- htdocs/core/class/CMailFile.class.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/htdocs/core/class/CMailFile.class.php b/htdocs/core/class/CMailFile.class.php index f299ecf9a88..fddd06f89b2 100644 --- a/htdocs/core/class/CMailFile.class.php +++ b/htdocs/core/class/CMailFile.class.php @@ -75,6 +75,16 @@ class CMailFile public $smtps; // Contains SMTPs object (if this method is used) public $phpmailer; // Contains PHPMailer object (if this method is used) + /** + * @var Swift_SmtpTransport + */ + public $transport; + + /** + * @var Swift_Mailer + */ + public $mailer; + /** * @var string CSS */ From 6f6ced5b9c9a48019c337b5624e6b6ca9dfd3898 Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Wed, 10 Aug 2022 13:31:44 +0200 Subject: [PATCH 485/826] Update note.php $help_url + DE:Modul_Produkte + DE:Modul_Leistungen --- htdocs/product/note.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/product/note.php b/htdocs/product/note.php index c54bd3637ae..93d40e296e9 100644 --- a/htdocs/product/note.php +++ b/htdocs/product/note.php @@ -86,21 +86,21 @@ $form = new Form($db); $help_url = ''; if (GETPOST("type") == '0' || ($object->type == Product::TYPE_PRODUCT)) { - $help_url = 'EN:Module_Products|FR:Module_Produits|ES:Módulo_Productos'; + $help_url = 'EN:Module_Products|FR:Module_Produits|ES:Módulo_Productos|DE:Modul_Produkte'; } if (GETPOST("type") == '1' || ($object->type == Product::TYPE_SERVICE)) { - $help_url = 'EN:Module_Services_En|FR:Module_Services|ES:Módulo_Servicios'; + $help_url = 'EN:Module_Services_En|FR:Module_Services|ES:Módulo_Servicios|DE:Modul_Leistungen'; } $title = $langs->trans('ProductServiceCard'); $shortlabel = dol_trunc($object->label, 16); if (GETPOST("type") == '0' || ($object->type == Product::TYPE_PRODUCT)) { $title = $langs->trans('Product')." ".$shortlabel." - ".$langs->trans('Notes'); - $help_url = 'EN:Module_Products|FR:Module_Produits|ES:Módulo_Productos'; + $help_url = 'EN:Module_Products|FR:Module_Produits|ES:Módulo_Productos|DE:Modul_Produkte'; } if (GETPOST("type") == '1' || ($object->type == Product::TYPE_SERVICE)) { $title = $langs->trans('Service')." ".$shortlabel." - ".$langs->trans('Notes'); - $help_url = 'EN:Module_Services_En|FR:Module_Services|ES:Módulo_Servicios'; + $help_url = 'EN:Module_Services_En|FR:Module_Services|ES:Módulo_Servicios|DE:Modul_Leistungen'; } llxHeader('', $title, $help_url); From a8a107fb376023ea1bce77ffca9fd5d330053bad Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Wed, 10 Aug 2022 13:37:15 +0200 Subject: [PATCH 486/826] Update index.php delete double entry: $taskstatic = new Task($db); --- htdocs/projet/activity/index.php | 1 - 1 file changed, 1 deletion(-) diff --git a/htdocs/projet/activity/index.php b/htdocs/projet/activity/index.php index 453a4078978..bbd9442f876 100644 --- a/htdocs/projet/activity/index.php +++ b/htdocs/projet/activity/index.php @@ -66,7 +66,6 @@ $month = $tmp['mon']; $year = $tmp['year']; $projectstatic = new Project($db); -$taskstatic = new Task($db); $projectsListId = $projectstatic->getProjectsAuthorizedForUser($user, 0, 1); // Return all projects I have permission on because I want my tasks and some of my task may be on a public projet that is not my project $taskstatic = new Task($db); $tasktmp = new Task($db); From 917ab403ff989bec9b081780ab39969e8b13d378 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 10 Aug 2022 13:38:18 +0200 Subject: [PATCH 487/826] wip --- htdocs/core/class/CMailFile.class.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/htdocs/core/class/CMailFile.class.php b/htdocs/core/class/CMailFile.class.php index fddd06f89b2..8963ded6be8 100644 --- a/htdocs/core/class/CMailFile.class.php +++ b/htdocs/core/class/CMailFile.class.php @@ -72,6 +72,11 @@ class CMailFile */ public $error = ''; + /** + * @var string[] Array of Error code (or message) + */ + public $errors = array(); + public $smtps; // Contains SMTPs object (if this method is used) public $phpmailer; // Contains PHPMailer object (if this method is used) @@ -85,6 +90,11 @@ class CMailFile */ public $mailer; + /** + * @var Swift_Plugins_Loggers_ArrayLogger + */ + public $logger; + /** * @var string CSS */ From bf704ec3608dd065429feacee737a14daa1c882d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 10 Aug 2022 13:41:30 +0200 Subject: [PATCH 488/826] remove duplicate --- htdocs/langs/en_US/admin.lang | 1 - 1 file changed, 1 deletion(-) diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 6215867920d..69a1f97e0e5 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -2296,4 +2296,3 @@ UsePassword=Use a password UseOauth=Use a OAUTH token Images=Images MaxNumberOfImagesInGetPost=Max number of images allowed in GETPOST check -CIDLookupURL=The module brings an URL that can be used by an external tool to get the name of a thirdparty or contact from its phone number. URL to use is: From af8abecbd6e97ebb812017fb35e32f46179454ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 10 Aug 2022 13:50:42 +0200 Subject: [PATCH 489/826] wip --- htdocs/core/class/CMailFile.class.php | 1 - 1 file changed, 1 deletion(-) diff --git a/htdocs/core/class/CMailFile.class.php b/htdocs/core/class/CMailFile.class.php index 8963ded6be8..161be6dc72e 100644 --- a/htdocs/core/class/CMailFile.class.php +++ b/htdocs/core/class/CMailFile.class.php @@ -917,7 +917,6 @@ class CMailFile } $result = $this->smtps->sendMsg(); - //print $result; if (!empty($conf->global->MAIN_MAIL_DEBUG)) { $this->dump_mail(); From 4c76223d639889de549696cd96b6ab5276ed6721 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 10 Aug 2022 14:09:14 +0200 Subject: [PATCH 490/826] Doc --- htdocs/conf/conf.php.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/conf/conf.php.example b/htdocs/conf/conf.php.example index 487576ed058..b58ac33707e 100644 --- a/htdocs/conf/conf.php.example +++ b/htdocs/conf/conf.php.example @@ -185,7 +185,7 @@ $dolibarr_main_instance_unique_id='84b5bc91f83b56e458db71e0adac2b62'; // values using a ",". In this case, Dolibarr will check login/pass for each value in // order defined into value. However, note that this can't work with all values. // Examples: -// $dolibarr_main_authentication='dolibarr'; // Use the password defined into application on user record. +// $dolibarr_main_authentication='dolibarr'; // Use the password defined into application on user file (default). // $dolibarr_main_authentication='http'; // Use the HTTP Basic authentication // $dolibarr_main_authentication='ldap'; // Check the password into a LDAP server // $dolibarr_main_authentication='ldap,dolibarr'; // You can set several mode using a comma as a separator. From 8465c0825371a46f8d25ec5f921e3867b091ae32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 10 Aug 2022 14:29:13 +0200 Subject: [PATCH 491/826] fix php8 warning --- htdocs/admin/mails_senderprofile_list.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/admin/mails_senderprofile_list.php b/htdocs/admin/mails_senderprofile_list.php index 8e31d0e6d62..db92c33a7fb 100644 --- a/htdocs/admin/mails_senderprofile_list.php +++ b/htdocs/admin/mails_senderprofile_list.php @@ -557,6 +557,7 @@ if (!empty($extrafields->attributes[$object->table_element]['computed']) && is_a // -------------------------------------------------------------------- $i = 0; $totalarray = array(); +$totalarray['nbfield'] = 0; while ($i < ($limit ? min($num, $limit) : $num)) { $obj = $db->fetch_object($resql); if (empty($obj)) { From cded29f684b3f1d40014707431fff7307e4a526a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 10 Aug 2022 14:36:29 +0200 Subject: [PATCH 492/826] fix php8 warning --- htdocs/core/class/html.formmail.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php index c23545a34c9..4652081c0f3 100644 --- a/htdocs/core/class/html.formmail.class.php +++ b/htdocs/core/class/html.formmail.class.php @@ -4,7 +4,7 @@ * Copyright (C) 2010-2011 Juanjo Menent * Copyright (C) 2015-2017 Marcos García * Copyright (C) 2015-2017 Nicolas ZABOURI - * Copyright (C) 2018-2021 Frédéric France + * Copyright (C) 2018-2022 Frédéric France * Copyright (C) 2022 Charlene Benke * * This program is free software; you can redistribute it and/or modify @@ -401,7 +401,7 @@ class FormMail extends Form // Define output language $outputlangs = $langs; $newlang = ''; - if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && !empty($this->param['langsmodels'])) { $newlang = $this->param['langsmodels']; } if (!empty($newlang)) { From 5377c6c05522ca0ec90fd6d28a1bc6aee19105e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 10 Aug 2022 14:38:38 +0200 Subject: [PATCH 493/826] fix php8 warning --- htdocs/core/class/html.formmail.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php index c23545a34c9..85cfba6cacd 100644 --- a/htdocs/core/class/html.formmail.class.php +++ b/htdocs/core/class/html.formmail.class.php @@ -428,7 +428,7 @@ class FormMail extends Form $keytoavoidconflict = empty($this->trackid) ? '' : '-'.$this->trackid; // this->trackid must be defined if (GETPOST('mode', 'alpha') == 'init' || (GETPOST('modelselected') && GETPOST('modelmailselected', 'alpha') && GETPOST('modelmailselected', 'alpha') != '-1')) { - if (!empty($arraydefaultmessage->joinfiles) && is_array($this->param['fileinit'])) { + if (!empty($arraydefaultmessage->joinfiles) && !empty($this->param['fileinit']) && is_array($this->param['fileinit'])) { foreach ($this->param['fileinit'] as $file) { $this->add_attached_files($file, basename($file), dol_mimetype($file)); } From 78c5521d808506c9080aa6c1d1b8b9f844221e11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 10 Aug 2022 14:42:07 +0200 Subject: [PATCH 494/826] fix php8 warning --- htdocs/core/class/html.formmail.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php index c23545a34c9..ee8b382f947 100644 --- a/htdocs/core/class/html.formmail.class.php +++ b/htdocs/core/class/html.formmail.class.php @@ -1182,7 +1182,7 @@ class FormMail extends Form { global $conf, $langs; //if (! $this->errorstomail) $this->errorstomail=$this->frommail; - $errorstomail = (!empty($conf->global->MAIN_MAIL_ERRORS_TO) ? $conf->global->MAIN_MAIL_ERRORS_TO : $this->errorstomail); + $errorstomail = getDolGlobalString('MAIN_MAIL_ERRORS_TO', (!empty($this->errorstomail) ? $this->errorstomail : '')); if ($this->witherrorstoreadonly) { $out = '
",i.document[0]).appendTo(t)):"tr"===n?i._createTrPlaceholder(i.currentItem,t):"img"===n&&t.attr("src",i.currentItem.attr("src")),s||t.css("visibility","hidden"),t},update:function(t,e){s&&!o.forcePlaceholderSize||(e.height()&&(!o.forcePlaceholderSize||"tbody"!==n&&"tr"!==n)||e.height(i.currentItem.innerHeight()-parseInt(i.currentItem.css("paddingTop")||0,10)-parseInt(i.currentItem.css("paddingBottom")||0,10)),e.width()||e.width(i.currentItem.innerWidth()-parseInt(i.currentItem.css("paddingLeft")||0,10)-parseInt(i.currentItem.css("paddingRight")||0,10)))}}),i.placeholder=V(o.placeholder.element.call(i.element,i.currentItem)),i.currentItem.after(i.placeholder),o.placeholder.update(i,i.placeholder)},_createTrPlaceholder:function(t,e){var i=this;t.children().each(function(){V("",i.document[0]).attr("colspan",V(this).attr("colspan")||1).appendTo(e)})},_contactContainers:function(t){for(var e,i,s,n,o,a,r,l,h,c=null,u=null,d=this.containers.length-1;0<=d;d--)V.contains(this.currentItem[0],this.containers[d].element[0])||(this._intersectsWith(this.containers[d].containerCache)?c&&V.contains(this.containers[d].element[0],c.element[0])||(c=this.containers[d],u=d):this.containers[d].containerCache.over&&(this.containers[d]._trigger("out",t,this._uiHash(this)),this.containers[d].containerCache.over=0));if(c)if(1===this.containers.length)this.containers[u].containerCache.over||(this.containers[u]._trigger("over",t,this._uiHash(this)),this.containers[u].containerCache.over=1);else{for(i=1e4,s=null,n=(l=c.floating||this._isFloating(this.currentItem))?"left":"top",o=l?"width":"height",h=l?"pageX":"pageY",e=this.items.length-1;0<=e;e--)V.contains(this.containers[u].element[0],this.items[e].item[0])&&this.items[e].item[0]!==this.currentItem[0]&&(a=this.items[e].item.offset()[n],r=!1,t[h]-a>this.items[e][o]/2&&(r=!0),Math.abs(t[h]-a)this.containment[2]&&(i=this.containment[2]+this.offset.click.left),t.pageY-this.offset.click.top>this.containment[3]&&(s=this.containment[3]+this.offset.click.top)),e.grid&&(t=this.originalPageY+Math.round((s-this.originalPageY)/e.grid[1])*e.grid[1],s=!this.containment||t-this.offset.click.top>=this.containment[1]&&t-this.offset.click.top<=this.containment[3]?t:t-this.offset.click.top>=this.containment[1]?t-e.grid[1]:t+e.grid[1],t=this.originalPageX+Math.round((i-this.originalPageX)/e.grid[0])*e.grid[0],i=!this.containment||t-this.offset.click.left>=this.containment[0]&&t-this.offset.click.left<=this.containment[2]?t:t-this.offset.click.left>=this.containment[0]?t-e.grid[0]:t+e.grid[0])),{top:s-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():o?0:n.scrollTop()),left:i-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():o?0:n.scrollLeft())}},_rearrange:function(t,e,i,s){i?i[0].appendChild(this.placeholder[0]):e.item[0].parentNode.insertBefore(this.placeholder[0],"down"===this.direction?e.item[0]:e.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var n=this.counter;this._delay(function(){n===this.counter&&this.refreshPositions(!s)})},_clear:function(t,e){this.reverting=!1;var i,s=[];if(!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null,this.helper[0]===this.currentItem[0]){for(i in this._storedCSS)"auto"!==this._storedCSS[i]&&"static"!==this._storedCSS[i]||(this._storedCSS[i]="");this.currentItem.css(this._storedCSS),this._removeClass(this.currentItem,"ui-sortable-helper")}else this.currentItem.show();function n(e,i,s){return function(t){s._trigger(e,t,i._uiHash(i))}}for(this.fromOutside&&!e&&s.push(function(t){this._trigger("receive",t,this._uiHash(this.fromOutside))}),!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(".ui-sortable-helper")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||e||s.push(function(t){this._trigger("update",t,this._uiHash())}),this!==this.currentContainer&&(e||(s.push(function(t){this._trigger("remove",t,this._uiHash())}),s.push(function(e){return function(t){e._trigger("receive",t,this._uiHash(this))}}.call(this,this.currentContainer)),s.push(function(e){return function(t){e._trigger("update",t,this._uiHash(this))}}.call(this,this.currentContainer)))),i=this.containers.length-1;0<=i;i--)e||s.push(n("deactivate",this,this.containers[i])),this.containers[i].containerCache.over&&(s.push(n("out",this,this.containers[i])),this.containers[i].containerCache.over=0);if(this.storedCursor&&(this.document.find("body").css("cursor",this.storedCursor),this.storedStylesheet.remove()),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex","auto"===this._storedZIndex?"":this._storedZIndex),this.dragging=!1,e||this._trigger("beforeStop",t,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.cancelHelperRemoval||(this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null),!e){for(i=0;i",widgetEventPrefix:"spin",options:{classes:{"ui-spinner":"ui-corner-all","ui-spinner-down":"ui-corner-br","ui-spinner-up":"ui-corner-tr"},culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),""!==this.value()&&this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var s=this._super(),n=this.element;return V.each(["min","max","step"],function(t,e){var i=n.attr(e);null!=i&&i.length&&(s[e]=i)}),s},_events:{keydown:function(t){this._start(t)&&this._keydown(t)&&t.preventDefault()},keyup:"_stop",focus:function(){this.previous=this.element.val()},blur:function(t){this.cancelBlur?delete this.cancelBlur:(this._stop(),this._refresh(),this.previous!==this.element.val()&&this._trigger("change",t))},mousewheel:function(t,e){var i=V.ui.safeActiveElement(this.document[0]);if(this.element[0]===i&&e){if(!this.spinning&&!this._start(t))return!1;this._spin((0").parent().append("")},_draw:function(){this._enhance(),this._addClass(this.uiSpinner,"ui-spinner","ui-widget ui-widget-content"),this._addClass("ui-spinner-input"),this.element.attr("role","spinbutton"),this.buttons=this.uiSpinner.children("a").attr("tabIndex",-1).attr("aria-hidden",!0).button({classes:{"ui-button":""}}),this._removeClass(this.buttons,"ui-corner-all"),this._addClass(this.buttons.first(),"ui-spinner-button ui-spinner-up"),this._addClass(this.buttons.last(),"ui-spinner-button ui-spinner-down"),this.buttons.first().button({icon:this.options.icons.up,showLabel:!1}),this.buttons.last().button({icon:this.options.icons.down,showLabel:!1}),this.buttons.height()>Math.ceil(.5*this.uiSpinner.height())&&0e.max?e.max:null!==e.min&&t"},_buttonHtml:function(){return""}});var ct;V.ui.spinner;V.widget("ui.tabs",{version:"1.13.1",delay:300,options:{active:null,classes:{"ui-tabs":"ui-corner-all","ui-tabs-nav":"ui-corner-all","ui-tabs-panel":"ui-corner-bottom","ui-tabs-tab":"ui-corner-top"},collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_isLocal:(ct=/#.*$/,function(t){var e=t.href.replace(ct,""),i=location.href.replace(ct,"");try{e=decodeURIComponent(e)}catch(t){}try{i=decodeURIComponent(i)}catch(t){}return 1?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var t=this.options,e=this.tablist.children(":has(a[href])");t.disabled=V.map(e.filter(".ui-state-disabled"),function(t){return e.index(t)}),this._processTabs(),!1!==t.active&&this.anchors.length?this.active.length&&!V.contains(this.tablist[0],this.active[0])?this.tabs.length===t.disabled.length?(t.active=!1,this.active=V()):this._activate(this._findNextTab(Math.max(0,t.active-1),!1)):t.active=this.tabs.index(this.active):(t.active=!1,this.active=V()),this._refresh()},_refresh:function(){this._setOptionDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-hidden":"true"}),this.active.length?(this.active.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}),this._addClass(this.active,"ui-tabs-active","ui-state-active"),this._getPanelForTab(this.active).show().attr({"aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var l=this,t=this.tabs,e=this.anchors,i=this.panels;this.tablist=this._getList().attr("role","tablist"),this._addClass(this.tablist,"ui-tabs-nav","ui-helper-reset ui-helper-clearfix ui-widget-header"),this.tablist.on("mousedown"+this.eventNamespace,"> li",function(t){V(this).is(".ui-state-disabled")&&t.preventDefault()}).on("focus"+this.eventNamespace,".ui-tabs-anchor",function(){V(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this.tabs=this.tablist.find("> li:has(a[href])").attr({role:"tab",tabIndex:-1}),this._addClass(this.tabs,"ui-tabs-tab","ui-state-default"),this.anchors=this.tabs.map(function(){return V("a",this)[0]}).attr({tabIndex:-1}),this._addClass(this.anchors,"ui-tabs-anchor"),this.panels=V(),this.anchors.each(function(t,e){var i,s,n,o=V(e).uniqueId().attr("id"),a=V(e).closest("li"),r=a.attr("aria-controls");l._isLocal(e)?(n=(i=e.hash).substring(1),s=l.element.find(l._sanitizeSelector(i))):(n=a.attr("aria-controls")||V({}).uniqueId()[0].id,(s=l.element.find(i="#"+n)).length||(s=l._createPanel(n)).insertAfter(l.panels[t-1]||l.tablist),s.attr("aria-live","polite")),s.length&&(l.panels=l.panels.add(s)),r&&a.data("ui-tabs-aria-controls",r),a.attr({"aria-controls":n,"aria-labelledby":o}),s.attr("aria-labelledby",o)}),this.panels.attr("role","tabpanel"),this._addClass(this.panels,"ui-tabs-panel","ui-widget-content"),t&&(this._off(t.not(this.tabs)),this._off(e.not(this.anchors)),this._off(i.not(this.panels)))},_getList:function(){return this.tablist||this.element.find("ol, ul").eq(0)},_createPanel:function(t){return V("
").attr("id",t).data("ui-tabs-destroy",!0)},_setOptionDisabled:function(t){var e,i;for(Array.isArray(t)&&(t.length?t.length===this.anchors.length&&(t=!0):t=!1),i=0;e=this.tabs[i];i++)e=V(e),!0===t||-1!==V.inArray(i,t)?(e.attr("aria-disabled","true"),this._addClass(e,null,"ui-state-disabled")):(e.removeAttr("aria-disabled"),this._removeClass(e,null,"ui-state-disabled"));this.options.disabled=t,this._toggleClass(this.widget(),this.widgetFullName+"-disabled",null,!0===t)},_setupEvents:function(t){var i={};t&&V.each(t.split(" "),function(t,e){i[e]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(!0,this.anchors,{click:function(t){t.preventDefault()}}),this._on(this.anchors,i),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(t){var i,e=this.element.parent();"fill"===t?(i=e.height(),i-=this.element.outerHeight()-this.element.height(),this.element.siblings(":visible").each(function(){var t=V(this),e=t.css("position");"absolute"!==e&&"fixed"!==e&&(i-=t.outerHeight(!0))}),this.element.children().not(this.panels).each(function(){i-=V(this).outerHeight(!0)}),this.panels.each(function(){V(this).height(Math.max(0,i-V(this).innerHeight()+V(this).height()))}).css("overflow","auto")):"auto"===t&&(i=0,this.panels.each(function(){i=Math.max(i,V(this).height("").height())}).height(i))},_eventHandler:function(t){var e=this.options,i=this.active,s=V(t.currentTarget).closest("li"),n=s[0]===i[0],o=n&&e.collapsible,a=o?V():this._getPanelForTab(s),r=i.length?this._getPanelForTab(i):V(),i={oldTab:i,oldPanel:r,newTab:o?V():s,newPanel:a};t.preventDefault(),s.hasClass("ui-state-disabled")||s.hasClass("ui-tabs-loading")||this.running||n&&!e.collapsible||!1===this._trigger("beforeActivate",t,i)||(e.active=!o&&this.tabs.index(s),this.active=n?V():s,this.xhr&&this.xhr.abort(),r.length||a.length||V.error("jQuery UI Tabs: Mismatching fragment identifier."),a.length&&this.load(this.tabs.index(s),t),this._toggle(t,i))},_toggle:function(t,e){var i=this,s=e.newPanel,n=e.oldPanel;function o(){i.running=!1,i._trigger("activate",t,e)}function a(){i._addClass(e.newTab.closest("li"),"ui-tabs-active","ui-state-active"),s.length&&i.options.show?i._show(s,i.options.show,o):(s.show(),o())}this.running=!0,n.length&&this.options.hide?this._hide(n,this.options.hide,function(){i._removeClass(e.oldTab.closest("li"),"ui-tabs-active","ui-state-active"),a()}):(this._removeClass(e.oldTab.closest("li"),"ui-tabs-active","ui-state-active"),n.hide(),a()),n.attr("aria-hidden","true"),e.oldTab.attr({"aria-selected":"false","aria-expanded":"false"}),s.length&&n.length?e.oldTab.attr("tabIndex",-1):s.length&&this.tabs.filter(function(){return 0===V(this).attr("tabIndex")}).attr("tabIndex",-1),s.attr("aria-hidden","false"),e.newTab.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0})},_activate:function(t){var t=this._findActive(t);t[0]!==this.active[0]&&(t=(t=!t.length?this.active:t).find(".ui-tabs-anchor")[0],this._eventHandler({target:t,currentTarget:t,preventDefault:V.noop}))},_findActive:function(t){return!1===t?V():this.tabs.eq(t)},_getIndex:function(t){return t="string"==typeof t?this.anchors.index(this.anchors.filter("[href$='"+V.escapeSelector(t)+"']")):t},_destroy:function(){this.xhr&&this.xhr.abort(),this.tablist.removeAttr("role").off(this.eventNamespace),this.anchors.removeAttr("role tabIndex").removeUniqueId(),this.tabs.add(this.panels).each(function(){V.data(this,"ui-tabs-destroy")?V(this).remove():V(this).removeAttr("role tabIndex aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded")}),this.tabs.each(function(){var t=V(this),e=t.data("ui-tabs-aria-controls");e?t.attr("aria-controls",e).removeData("ui-tabs-aria-controls"):t.removeAttr("aria-controls")}),this.panels.show(),"content"!==this.options.heightStyle&&this.panels.css("height","")},enable:function(i){var t=this.options.disabled;!1!==t&&(t=void 0!==i&&(i=this._getIndex(i),Array.isArray(t)?V.map(t,function(t){return t!==i?t:null}):V.map(this.tabs,function(t,e){return e!==i?e:null})),this._setOptionDisabled(t))},disable:function(t){var e=this.options.disabled;if(!0!==e){if(void 0===t)e=!0;else{if(t=this._getIndex(t),-1!==V.inArray(t,e))return;e=Array.isArray(e)?V.merge([t],e).sort():[t]}this._setOptionDisabled(e)}},load:function(t,s){t=this._getIndex(t);function n(t,e){"abort"===e&&o.panels.stop(!1,!0),o._removeClass(i,"ui-tabs-loading"),a.removeAttr("aria-busy"),t===o.xhr&&delete o.xhr}var o=this,i=this.tabs.eq(t),t=i.find(".ui-tabs-anchor"),a=this._getPanelForTab(i),r={tab:i,panel:a};this._isLocal(t[0])||(this.xhr=V.ajax(this._ajaxSettings(t,s,r)),this.xhr&&"canceled"!==this.xhr.statusText&&(this._addClass(i,"ui-tabs-loading"),a.attr("aria-busy","true"),this.xhr.done(function(t,e,i){setTimeout(function(){a.html(t),o._trigger("load",s,r),n(i,e)},1)}).fail(function(t,e){setTimeout(function(){n(t,e)},1)})))},_ajaxSettings:function(t,i,s){var n=this;return{url:t.attr("href").replace(/#.*$/,""),beforeSend:function(t,e){return n._trigger("beforeLoad",i,V.extend({jqXHR:t,ajaxSettings:e},s))}}},_getPanelForTab:function(t){t=V(t).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+t))}}),!1!==V.uiBackCompat&&V.widget("ui.tabs",V.ui.tabs,{_processTabs:function(){this._superApply(arguments),this._addClass(this.tabs,"ui-tab")}});V.ui.tabs;V.widget("ui.tooltip",{version:"1.13.1",options:{classes:{"ui-tooltip":"ui-corner-all ui-widget-shadow"},content:function(){var t=V(this).attr("title");return V("").text(t).html()},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,track:!1,close:null,open:null},_addDescribedBy:function(t,e){var i=(t.attr("aria-describedby")||"").split(/\s+/);i.push(e),t.data("ui-tooltip-id",e).attr("aria-describedby",String.prototype.trim.call(i.join(" ")))},_removeDescribedBy:function(t){var e=t.data("ui-tooltip-id"),i=(t.attr("aria-describedby")||"").split(/\s+/),e=V.inArray(e,i);-1!==e&&i.splice(e,1),t.removeData("ui-tooltip-id"),(i=String.prototype.trim.call(i.join(" ")))?t.attr("aria-describedby",i):t.removeAttr("aria-describedby")},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.liveRegion=V("
").attr({role:"log","aria-live":"assertive","aria-relevant":"additions"}).appendTo(this.document[0].body),this._addClass(this.liveRegion,null,"ui-helper-hidden-accessible"),this.disabledTitles=V([])},_setOption:function(t,e){var i=this;this._super(t,e),"content"===t&&V.each(this.tooltips,function(t,e){i._updateContent(e.element)})},_setOptionDisabled:function(t){this[t?"_disable":"_enable"]()},_disable:function(){var s=this;V.each(this.tooltips,function(t,e){var i=V.Event("blur");i.target=i.currentTarget=e.element[0],s.close(i,!0)}),this.disabledTitles=this.disabledTitles.add(this.element.find(this.options.items).addBack().filter(function(){var t=V(this);if(t.is("[title]"))return t.data("ui-tooltip-title",t.attr("title")).removeAttr("title")}))},_enable:function(){this.disabledTitles.each(function(){var t=V(this);t.data("ui-tooltip-title")&&t.attr("title",t.data("ui-tooltip-title"))}),this.disabledTitles=V([])},open:function(t){var i=this,e=V(t?t.target:this.element).closest(this.options.items);e.length&&!e.data("ui-tooltip-id")&&(e.attr("title")&&e.data("ui-tooltip-title",e.attr("title")),e.data("ui-tooltip-open",!0),t&&"mouseover"===t.type&&e.parents().each(function(){var t,e=V(this);e.data("ui-tooltip-open")&&((t=V.Event("blur")).target=t.currentTarget=this,i.close(t,!0)),e.attr("title")&&(e.uniqueId(),i.parents[this.id]={element:this,title:e.attr("title")},e.attr("title",""))}),this._registerCloseHandlers(t,e),this._updateContent(e,t))},_updateContent:function(e,i){var t=this.options.content,s=this,n=i?i.type:null;if("string"==typeof t||t.nodeType||t.jquery)return this._open(i,e,t);(t=t.call(e[0],function(t){s._delay(function(){e.data("ui-tooltip-open")&&(i&&(i.type=n),this._open(i,e,t))})}))&&this._open(i,e,t)},_open:function(t,e,i){var s,n,o,a=V.extend({},this.options.position);function r(t){a.of=t,n.is(":hidden")||n.position(a)}i&&((s=this._find(e))?s.tooltip.find(".ui-tooltip-content").html(i):(e.is("[title]")&&(t&&"mouseover"===t.type?e.attr("title",""):e.removeAttr("title")),s=this._tooltip(e),n=s.tooltip,this._addDescribedBy(e,n.attr("id")),n.find(".ui-tooltip-content").html(i),this.liveRegion.children().hide(),(i=V("
").html(n.find(".ui-tooltip-content").html())).removeAttr("name").find("[name]").removeAttr("name"),i.removeAttr("id").find("[id]").removeAttr("id"),i.appendTo(this.liveRegion),this.options.track&&t&&/^mouse/.test(t.type)?(this._on(this.document,{mousemove:r}),r(t)):n.position(V.extend({of:e},this.options.position)),n.hide(),this._show(n,this.options.show),this.options.track&&this.options.show&&this.options.show.delay&&(o=this.delayedShow=setInterval(function(){n.is(":visible")&&(r(a.of),clearInterval(o))},13)),this._trigger("open",t,{tooltip:n})))},_registerCloseHandlers:function(t,e){var i={keyup:function(t){t.keyCode===V.ui.keyCode.ESCAPE&&((t=V.Event(t)).currentTarget=e[0],this.close(t,!0))}};e[0]!==this.element[0]&&(i.remove=function(){var t=this._find(e);t&&this._removeTooltip(t.tooltip)}),t&&"mouseover"!==t.type||(i.mouseleave="close"),t&&"focusin"!==t.type||(i.focusout="close"),this._on(!0,e,i)},close:function(t){var e,i=this,s=V(t?t.currentTarget:this.element),n=this._find(s);n?(e=n.tooltip,n.closing||(clearInterval(this.delayedShow),s.data("ui-tooltip-title")&&!s.attr("title")&&s.attr("title",s.data("ui-tooltip-title")),this._removeDescribedBy(s),n.hiding=!0,e.stop(!0),this._hide(e,this.options.hide,function(){i._removeTooltip(V(this))}),s.removeData("ui-tooltip-open"),this._off(s,"mouseleave focusout keyup"),s[0]!==this.element[0]&&this._off(s,"remove"),this._off(this.document,"mousemove"),t&&"mouseleave"===t.type&&V.each(this.parents,function(t,e){V(e.element).attr("title",e.title),delete i.parents[t]}),n.closing=!0,this._trigger("close",t,{tooltip:e}),n.hiding||(n.closing=!1))):s.removeData("ui-tooltip-open")},_tooltip:function(t){var e=V("
").attr("role","tooltip"),i=V("
").appendTo(e),s=e.uniqueId().attr("id");return this._addClass(i,"ui-tooltip-content"),this._addClass(e,"ui-tooltip","ui-widget ui-widget-content"),e.appendTo(this._appendTo(t)),this.tooltips[s]={element:t,tooltip:e}},_find:function(t){t=t.data("ui-tooltip-id");return t?this.tooltips[t]:null},_removeTooltip:function(t){clearInterval(this.delayedShow),t.remove(),delete this.tooltips[t.attr("id")]},_appendTo:function(t){t=t.closest(".ui-front, dialog");return t=!t.length?this.document[0].body:t},_destroy:function(){var s=this;V.each(this.tooltips,function(t,e){var i=V.Event("blur"),e=e.element;i.target=i.currentTarget=e[0],s.close(i,!0),V("#"+t).remove(),e.data("ui-tooltip-title")&&(e.attr("title")||e.attr("title",e.data("ui-tooltip-title")),e.removeData("ui-tooltip-title"))}),this.liveRegion.remove()}}),!1!==V.uiBackCompat&&V.widget("ui.tooltip",V.ui.tooltip,{options:{tooltipClass:null},_tooltip:function(){var t=this._superApply(arguments);return this.options.tooltipClass&&t.tooltip.addClass(this.options.tooltipClass),t}});V.ui.tooltip}); \ No newline at end of file +!function(t){"use strict";"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)}(function(V){"use strict";V.ui=V.ui||{};V.ui.version="1.13.2";var n,i=0,a=Array.prototype.hasOwnProperty,r=Array.prototype.slice;V.cleanData=(n=V.cleanData,function(t){for(var e,i,s=0;null!=(i=t[s]);s++)(e=V._data(i,"events"))&&e.remove&&V(i).triggerHandler("remove");n(t)}),V.widget=function(t,i,e){var s,n,o,a={},r=t.split(".")[0],l=r+"-"+(t=t.split(".")[1]);return e||(e=i,i=V.Widget),Array.isArray(e)&&(e=V.extend.apply(null,[{}].concat(e))),V.expr.pseudos[l.toLowerCase()]=function(t){return!!V.data(t,l)},V[r]=V[r]||{},s=V[r][t],n=V[r][t]=function(t,e){if(!this||!this._createWidget)return new n(t,e);arguments.length&&this._createWidget(t,e)},V.extend(n,s,{version:e.version,_proto:V.extend({},e),_childConstructors:[]}),(o=new i).options=V.widget.extend({},o.options),V.each(e,function(e,s){function n(){return i.prototype[e].apply(this,arguments)}function o(t){return i.prototype[e].apply(this,t)}a[e]="function"==typeof s?function(){var t,e=this._super,i=this._superApply;return this._super=n,this._superApply=o,t=s.apply(this,arguments),this._super=e,this._superApply=i,t}:s}),n.prototype=V.widget.extend(o,{widgetEventPrefix:s&&o.widgetEventPrefix||t},a,{constructor:n,namespace:r,widgetName:t,widgetFullName:l}),s?(V.each(s._childConstructors,function(t,e){var i=e.prototype;V.widget(i.namespace+"."+i.widgetName,n,e._proto)}),delete s._childConstructors):i._childConstructors.push(n),V.widget.bridge(t,n),n},V.widget.extend=function(t){for(var e,i,s=r.call(arguments,1),n=0,o=s.length;n",options:{classes:{},disabled:!1,create:null},_createWidget:function(t,e){e=V(e||this.defaultElement||this)[0],this.element=V(e),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=V(),this.hoverable=V(),this.focusable=V(),this.classesElementLookup={},e!==this&&(V.data(e,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===e&&this.destroy()}}),this.document=V(e.style?e.ownerDocument:e.document||e),this.window=V(this.document[0].defaultView||this.document[0].parentWindow)),this.options=V.widget.extend({},this.options,this._getCreateOptions(),t),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:V.noop,_create:V.noop,_init:V.noop,destroy:function(){var i=this;this._destroy(),V.each(this.classesElementLookup,function(t,e){i._removeClass(e,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:V.noop,widget:function(){return this.element},option:function(t,e){var i,s,n,o=t;if(0===arguments.length)return V.widget.extend({},this.options);if("string"==typeof t)if(o={},t=(i=t.split(".")).shift(),i.length){for(s=o[t]=V.widget.extend({},this.options[t]),n=0;n
"),i=e.children()[0];return V("body").append(e),t=i.offsetWidth,e.css("overflow","scroll"),t===(i=i.offsetWidth)&&(i=e[0].clientWidth),e.remove(),s=t-i},getScrollInfo:function(t){var e=t.isWindow||t.isDocument?"":t.element.css("overflow-x"),i=t.isWindow||t.isDocument?"":t.element.css("overflow-y"),e="scroll"===e||"auto"===e&&t.widthx(k(s),k(n))?o.important="horizontal":o.important="vertical",u.using.call(this,t,o)}),a.offset(V.extend(h,{using:t}))})},V.ui.position={fit:{left:function(t,e){var i=e.within,s=i.isWindow?i.scrollLeft:i.offset.left,n=i.width,o=t.left-e.collisionPosition.marginLeft,a=s-o,r=o+e.collisionWidth-n-s;e.collisionWidth>n?0n?0")[0],w=d.each;function P(t){return null==t?t+"":"object"==typeof t?p[e.call(t)]||"object":typeof t}function M(t,e,i){var s=v[e.type]||{};return null==t?i||!e.def?null:e.def:(t=s.floor?~~t:parseFloat(t),isNaN(t)?e.def:s.mod?(t+s.mod)%s.mod:Math.min(s.max,Math.max(0,t)))}function S(s){var n=m(),o=n._rgba=[];return s=s.toLowerCase(),w(g,function(t,e){var i=e.re.exec(s),i=i&&e.parse(i),e=e.space||"rgba";if(i)return i=n[e](i),n[_[e].cache]=i[_[e].cache],o=n._rgba=i._rgba,!1}),o.length?("0,0,0,0"===o.join()&&d.extend(o,B.transparent),n):B[s]}function H(t,e,i){return 6*(i=(i+1)%1)<1?t+(e-t)*i*6:2*i<1?e:3*i<2?t+(e-t)*(2/3-i)*6:t}y.style.cssText="background-color:rgba(1,1,1,.5)",b.rgba=-1o.mod/2?s+=o.mod:s-n>o.mod/2&&(s-=o.mod)),l[i]=M((n-s)*a+s,e)))}),this[e](l)},blend:function(t){if(1===this._rgba[3])return this;var e=this._rgba.slice(),i=e.pop(),s=m(t)._rgba;return m(d.map(e,function(t,e){return(1-i)*s[e]+i*t}))},toRgbaString:function(){var t="rgba(",e=d.map(this._rgba,function(t,e){return null!=t?t:2
").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),e={width:i.width(),height:i.height()},n=document.activeElement;try{n.id}catch(t){n=document.body}return i.wrap(t),i[0]!==n&&!V.contains(i[0],n)||V(n).trigger("focus"),t=i.parent(),"static"===i.css("position")?(t.css({position:"relative"}),i.css({position:"relative"})):(V.extend(s,{position:i.css("position"),zIndex:i.css("z-index")}),V.each(["top","left","bottom","right"],function(t,e){s[e]=i.css(e),isNaN(parseInt(s[e],10))&&(s[e]="auto")}),i.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),i.css(e),t.css(s).show()},removeWrapper:function(t){var e=document.activeElement;return t.parent().is(".ui-effects-wrapper")&&(t.parent().replaceWith(t),t[0]!==e&&!V.contains(t[0],e)||V(e).trigger("focus")),t}}),V.extend(V.effects,{version:"1.13.2",define:function(t,e,i){return i||(i=e,e="effect"),V.effects.effect[t]=i,V.effects.effect[t].mode=e,i},scaledDimensions:function(t,e,i){if(0===e)return{height:0,width:0,outerHeight:0,outerWidth:0};var s="horizontal"!==i?(e||100)/100:1,e="vertical"!==i?(e||100)/100:1;return{height:t.height()*e,width:t.width()*s,outerHeight:t.outerHeight()*e,outerWidth:t.outerWidth()*s}},clipToBox:function(t){return{width:t.clip.right-t.clip.left,height:t.clip.bottom-t.clip.top,left:t.clip.left,top:t.clip.top}},unshift:function(t,e,i){var s=t.queue();1").insertAfter(t).css({display:/^(inline|ruby)/.test(t.css("display"))?"inline-block":"block",visibility:"hidden",marginTop:t.css("marginTop"),marginBottom:t.css("marginBottom"),marginLeft:t.css("marginLeft"),marginRight:t.css("marginRight"),float:t.css("float")}).outerWidth(t.outerWidth()).outerHeight(t.outerHeight()).addClass("ui-effects-placeholder"),t.data(j+"placeholder",e)),t.css({position:i,left:s.left,top:s.top}),e},removePlaceholder:function(t){var e=j+"placeholder",i=t.data(e);i&&(i.remove(),t.removeData(e))},cleanUp:function(t){V.effects.restoreStyle(t),V.effects.removePlaceholder(t)},setTransition:function(s,t,n,o){return o=o||{},V.each(t,function(t,e){var i=s.cssUnit(e);0
");l.appendTo("body").addClass(t.className).css({top:s.top-a,left:s.left-r,height:i.innerHeight(),width:i.innerWidth(),position:n?"fixed":"absolute"}).animate(o,t.duration,t.easing,function(){l.remove(),"function"==typeof e&&e()})}}),V.fx.step.clip=function(t){t.clipInit||(t.start=V(t.elem).cssClip(),"string"==typeof t.end&&(t.end=G(t.end,t.elem)),t.clipInit=!0),V(t.elem).cssClip({top:t.pos*(t.end.top-t.start.top)+t.start.top,right:t.pos*(t.end.right-t.start.right)+t.start.right,bottom:t.pos*(t.end.bottom-t.start.bottom)+t.start.bottom,left:t.pos*(t.end.left-t.start.left)+t.start.left})},Y={},V.each(["Quad","Cubic","Quart","Quint","Expo"],function(e,t){Y[t]=function(t){return Math.pow(t,e+2)}}),V.extend(Y,{Sine:function(t){return 1-Math.cos(t*Math.PI/2)},Circ:function(t){return 1-Math.sqrt(1-t*t)},Elastic:function(t){return 0===t||1===t?t:-Math.pow(2,8*(t-1))*Math.sin((80*(t-1)-7.5)*Math.PI/15)},Back:function(t){return t*t*(3*t-2)},Bounce:function(t){for(var e,i=4;t<((e=Math.pow(2,--i))-1)/11;);return 1/Math.pow(4,3-i)-7.5625*Math.pow((3*e-2)/22-t,2)}}),V.each(Y,function(t,e){V.easing["easeIn"+t]=e,V.easing["easeOut"+t]=function(t){return 1-e(1-t)},V.easing["easeInOut"+t]=function(t){return t<.5?e(2*t)/2:1-e(-2*t+2)/2}});y=V.effects,V.effects.define("blind","hide",function(t,e){var i={up:["bottom","top"],vertical:["bottom","top"],down:["top","bottom"],left:["right","left"],horizontal:["right","left"],right:["left","right"]},s=V(this),n=t.direction||"up",o=s.cssClip(),a={clip:V.extend({},o)},r=V.effects.createPlaceholder(s);a.clip[i[n][0]]=a.clip[i[n][1]],"show"===t.mode&&(s.cssClip(a.clip),r&&r.css(V.effects.clipToBox(a)),a.clip=o),r&&r.animate(V.effects.clipToBox(a),t.duration,t.easing),s.animate(a,{queue:!1,duration:t.duration,easing:t.easing,complete:e})}),V.effects.define("bounce",function(t,e){var i,s,n=V(this),o=t.mode,a="hide"===o,r="show"===o,l=t.direction||"up",h=t.distance,c=t.times||5,o=2*c+(r||a?1:0),u=t.duration/o,d=t.easing,p="up"===l||"down"===l?"top":"left",f="up"===l||"left"===l,g=0,t=n.queue().length;for(V.effects.createPlaceholder(n),l=n.css(p),h=h||n["top"==p?"outerHeight":"outerWidth"]()/3,r&&((s={opacity:1})[p]=l,n.css("opacity",0).css(p,f?2*-h:2*h).animate(s,u,d)),a&&(h/=Math.pow(2,c-1)),(s={})[p]=l;g
").css({position:"absolute",visibility:"visible",left:-s*p,top:-i*f}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:p,height:f,left:n+(u?a*p:0),top:o+(u?r*f:0),opacity:u?0:1}).animate({left:n+(u?0:a*p),top:o+(u?0:r*f),opacity:u?1:0},t.duration||500,t.easing,m)}),V.effects.define("fade","toggle",function(t,e){var i="show"===t.mode;V(this).css("opacity",i?0:1).animate({opacity:i?1:0},{queue:!1,duration:t.duration,easing:t.easing,complete:e})}),V.effects.define("fold","hide",function(e,t){var i=V(this),s=e.mode,n="show"===s,o="hide"===s,a=e.size||15,r=/([0-9]+)%/.exec(a),l=!!e.horizFirst?["right","bottom"]:["bottom","right"],h=e.duration/2,c=V.effects.createPlaceholder(i),u=i.cssClip(),d={clip:V.extend({},u)},p={clip:V.extend({},u)},f=[u[l[0]],u[l[1]]],s=i.queue().length;r&&(a=parseInt(r[1],10)/100*f[o?0:1]),d.clip[l[0]]=a,p.clip[l[0]]=a,p.clip[l[1]]=0,n&&(i.cssClip(p.clip),c&&c.css(V.effects.clipToBox(p)),p.clip=u),i.queue(function(t){c&&c.animate(V.effects.clipToBox(d),h,e.easing).animate(V.effects.clipToBox(p),h,e.easing),t()}).animate(d,h,e.easing).animate(p,h,e.easing).queue(t),V.effects.unshift(i,s,4)}),V.effects.define("highlight","show",function(t,e){var i=V(this),s={backgroundColor:i.css("backgroundColor")};"hide"===t.mode&&(s.opacity=0),V.effects.saveStyle(i),i.css({backgroundImage:"none",backgroundColor:t.color||"#ffff99"}).animate(s,{queue:!1,duration:t.duration,easing:t.easing,complete:e})}),V.effects.define("size",function(s,e){var n,i=V(this),t=["fontSize"],o=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],a=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],r=s.mode,l="effect"!==r,h=s.scale||"both",c=s.origin||["middle","center"],u=i.css("position"),d=i.position(),p=V.effects.scaledDimensions(i),f=s.from||p,g=s.to||V.effects.scaledDimensions(i,0);V.effects.createPlaceholder(i),"show"===r&&(r=f,f=g,g=r),n={from:{y:f.height/p.height,x:f.width/p.width},to:{y:g.height/p.height,x:g.width/p.width}},"box"!==h&&"both"!==h||(n.from.y!==n.to.y&&(f=V.effects.setTransition(i,o,n.from.y,f),g=V.effects.setTransition(i,o,n.to.y,g)),n.from.x!==n.to.x&&(f=V.effects.setTransition(i,a,n.from.x,f),g=V.effects.setTransition(i,a,n.to.x,g))),"content"!==h&&"both"!==h||n.from.y!==n.to.y&&(f=V.effects.setTransition(i,t,n.from.y,f),g=V.effects.setTransition(i,t,n.to.y,g)),c&&(c=V.effects.getBaseline(c,p),f.top=(p.outerHeight-f.outerHeight)*c.y+d.top,f.left=(p.outerWidth-f.outerWidth)*c.x+d.left,g.top=(p.outerHeight-g.outerHeight)*c.y+d.top,g.left=(p.outerWidth-g.outerWidth)*c.x+d.left),delete f.outerHeight,delete f.outerWidth,i.css(f),"content"!==h&&"both"!==h||(o=o.concat(["marginTop","marginBottom"]).concat(t),a=a.concat(["marginLeft","marginRight"]),i.find("*[width]").each(function(){var t=V(this),e=V.effects.scaledDimensions(t),i={height:e.height*n.from.y,width:e.width*n.from.x,outerHeight:e.outerHeight*n.from.y,outerWidth:e.outerWidth*n.from.x},e={height:e.height*n.to.y,width:e.width*n.to.x,outerHeight:e.height*n.to.y,outerWidth:e.width*n.to.x};n.from.y!==n.to.y&&(i=V.effects.setTransition(t,o,n.from.y,i),e=V.effects.setTransition(t,o,n.to.y,e)),n.from.x!==n.to.x&&(i=V.effects.setTransition(t,a,n.from.x,i),e=V.effects.setTransition(t,a,n.to.x,e)),l&&V.effects.saveStyle(t),t.css(i),t.animate(e,s.duration,s.easing,function(){l&&V.effects.restoreStyle(t)})})),i.animate(g,{queue:!1,duration:s.duration,easing:s.easing,complete:function(){var t=i.offset();0===g.opacity&&i.css("opacity",f.opacity),l||(i.css("position","static"===u?"relative":u).offset(t),V.effects.saveStyle(i)),e()}})}),V.effects.define("scale",function(t,e){var i=V(this),s=t.mode,s=parseInt(t.percent,10)||(0===parseInt(t.percent,10)||"effect"!==s?0:100),s=V.extend(!0,{from:V.effects.scaledDimensions(i),to:V.effects.scaledDimensions(i,s,t.direction||"both"),origin:t.origin||["middle","center"]},t);t.fade&&(s.from.opacity=1,s.to.opacity=0),V.effects.effect.size.call(this,s,e)}),V.effects.define("puff","hide",function(t,e){t=V.extend(!0,{},t,{fade:!0,percent:parseInt(t.percent,10)||150});V.effects.effect.scale.call(this,t,e)}),V.effects.define("pulsate","show",function(t,e){var i=V(this),s=t.mode,n="show"===s,o=2*(t.times||5)+(n||"hide"===s?1:0),a=t.duration/o,r=0,l=1,s=i.queue().length;for(!n&&i.is(":visible")||(i.css("opacity",0).show(),r=1);l li > :first-child").add(t.find("> :not(li)").even())},heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},hideProps:{borderTopWidth:"hide",borderBottomWidth:"hide",paddingTop:"hide",paddingBottom:"hide",height:"hide"},showProps:{borderTopWidth:"show",borderBottomWidth:"show",paddingTop:"show",paddingBottom:"show",height:"show"},_create:function(){var t=this.options;this.prevShow=this.prevHide=V(),this._addClass("ui-accordion","ui-widget ui-helper-reset"),this.element.attr("role","tablist"),t.collapsible||!1!==t.active&&null!=t.active||(t.active=0),this._processPanels(),t.active<0&&(t.active+=this.headers.length),this._refresh()},_getCreateEventData:function(){return{header:this.active,panel:this.active.length?this.active.next():V()}},_createIcons:function(){var t,e=this.options.icons;e&&(t=V(""),this._addClass(t,"ui-accordion-header-icon","ui-icon "+e.header),t.prependTo(this.headers),t=this.active.children(".ui-accordion-header-icon"),this._removeClass(t,e.header)._addClass(t,null,e.activeHeader)._addClass(this.headers,"ui-accordion-icons"))},_destroyIcons:function(){this._removeClass(this.headers,"ui-accordion-icons"),this.headers.children(".ui-accordion-header-icon").remove()},_destroy:function(){var t;this.element.removeAttr("role"),this.headers.removeAttr("role aria-expanded aria-selected aria-controls tabIndex").removeUniqueId(),this._destroyIcons(),t=this.headers.next().css("display","").removeAttr("role aria-hidden aria-labelledby").removeUniqueId(),"content"!==this.options.heightStyle&&t.css("height","")},_setOption:function(t,e){"active"!==t?("event"===t&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(e)),this._super(t,e),"collapsible"!==t||e||!1!==this.options.active||this._activate(0),"icons"===t&&(this._destroyIcons(),e&&this._createIcons())):this._activate(e)},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",t),this._toggleClass(null,"ui-state-disabled",!!t),this._toggleClass(this.headers.add(this.headers.next()),null,"ui-state-disabled",!!t)},_keydown:function(t){if(!t.altKey&&!t.ctrlKey){var e=V.ui.keyCode,i=this.headers.length,s=this.headers.index(t.target),n=!1;switch(t.keyCode){case e.RIGHT:case e.DOWN:n=this.headers[(s+1)%i];break;case e.LEFT:case e.UP:n=this.headers[(s-1+i)%i];break;case e.SPACE:case e.ENTER:this._eventHandler(t);break;case e.HOME:n=this.headers[0];break;case e.END:n=this.headers[i-1]}n&&(V(t.target).attr("tabIndex",-1),V(n).attr("tabIndex",0),V(n).trigger("focus"),t.preventDefault())}},_panelKeyDown:function(t){t.keyCode===V.ui.keyCode.UP&&t.ctrlKey&&V(t.currentTarget).prev().trigger("focus")},refresh:function(){var t=this.options;this._processPanels(),!1===t.active&&!0===t.collapsible||!this.headers.length?(t.active=!1,this.active=V()):!1===t.active?this._activate(0):this.active.length&&!V.contains(this.element[0],this.active[0])?this.headers.length===this.headers.find(".ui-state-disabled").length?(t.active=!1,this.active=V()):this._activate(Math.max(0,t.active-1)):t.active=this.headers.index(this.active),this._destroyIcons(),this._refresh()},_processPanels:function(){var t=this.headers,e=this.panels;"function"==typeof this.options.header?this.headers=this.options.header(this.element):this.headers=this.element.find(this.options.header),this._addClass(this.headers,"ui-accordion-header ui-accordion-header-collapsed","ui-state-default"),this.panels=this.headers.next().filter(":not(.ui-accordion-content-active)").hide(),this._addClass(this.panels,"ui-accordion-content","ui-helper-reset ui-widget-content"),e&&(this._off(t.not(this.headers)),this._off(e.not(this.panels)))},_refresh:function(){var i,t=this.options,e=t.heightStyle,s=this.element.parent();this.active=this._findActive(t.active),this._addClass(this.active,"ui-accordion-header-active","ui-state-active")._removeClass(this.active,"ui-accordion-header-collapsed"),this._addClass(this.active.next(),"ui-accordion-content-active"),this.active.next().show(),this.headers.attr("role","tab").each(function(){var t=V(this),e=t.uniqueId().attr("id"),i=t.next(),s=i.uniqueId().attr("id");t.attr("aria-controls",s),i.attr("aria-labelledby",e)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}).next().attr({"aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}).next().attr({"aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._createIcons(),this._setupEvents(t.event),"fill"===e?(i=s.height(),this.element.siblings(":visible").each(function(){var t=V(this),e=t.css("position");"absolute"!==e&&"fixed"!==e&&(i-=t.outerHeight(!0))}),this.headers.each(function(){i-=V(this).outerHeight(!0)}),this.headers.next().each(function(){V(this).height(Math.max(0,i-V(this).innerHeight()+V(this).height()))}).css("overflow","auto")):"auto"===e&&(i=0,this.headers.next().each(function(){var t=V(this).is(":visible");t||V(this).show(),i=Math.max(i,V(this).css("height","").height()),t||V(this).hide()}).height(i))},_activate:function(t){t=this._findActive(t)[0];t!==this.active[0]&&(t=t||this.active[0],this._eventHandler({target:t,currentTarget:t,preventDefault:V.noop}))},_findActive:function(t){return"number"==typeof t?this.headers.eq(t):V()},_setupEvents:function(t){var i={keydown:"_keydown"};t&&V.each(t.split(" "),function(t,e){i[e]="_eventHandler"}),this._off(this.headers.add(this.headers.next())),this._on(this.headers,i),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._hoverable(this.headers),this._focusable(this.headers)},_eventHandler:function(t){var e=this.options,i=this.active,s=V(t.currentTarget),n=s[0]===i[0],o=n&&e.collapsible,a=o?V():s.next(),r=i.next(),a={oldHeader:i,oldPanel:r,newHeader:o?V():s,newPanel:a};t.preventDefault(),n&&!e.collapsible||!1===this._trigger("beforeActivate",t,a)||(e.active=!o&&this.headers.index(s),this.active=n?V():s,this._toggle(a),this._removeClass(i,"ui-accordion-header-active","ui-state-active"),e.icons&&(i=i.children(".ui-accordion-header-icon"),this._removeClass(i,null,e.icons.activeHeader)._addClass(i,null,e.icons.header)),n||(this._removeClass(s,"ui-accordion-header-collapsed")._addClass(s,"ui-accordion-header-active","ui-state-active"),e.icons&&(n=s.children(".ui-accordion-header-icon"),this._removeClass(n,null,e.icons.header)._addClass(n,null,e.icons.activeHeader)),this._addClass(s.next(),"ui-accordion-content-active")))},_toggle:function(t){var e=t.newPanel,i=this.prevShow.length?this.prevShow:t.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=e,this.prevHide=i,this.options.animate?this._animate(e,i,t):(i.hide(),e.show(),this._toggleComplete(t)),i.attr({"aria-hidden":"true"}),i.prev().attr({"aria-selected":"false","aria-expanded":"false"}),e.length&&i.length?i.prev().attr({tabIndex:-1,"aria-expanded":"false"}):e.length&&this.headers.filter(function(){return 0===parseInt(V(this).attr("tabIndex"),10)}).attr("tabIndex",-1),e.attr("aria-hidden","false").prev().attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0})},_animate:function(t,i,e){var s,n,o,a=this,r=0,l=t.css("box-sizing"),h=t.length&&(!i.length||t.index()",delay:300,options:{icons:{submenu:"ui-icon-caret-1-e"},items:"> *",menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.lastMousePosition={x:null,y:null},this.element.uniqueId().attr({role:this.options.role,tabIndex:0}),this._addClass("ui-menu","ui-widget ui-widget-content"),this._on({"mousedown .ui-menu-item":function(t){t.preventDefault(),this._activateItem(t)},"click .ui-menu-item":function(t){var e=V(t.target),i=V(V.ui.safeActiveElement(this.document[0]));!this.mouseHandled&&e.not(".ui-state-disabled").length&&(this.select(t),t.isPropagationStopped()||(this.mouseHandled=!0),e.has(".ui-menu").length?this.expand(t):!this.element.is(":focus")&&i.closest(".ui-menu").length&&(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":"_activateItem","mousemove .ui-menu-item":"_activateItem",mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(t,e){var i=this.active||this._menuItems().first();e||this.focus(t,i)},blur:function(t){this._delay(function(){V.contains(this.element[0],V.ui.safeActiveElement(this.document[0]))||this.collapseAll(t)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(t){this._closeOnDocumentClick(t)&&this.collapseAll(t,!0),this.mouseHandled=!1}})},_activateItem:function(t){var e,i;this.previousFilter||t.clientX===this.lastMousePosition.x&&t.clientY===this.lastMousePosition.y||(this.lastMousePosition={x:t.clientX,y:t.clientY},e=V(t.target).closest(".ui-menu-item"),i=V(t.currentTarget),e[0]===i[0]&&(i.is(".ui-state-active")||(this._removeClass(i.siblings().children(".ui-state-active"),null,"ui-state-active"),this.focus(t,i))))},_destroy:function(){var t=this.element.find(".ui-menu-item").removeAttr("role aria-disabled").children(".ui-menu-item-wrapper").removeUniqueId().removeAttr("tabIndex role aria-haspopup");this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeAttr("role aria-labelledby aria-expanded aria-hidden aria-disabled tabIndex").removeUniqueId().show(),t.children().each(function(){var t=V(this);t.data("ui-menu-submenu-caret")&&t.remove()})},_keydown:function(t){var e,i,s,n=!0;switch(t.keyCode){case V.ui.keyCode.PAGE_UP:this.previousPage(t);break;case V.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case V.ui.keyCode.HOME:this._move("first","first",t);break;case V.ui.keyCode.END:this._move("last","last",t);break;case V.ui.keyCode.UP:this.previous(t);break;case V.ui.keyCode.DOWN:this.next(t);break;case V.ui.keyCode.LEFT:this.collapse(t);break;case V.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(t);break;case V.ui.keyCode.ENTER:case V.ui.keyCode.SPACE:this._activate(t);break;case V.ui.keyCode.ESCAPE:this.collapse(t);break;default:e=this.previousFilter||"",s=n=!1,i=96<=t.keyCode&&t.keyCode<=105?(t.keyCode-96).toString():String.fromCharCode(t.keyCode),clearTimeout(this.filterTimer),i===e?s=!0:i=e+i,e=this._filterMenuItems(i),(e=s&&-1!==e.index(this.active.next())?this.active.nextAll(".ui-menu-item"):e).length||(i=String.fromCharCode(t.keyCode),e=this._filterMenuItems(i)),e.length?(this.focus(t,e),this.previousFilter=i,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter}n&&t.preventDefault()},_activate:function(t){this.active&&!this.active.is(".ui-state-disabled")&&(this.active.children("[aria-haspopup='true']").length?this.expand(t):this.select(t))},refresh:function(){var t,e,s=this,n=this.options.icons.submenu,i=this.element.find(this.options.menus);this._toggleClass("ui-menu-icons",null,!!this.element.find(".ui-icon").length),e=i.filter(":not(.ui-menu)").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var t=V(this),e=t.prev(),i=V("").data("ui-menu-submenu-caret",!0);s._addClass(i,"ui-menu-icon","ui-icon "+n),e.attr("aria-haspopup","true").prepend(i),t.attr("aria-labelledby",e.attr("id"))}),this._addClass(e,"ui-menu","ui-widget ui-widget-content ui-front"),(t=i.add(this.element).find(this.options.items)).not(".ui-menu-item").each(function(){var t=V(this);s._isDivider(t)&&s._addClass(t,"ui-menu-divider","ui-widget-content")}),i=(e=t.not(".ui-menu-item, .ui-menu-divider")).children().not(".ui-menu").uniqueId().attr({tabIndex:-1,role:this._itemRole()}),this._addClass(e,"ui-menu-item")._addClass(i,"ui-menu-item-wrapper"),t.filter(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!V.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(t,e){var i;"icons"===t&&(i=this.element.find(".ui-menu-icon"),this._removeClass(i,null,this.options.icons.submenu)._addClass(i,null,e.submenu)),this._super(t,e)},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",String(t)),this._toggleClass(null,"ui-state-disabled",!!t)},focus:function(t,e){var i;this.blur(t,t&&"focus"===t.type),this._scrollIntoView(e),this.active=e.first(),i=this.active.children(".ui-menu-item-wrapper"),this._addClass(i,null,"ui-state-active"),this.options.role&&this.element.attr("aria-activedescendant",i.attr("id")),i=this.active.parent().closest(".ui-menu-item").children(".ui-menu-item-wrapper"),this._addClass(i,null,"ui-state-active"),t&&"keydown"===t.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),(i=e.children(".ui-menu")).length&&t&&/^mouse/.test(t.type)&&this._startOpening(i),this.activeMenu=e.parent(),this._trigger("focus",t,{item:e})},_scrollIntoView:function(t){var e,i,s;this._hasScroll()&&(i=parseFloat(V.css(this.activeMenu[0],"borderTopWidth"))||0,s=parseFloat(V.css(this.activeMenu[0],"paddingTop"))||0,e=t.offset().top-this.activeMenu.offset().top-i-s,i=this.activeMenu.scrollTop(),s=this.activeMenu.height(),t=t.outerHeight(),e<0?this.activeMenu.scrollTop(i+e):s",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},requestIndex:0,pending:0,liveRegionTimer:null,_create:function(){var i,s,n,t=this.element[0].nodeName.toLowerCase(),e="textarea"===t,t="input"===t;this.isMultiLine=e||!t&&this._isContentEditable(this.element),this.valueMethod=this.element[e||t?"val":"text"],this.isNewMenu=!0,this._addClass("ui-autocomplete-input"),this.element.attr("autocomplete","off"),this._on(this.element,{keydown:function(t){if(this.element.prop("readOnly"))s=n=i=!0;else{s=n=i=!1;var e=V.ui.keyCode;switch(t.keyCode){case e.PAGE_UP:i=!0,this._move("previousPage",t);break;case e.PAGE_DOWN:i=!0,this._move("nextPage",t);break;case e.UP:i=!0,this._keyEvent("previous",t);break;case e.DOWN:i=!0,this._keyEvent("next",t);break;case e.ENTER:this.menu.active&&(i=!0,t.preventDefault(),this.menu.select(t));break;case e.TAB:this.menu.active&&this.menu.select(t);break;case e.ESCAPE:this.menu.element.is(":visible")&&(this.isMultiLine||this._value(this.term),this.close(t),t.preventDefault());break;default:s=!0,this._searchTimeout(t)}}},keypress:function(t){if(i)return i=!1,void(this.isMultiLine&&!this.menu.element.is(":visible")||t.preventDefault());if(!s){var e=V.ui.keyCode;switch(t.keyCode){case e.PAGE_UP:this._move("previousPage",t);break;case e.PAGE_DOWN:this._move("nextPage",t);break;case e.UP:this._keyEvent("previous",t);break;case e.DOWN:this._keyEvent("next",t)}}},input:function(t){if(n)return n=!1,void t.preventDefault();this._searchTimeout(t)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(t){clearTimeout(this.searching),this.close(t),this._change(t)}}),this._initSource(),this.menu=V("
'.$form->editfieldkey('DefaultLang', 'default_lang', '', $object, 0).''."\n"; + print img_picto('', 'language').$formadmin->select_language($object->default_lang, 'default_lang', 0, 0, 1); + print '
".$langs->trans("Public")."\n"; print $form->selectyesno("public", (GETPOSTISSET("public") ? GETPOST("public", 'alphanohtml', 2) : $object->public), 1); @@ -1803,6 +1814,19 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { // Birth Date print '
'.$langs->trans("DateOfBirth").''.dol_print_date($object->birth, 'day').'
'.$langs->trans("DefaultLang").''; + //$s=picto_from_langcode($object->default_lang); + //print ($s?$s.' ':''); + $langs->load("languages"); + $labellang = ($object->default_lang ? $langs->trans('Language_'.$object->default_lang) : ''); + print picto_from_langcode($object->default_lang, 'class="paddingrightonly saturatemedium opacitylow"'); + print $labellang; + print '
'.$langs->trans("Public").''.yn($object->public).'
'.$langs->trans('Date').''.dol_print_date($now,'day').'
'.$langs->trans("DateChequeReceived").''; - print $form->selectDate($filterdate, 'fd', 0, 0, 1, '', 1, 1); + // filter by dates from / to + print '
'; + print $form->selectDate($search_date_start, 'search_date_start_', 0, 0, 1, '', 1, 1, 0, '', '', '', '', 1, '', $langs->trans('From')); + print '
'; + print '
'; + print $form->selectDate($search_date_end, 'search_date_end_', 0, 0, 1, '', 1, 1, 0, '', '', '', '', 1, '', $langs->trans('to')); + print '
'; print '
'.$langs->trans("BankAccount").''; $form->select_comptes($filteraccountid, 'accountid', 0, 'courant <> 2', 1); @@ -363,7 +384,7 @@ if ($action == 'new') { print '
'; print ''; - if ($filterdate || $filteraccountid > 0) { + if ($search_date_start || $search_date_end || $filteraccountid > 0) { print '   '; print ''; } @@ -382,8 +403,11 @@ if ($action == 'new') { $sql .= " AND ba.entity IN (".getEntity('bank_account').")"; $sql .= " AND b.fk_bordereau = 0"; $sql .= " AND b.amount > 0"; - if ($filterdate) { - $sql .= " AND b.dateo = '".$db->idate($filterdate)."'"; + if ($search_date_start) { + $sql .= " AND b.dateo >= '".$db->idate($search_date_start)."'"; + } + if ($search_date_end) { + $sql .= " AND b.dateo <= '".$db->idate($search_date_end)."'"; } if ($filteraccountid > 0) { $sql .= " AND ba.rowid = ".((int) $filteraccountid); From ef0bd60283c98c8c939e605ec72479ffe15eaf39 Mon Sep 17 00:00:00 2001 From: lvessiller Date: Mon, 8 Aug 2022 15:06:25 +0200 Subject: [PATCH 471/826] FIX reload stickler-ci From 001d326a8cb0919c3fd5f31cd4854e74608d05dc Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Tue, 9 Aug 2022 10:32:34 +0200 Subject: [PATCH 472/826] update code for PHP8 compliance --- htdocs/imports/import.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/imports/import.php b/htdocs/imports/import.php index 51a50c6376c..7aa566630c3 100644 --- a/htdocs/imports/import.php +++ b/htdocs/imports/import.php @@ -1818,7 +1818,7 @@ if ($step == 5 && $datatoimport) { // Actions print '
'; - if ($user->rights->import->run) { + if ($user->hasRight('import', 'run')) { print ''; } else { print ''.$langs->trans("RunSimulateImportFile").''; @@ -1974,7 +1974,7 @@ if ($step == 5 && $datatoimport) { // Actions print '
'; - if ($user->rights->import->run) { + if ($user->hasRight('import', 'run')) { if (empty($nboferrors)) { print ''.$langs->trans("RunImportFile").''; } else { From b8a29fbcb2c3d02afa5c1c29ada8403ed849ca02 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Tue, 9 Aug 2022 10:40:08 +0200 Subject: [PATCH 473/826] update code for PHP8 compliance --- htdocs/document.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/document.php b/htdocs/document.php index a33708e3e77..e432d6a92f1 100644 --- a/htdocs/document.php +++ b/htdocs/document.php @@ -120,7 +120,7 @@ if ($user->socid > 0) { // For some module part, dir may be privates if (in_array($modulepart, array('facture_paiement', 'unpaid'))) { - if (empty($user->rights->societe->client->voir) || $socid) { + if (empty($user->hasRight('societe', 'client', 'voir')) || $socid) { $original_file = 'private/'.$user->id.'/'.$original_file; // If user has no permission to see all, output dir is specific to user } } From 79830bee9e5865cfe1723da522ea4a9716e2f469 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Tue, 9 Aug 2022 10:57:58 +0200 Subject: [PATCH 474/826] update code for PHP8 compliance --- htdocs/accountancy/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/accountancy/index.php b/htdocs/accountancy/index.php index 99ae0bd845b..bd48c205dae 100644 --- a/htdocs/accountancy/index.php +++ b/htdocs/accountancy/index.php @@ -49,7 +49,7 @@ if (empty($user->rights->accounting->mouvements->lire)) { if (empty($conf->comptabilite->enabled) && empty($conf->accounting->enabled) && empty($conf->asset->enabled) && empty($conf->intracommreport->enabled)) { accessforbidden(); } -if (empty($user->rights->compta->resultat->lire) && empty($user->rights->accounting->comptarapport->lire) && empty($user->rights->accounting->mouvements->lire) && empty($user->rights->asset->read) && empty($user->rights->intracommreport->read)) { +if (empty($user->hasRight('compta', 'resultat', 'lire')) && empty($user->hasRight('accounting', 'comptarapport', 'lire')) && empty($user->hasRight('accounting', 'mouvements', 'lire')) && empty($user->hasRight('asset', 'read')) && empty($user->hasRight('intracommreport', 'read'))) { accessforbidden(); } From fb386faf94c2a934bb965bc4fb4a409ffcca187c Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Tue, 9 Aug 2022 11:05:49 +0200 Subject: [PATCH 475/826] update code for PHP8 compliance --- htdocs/index.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/index.php b/htdocs/index.php index 6715577e615..017b90a6194 100644 --- a/htdocs/index.php +++ b/htdocs/index.php @@ -155,12 +155,12 @@ if (empty($conf->global->MAIN_DISABLE_GLOBAL_WORKBOARD)) { require_once DOL_DOCUMENT_ROOT.'/core/class/workboardresponse.class.php'; // Number of actions to do (late) - if (isModEnabled('agenda') && empty($conf->global->MAIN_DISABLE_BLOCK_AGENDA) && $user->rights->agenda->myactions->read) { + if (isModEnabled('agenda') && empty($conf->global->MAIN_DISABLE_BLOCK_AGENDA) && $user->hasRight('agenda', 'myactions', 'read')) { include_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php'; $board = new ActionComm($db); $dashboardlines[$board->element] = $board->load_board($user); } - + // Number of project opened if (!empty($conf->project->enabled) && empty($conf->global->MAIN_DISABLE_BLOCK_PROJECT) && $user->hasRight('projet', 'lire')) { include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; @@ -202,13 +202,13 @@ if (empty($conf->global->MAIN_DISABLE_GLOBAL_WORKBOARD)) { } // Number of suppliers orders a deal - if (isModEnabled('supplier_order') && empty($conf->global->MAIN_DISABLE_BLOCK_SUPPLIER) && $user->rights->fournisseur->commande->lire) { + if (isModEnabled('supplier_order') && empty($conf->global->MAIN_DISABLE_BLOCK_SUPPLIER) && $user->hasRight('fournisseur', 'commande', 'lire')) { include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php'; $board = new CommandeFournisseur($db); $dashboardlines[$board->element.'_opened'] = $board->load_board($user, "opened"); $dashboardlines[$board->element.'_awaiting'] = $board->load_board($user, 'awaiting'); } - + // Number of contract / services enabled (delayed) if (isModEnabled('contrat') && empty($conf->global->MAIN_DISABLE_BLOCK_CONTRACT) && $user->hasRight('contrat', 'lire')) { include_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php'; @@ -235,12 +235,12 @@ if (empty($conf->global->MAIN_DISABLE_GLOBAL_WORKBOARD)) { } // Number of supplier invoices (paid) - if (isModEnabled('supplier_invoice') && empty($conf->global->MAIN_DISABLE_BLOCK_SUPPLIER) && !empty($user->rights->fournisseur->facture->lire)) { + if (isModEnabled('supplier_invoice') && empty($conf->global->MAIN_DISABLE_BLOCK_SUPPLIER) && !empty($user->hasRight('fournisseur', 'facture', 'lire'))) { include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php'; $board = new FactureFournisseur($db); $dashboardlines[$board->element] = $board->load_board($user); } - + // Number of transactions to conciliate if (isModEnabled('banque') && empty($conf->global->MAIN_DISABLE_BLOCK_BANK) && $user->hasRight('banque', 'lire') && !$user->socid) { include_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; From e51732682a13b4715a0c0aa04c20fcc3f53b8545 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Tue, 9 Aug 2022 09:06:20 +0000 Subject: [PATCH 476/826] Fixing style errors. --- htdocs/index.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/index.php b/htdocs/index.php index 017b90a6194..afce0c5e553 100644 --- a/htdocs/index.php +++ b/htdocs/index.php @@ -160,7 +160,7 @@ if (empty($conf->global->MAIN_DISABLE_GLOBAL_WORKBOARD)) { $board = new ActionComm($db); $dashboardlines[$board->element] = $board->load_board($user); } - + // Number of project opened if (!empty($conf->project->enabled) && empty($conf->global->MAIN_DISABLE_BLOCK_PROJECT) && $user->hasRight('projet', 'lire')) { include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; @@ -208,7 +208,7 @@ if (empty($conf->global->MAIN_DISABLE_GLOBAL_WORKBOARD)) { $dashboardlines[$board->element.'_opened'] = $board->load_board($user, "opened"); $dashboardlines[$board->element.'_awaiting'] = $board->load_board($user, 'awaiting'); } - + // Number of contract / services enabled (delayed) if (isModEnabled('contrat') && empty($conf->global->MAIN_DISABLE_BLOCK_CONTRACT) && $user->hasRight('contrat', 'lire')) { include_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php'; @@ -240,7 +240,7 @@ if (empty($conf->global->MAIN_DISABLE_GLOBAL_WORKBOARD)) { $board = new FactureFournisseur($db); $dashboardlines[$board->element] = $board->load_board($user); } - + // Number of transactions to conciliate if (isModEnabled('banque') && empty($conf->global->MAIN_DISABLE_BLOCK_BANK) && $user->hasRight('banque', 'lire') && !$user->socid) { include_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; From 7a4ec39a821c28c5402977d92c66079e6be98570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Tue, 9 Aug 2022 16:36:02 +0200 Subject: [PATCH 477/826] fix doc_generic_recruitmentjobposition_odt --- .../doc_generic_recruitmentjobposition_odt.modules.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/htdocs/recruitment/core/modules/recruitment/doc/doc_generic_recruitmentjobposition_odt.modules.php b/htdocs/recruitment/core/modules/recruitment/doc/doc_generic_recruitmentjobposition_odt.modules.php index 8d187807700..ba35cb0ba3f 100644 --- a/htdocs/recruitment/core/modules/recruitment/doc/doc_generic_recruitmentjobposition_odt.modules.php +++ b/htdocs/recruitment/core/modules/recruitment/doc/doc_generic_recruitmentjobposition_odt.modules.php @@ -4,7 +4,7 @@ * Copyright (C) 2014 Marcos García * Copyright (C) 2016 Charlie Benke * Copyright (C) 2018-2021 Philippe Grand - * Copyright (C) 2018 Frédéric France + * Copyright (C) 2018-2022 Frédéric France * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,12 +22,12 @@ */ /** - * \file htdocs/core/modules/recruitment/doc/doc_generic_recruitmentjobposition_odt.modules.php + * \file htdocs/recruitment/core/modules/recruitment/doc/doc_generic_recruitmentjobposition_odt.modules.php * \ingroup recruitment * \brief File of class to build ODT documents for recruitmentjobpositions */ -dol_include_once('/recruitment/core/modules/recruitment/modules_recruitmentjobposition.php'); +require_once DOL_DOCUMENT_ROOT.'/recruitment/core/modules/recruitment/modules_recruitmentjobposition.php'; require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; @@ -234,7 +234,7 @@ class doc_generic_recruitmentjobposition_odt extends ModelePDFRecruitmentJobPosi $outputlangs->loadLangs(array("main", "dict", "companies", "bills")); - if ($conf->commande->dir_output) { + if ($conf->recruitment->dir_output) { // If $object is id instead of object if (!is_object($object)) { $id = $object; @@ -246,7 +246,7 @@ class doc_generic_recruitmentjobposition_odt extends ModelePDFRecruitmentJobPosi } } - $dir = $conf->commande->multidir_output[isset($object->entity) ? $object->entity : 1]; + $dir = $conf->recruitment->multidir_output[isset($object->entity) ? $object->entity : 1].'/recruitmentjobposition/'; $objectref = dol_sanitizeFileName($object->ref); if (!preg_match('/specimen/i', $objectref)) { $dir .= "/".$objectref; From c724c5172a48bc55093b463b848a8cde80c20deb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Tue, 9 Aug 2022 16:37:29 +0200 Subject: [PATCH 478/826] Update recruitmentjobposition_card.php --- .../recruitmentjobposition_card.php | 26 +++---------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/htdocs/recruitment/recruitmentjobposition_card.php b/htdocs/recruitment/recruitmentjobposition_card.php index ed1b1b54711..996868a791e 100644 --- a/htdocs/recruitment/recruitmentjobposition_card.php +++ b/htdocs/recruitment/recruitmentjobposition_card.php @@ -21,41 +21,21 @@ * \brief Page to create/edit/view recruitmentjobposition */ -//if (! defined('NOREQUIREDB')) define('NOREQUIREDB','1'); // Do not create database handler $db -//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER','1'); // Do not load object $user -//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC','1'); // Do not load object $mysoc -//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN','1'); // Do not load object $langs -//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION','1'); // Do not check injection attack on GET parameters -//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION','1'); // Do not check injection attack on POST parameters -//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK','1'); // Do not check CSRF attack (test on referer + on token if option MAIN_SECURITY_CSRF_WITH_TOKEN is on). -//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL','1'); // Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on) -//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK','1'); // Do not check style html tag into posted data -//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU','1'); // If there is no need to load and show top and left menu -//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML','1'); // If we don't need to load the html.form.class.php -//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX','1'); // Do not load ajax.lib.php library -//if (! defined("NOLOGIN")) define("NOLOGIN",'1'); // If this page is public (can be called outside logged session). This include the NOIPCHECK too. -//if (! defined('NOIPCHECK')) define('NOIPCHECK','1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip -//if (! defined("MAIN_LANG_DEFAULT")) define('MAIN_LANG_DEFAULT','auto'); // Force lang to a particular value -//if (! defined("MAIN_AUTHENTICATION_MODE")) define('MAIN_AUTHENTICATION_MODE','aloginmodule'); // Force authentication handler -//if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN',1); // The main.inc.php does not make a redirect if not logged, instead show simple error message -//if (! defined("FORCECSP")) define('FORCECSP','none'); // Disable all Content Security Policies - - // Load Dolibarr environment require_once '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php'; require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; -dol_include_once('/recruitment/class/recruitmentjobposition.class.php'); -dol_include_once('/recruitment/lib/recruitment_recruitmentjobposition.lib.php'); +require_once DOL_DOCUMENT_ROOT.'/recruitment/class/recruitmentjobposition.class.php'; +require_once DOL_DOCUMENT_ROOT.'/recruitment/lib/recruitment_recruitmentjobposition.lib.php'; // Load translation files required by the page $langs->loadLangs(array("recruitment", "other")); // Get parameters $id = GETPOST('id', 'int'); -$ref = GETPOST('ref', 'alpha'); +$ref = GETPOST('ref', 'alpha'); $action = GETPOST('action', 'aZ09'); $confirm = GETPOST('confirm', 'alpha'); $cancel = GETPOST('cancel', 'aZ09'); From 3c3e8dabe2f70c228bdf6d14b05849e5362ff5fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Tue, 9 Aug 2022 16:48:17 +0200 Subject: [PATCH 479/826] Update recruitmentjobposition_document.php --- htdocs/recruitment/recruitmentjobposition_document.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/recruitment/recruitmentjobposition_document.php b/htdocs/recruitment/recruitmentjobposition_document.php index 49a36a736d1..d05ed9ab5d6 100644 --- a/htdocs/recruitment/recruitmentjobposition_document.php +++ b/htdocs/recruitment/recruitmentjobposition_document.php @@ -28,8 +28,8 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; -dol_include_once('/recruitment/class/recruitmentjobposition.class.php'); -dol_include_once('/recruitment/lib/recruitment_recruitmentjobposition.lib.php'); +require_once DOL_DOCUMENT_ROOT.'/recruitment/class/recruitmentjobposition.class.php'; +require_once DOL_DOCUMENT_ROOT.'/recruitment/lib/recruitment_recruitmentjobposition.lib.php'; // Load translation files required by the page $langs->loadLangs(array("recruitment", "companies", "other", "mails")); From 630113902792d32ed67c67bc817d30bf4217b066 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 10 Aug 2022 04:42:08 +0200 Subject: [PATCH 480/826] Update mo_production.php --- htdocs/mrp/mo_production.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/mrp/mo_production.php b/htdocs/mrp/mo_production.php index 65019337b64..c35dd303dcc 100644 --- a/htdocs/mrp/mo_production.php +++ b/htdocs/mrp/mo_production.php @@ -39,7 +39,7 @@ dol_include_once('/mrp/lib/mrp_mo.lib.php'); // Load translation files required by the page $langs->loadLangs(array("mrp", "stocks", "other", "product", "productbatch")); -$newToken = function_exists('newToken') ? newToken() : $_SESSION['newtoken']; + // Get parameters $id = GETPOST('id', 'int'); $ref = GETPOST('ref', 'alpha'); @@ -431,6 +431,8 @@ $tmpstockmovement = new MouvementStock($db); $help_url = 'EN:Module_Manufacturing_Orders|FR:Module_Ordres_de_Fabrication'; llxHeader('', $langs->trans('Mo'), $help_url, '', 0, 0, array('/mrp/js/lib_dispatch.js.php')); +$newToken = newToken(); + // Part to show record if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create'))) { $res = $object->fetch_thirdparty(); From b1814a45ce7ce8b2b11d9274d4bd54769ff6a107 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 10 Aug 2022 09:33:58 +0200 Subject: [PATCH 481/826] add oauth2 for swiftmailer --- htdocs/admin/mails.php | 21 ++++++++++++--------- htdocs/langs/fr_FR/admin.lang | 4 ++-- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/htdocs/admin/mails.php b/htdocs/admin/mails.php index 9145ad9a1a7..03b4387b255 100644 --- a/htdocs/admin/mails.php +++ b/htdocs/admin/mails.php @@ -292,7 +292,7 @@ if ($action == 'edit') { jQuery("#smtp_port_mess").hide(); jQuery(".smtp_method").show(); jQuery(".dkim").show(); - jQuery(".smtp_auth_method").hide(); + jQuery(".smtp_auth_method").show(); } } function change_smtp_auth_method() { @@ -300,6 +300,9 @@ if ($action == 'edit') { if (jQuery("#MAIN_MAIL_SENDMODE").val()==\'smtps\' && jQuery("#radio_oauth").prop("checked")) { jQuery(".smtp_oauth_service").show(); jQuery(".smtp_pw").hide(); + } else if (jQuery("#MAIN_MAIL_SENDMODE").val()==\'swiftmailer\' && jQuery("#radio_oauth").prop("checked")) { + jQuery(".smtp_oauth_service").show(); + jQuery(".smtp_pw").hide(); } else if(jQuery("#MAIN_MAIL_SENDMODE").val()==\'mail\'){ jQuery(".smtp_oauth_service").hide(); jQuery(".smtp_pw").hide(); @@ -465,13 +468,13 @@ if ($action == 'edit') { if (!empty($conf->use_javascript_ajax) || (isset($conf->global->MAIN_MAIL_SENDMODE) && in_array($conf->global->MAIN_MAIL_SENDMODE, array('smtps', 'swiftmailer')))) { print '
'.$langs->trans("MAIN_MAIL_SMTPS_AUTH_TYPE").''; if (empty($conf->multicompany->enabled) || ($user->admin && !$user->entity)) { - print 'global->MAIN_MAIL_SMTPS_AUTH_TYPE == 'LOGIN' ? ' checked' : '').'> '; + print ' '; print ''; print '            '; - print 'global->MAIN_MAIL_SMTPS_AUTH_TYPE == 'XOAUTH2' ? ' checked' : '').'> '; + print ' '; print ''; } else { - $value = $conf->global->MAIN_MAIL_SMTPS_AUTH_TYPE; + $value = getDolGlobalString('MAIN_MAIL_SMTPS_AUTH_TYPE', 'LOGIN'); $htmltext = $langs->trans("ContactSuperAdminForChange"); print $form->textwithpicto($langs->trans("MAIN_MAIL_SMTPS_AUTH_TYPE"), $htmltext, 1, 'superadmin'); print ''; @@ -497,7 +500,7 @@ if ($action == 'edit') { } // OAUTH service provider - if (!empty($conf->use_javascript_ajax) || (isset($conf->global->MAIN_MAIL_SENDMODE) && in_array($conf->global->MAIN_MAIL_SENDMODE, array('smtps')))) { + if (!empty($conf->use_javascript_ajax) || (isset($conf->global->MAIN_MAIL_SENDMODE) && in_array($conf->global->MAIN_MAIL_SENDMODE, array('smtps', 'swiftmailer')))) { print '
'.$langs->trans("MAIN_MAIL_SMTPS_OAUTH_SERVICE").''; // SuperAdministrator access only @@ -699,19 +702,19 @@ if ($action == 'edit') { } // AUTH method - if (isset($conf->global->MAIN_MAIL_SENDMODE) && in_array($conf->global->MAIN_MAIL_SENDMODE, array('smtps'))) { - $authtype = $conf->global->MAIN_MAIL_SMTPS_AUTH_TYPE; + if (isset($conf->global->MAIN_MAIL_SENDMODE) && in_array($conf->global->MAIN_MAIL_SENDMODE, array('smtps', 'swiftmailer'))) { + $authtype = getDolGlobalString('MAIN_MAIL_SMTPS_AUTH_TYPE', 'LOGIN'); $text = ($authtype === "LOGIN") ? $langs->trans("UsePassword") : ($authtype === "XOAUTH2" ? $langs->trans("UseOauth") : '') ; print '
'.$langs->trans("MAIN_MAIL_SMTPS_AUTH_TYPE").''.$text.'
'.$langs->trans("MAIN_MAIL_SMTPS_PW").''.preg_replace('/./', '*', $conf->global->MAIN_MAIL_SMTPS_PW).'
'.$langs->trans("MAIN_MAIL_SMTP_SERVER_NotAvailableOnLinuxLike").''.$langs->trans("SeeLocalSendMailSetup").'
'.$langs->trans("MAIN_MAIL_SMTP_SERVER", ini_get('SMTP') ?ini_get('SMTP') : $langs->transnoentities("Undefined")).''.(!empty($conf->global->MAIN_MAIL_SMTP_SERVER) ? $conf->global->MAIN_MAIL_SMTP_SERVER : '').'
'.$langs->trans("MAIN_MAIL_SMTP_PORT_NotAvailableOnLinuxLike").''.$langs->trans("SeeLocalSendMailSetup").'
'.$langs->trans("MAIN_MAIL_SMTP_PORT", ini_get('smtp_port') ?ini_get('smtp_port') : $langs->transnoentities("Undefined")).''.(!empty($conf->global->MAIN_MAIL_SMTP_PORT) ? $conf->global->MAIN_MAIL_SMTP_PORT : '').'
'.$langs->trans("MAIN_MAIL_SMTPS_ID").''.$conf->global->MAIN_MAIL_SMTPS_ID.'
'.$langs->trans("MAIN_MAIL_SMTPS_AUTH_TYPE").''.$text.'
'.$langs->trans("MAIN_MAIL_SMTPS_PW").''.preg_replace('/./', '*', $conf->global->MAIN_MAIL_SMTPS_PW).'
'.$langs->trans("MailErrorsTo").''; $out .= ''; From a465aa8f581b062475d0adadfaa03c95d1a021d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 10 Aug 2022 14:47:04 +0200 Subject: [PATCH 495/826] fix php8 warning --- htdocs/core/class/html.formmail.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php index c23545a34c9..e906fc7f7a6 100644 --- a/htdocs/core/class/html.formmail.class.php +++ b/htdocs/core/class/html.formmail.class.php @@ -604,7 +604,7 @@ class FormMail extends Form // Also add robot email if (!empty($this->fromalsorobot)) { - if (!empty($conf->global->MAIN_MAIL_EMAIL_FROM) && $conf->global->MAIN_MAIL_EMAIL_FROM != $conf->global->MAIN_INFO_SOCIETE_MAIL) { + if (!empty($conf->global->MAIN_MAIL_EMAIL_FROM) && getDolGlobalString('MAIN_MAIL_EMAIL_FROM') != getDolGlobalString('MAIN_INFO_SOCIETE_MAIL')) { $liste['robot'] = $conf->global->MAIN_MAIL_EMAIL_FROM; if ($this->frommail) { $liste['robot'] .= ' <'.$conf->global->MAIN_MAIL_EMAIL_FROM.'>'; From 3efcd5f618e9a3f248c63de767447283767d722c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 10 Aug 2022 16:29:37 +0200 Subject: [PATCH 496/826] fix log --- htdocs/core/class/CMailFile.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/CMailFile.class.php b/htdocs/core/class/CMailFile.class.php index 161be6dc72e..54573f92c7a 100644 --- a/htdocs/core/class/CMailFile.class.php +++ b/htdocs/core/class/CMailFile.class.php @@ -992,7 +992,7 @@ class CMailFile } catch (Exception $e) { // Return an error if token not found $this->errors[] = $e->getMessage(); - dol_syslog("CMailFile::sendfile: mail end error=".$this->error, LOG_ERR); + dol_syslog("CMailFile::sendfile: mail end error=".$e->getMessage(), LOG_ERR); } } if (!empty($conf->global->$keyforsslseflsigned)) { From d6494ae484db9879e96c9ef1692fef46cf1dc621 Mon Sep 17 00:00:00 2001 From: lvessiller Date: Wed, 10 Aug 2022 17:35:39 +0200 Subject: [PATCH 497/826] NEW make sell or eat by mandatory in product lot (SQL) --- htdocs/install/mysql/migration/16.0.0-17.0.0.sql | 3 +++ htdocs/install/mysql/tables/llx_product.sql | 1 + 2 files changed, 4 insertions(+) diff --git a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql index e72fc1b8dcd..ea87bd858e0 100644 --- a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql +++ b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql @@ -77,3 +77,6 @@ ALTER TABLE llx_recruitment_recruitmentcandidature ADD email_date datetime after ALTER TABLE llx_ticket ADD email_date datetime after email_msgid; INSERT INTO llx_const (name, entity, value, type, visible) VALUES ('MAIN_SECURITY_MAX_IMG_IN_HTML_CONTENT', 1, 1000, 'int', 0); + +-- Make sell-by or eat-by date mandatory +ALTER TABLE llx_product ADD COLUMN sell_or_eat_by_mandatory tinyint DEFAULT 0 NOT NULL AFTER tobatch; diff --git a/htdocs/install/mysql/tables/llx_product.sql b/htdocs/install/mysql/tables/llx_product.sql index 83e8882caa7..a234ae8ddb1 100644 --- a/htdocs/install/mysql/tables/llx_product.sql +++ b/htdocs/install/mysql/tables/llx_product.sql @@ -59,6 +59,7 @@ create table llx_product tobuy tinyint DEFAULT 1, -- Product you buy onportal tinyint DEFAULT 0, -- If it is a product you sell and you want to sell it on portal (module website must be on) tobatch tinyint DEFAULT 0 NOT NULL, -- Is it a product that need a batch management (eat-by or lot management) + sell_or_eat_by_mandatory tinyint DEFAULT 0 NOT NULL, -- Make sell-by or eat-by date mandatory batch_mask varchar(32) DEFAULT NULL, -- If the product has batch feature, you may want to use a batch mask per product fk_product_type integer DEFAULT 0, -- Type of product: 0 for regular product, 1 for service, 9 for other (used by external module) duration varchar(6), From bde596deb37fb48b5bc74c4e92294817925b1f83 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 10 Aug 2022 17:55:42 +0200 Subject: [PATCH 498/826] Upgrade to jquery-ui 1.13.2 #yogosha12015 --- COPYRIGHT | 2 +- htdocs/includes/jquery/js/jquery-ui.js | 165 +++++++++++---------- htdocs/includes/jquery/js/jquery-ui.min.js | 4 +- 3 files changed, 88 insertions(+), 83 deletions(-) diff --git a/COPYRIGHT b/COPYRIGHT index 45b3047a375..83d054d63be 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -52,7 +52,7 @@ Ace 1.4.14 BSD Yes ChartJS 3.7.1 MIT License Yes JS library for graph CKEditor 4.18 LGPL-2.1+ Yes Editor WYSIWYG jQuery 3.6.0 MIT License Yes JS library -jQuery UI 1.13.1 GPL and MIT License Yes JS library plugin UI +jQuery UI 1.13.2 GPL and MIT License Yes JS library plugin UI jQuery select2 4.0.13 GPL and Apache License Yes JS library plugin for sexier multiselect. Warning: 4.0.6+ create troubles without patching css jQuery blockUI 2.70.0 GPL and MIT License Yes JS library plugin blockUI (to use ajax popups) jQuery Colorpicker 1.1 MIT License Yes JS library for color picker for a defined list of colors diff --git a/htdocs/includes/jquery/js/jquery-ui.js b/htdocs/includes/jquery/js/jquery-ui.js index 5d9bfa2f1b1..1a613bf2f94 100644 --- a/htdocs/includes/jquery/js/jquery-ui.js +++ b/htdocs/includes/jquery/js/jquery-ui.js @@ -1,4 +1,4 @@ -/*! jQuery UI - v1.13.1 - 2022-01-20 +/*! jQuery UI - v1.13.2 - 2022-07-14 * http://jqueryui.com * Includes: widget.js, position.js, data.js, disable-selection.js, effect.js, effects/effect-blind.js, effects/effect-bounce.js, effects/effect-clip.js, effects/effect-drop.js, effects/effect-explode.js, effects/effect-fade.js, effects/effect-fold.js, effects/effect-highlight.js, effects/effect-puff.js, effects/effect-pulsate.js, effects/effect-scale.js, effects/effect-shake.js, effects/effect-size.js, effects/effect-slide.js, effects/effect-transfer.js, focusable.js, form-reset-mixin.js, jquery-patch.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/accordion.js, widgets/autocomplete.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/datepicker.js, widgets/dialog.js, widgets/draggable.js, widgets/droppable.js, widgets/menu.js, widgets/mouse.js, widgets/progressbar.js, widgets/resizable.js, widgets/selectable.js, widgets/selectmenu.js, widgets/slider.js, widgets/sortable.js, widgets/spinner.js, widgets/tabs.js, widgets/tooltip.js * Copyright jQuery Foundation and other contributors; Licensed MIT */ @@ -20,11 +20,11 @@ $.ui = $.ui || {}; -var version = $.ui.version = "1.13.1"; +var version = $.ui.version = "1.13.2"; /*! - * jQuery UI Widget 1.13.1 + * jQuery UI Widget 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -766,7 +766,7 @@ var widget = $.widget; /*! - * jQuery UI Position 1.13.1 + * jQuery UI Position 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -1263,7 +1263,7 @@ var position = $.ui.position; /*! - * jQuery UI :data 1.13.1 + * jQuery UI :data 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -1292,7 +1292,7 @@ var data = $.extend( $.expr.pseudos, { } ); /*! - * jQuery UI Disable Selection 1.13.1 + * jQuery UI Disable Selection 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -2047,7 +2047,7 @@ colors = jQuery.Color.names = { /*! - * jQuery UI Effects 1.13.1 + * jQuery UI Effects 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -2431,7 +2431,7 @@ if ( $.uiBackCompat !== false ) { } $.extend( $.effects, { - version: "1.13.1", + version: "1.13.2", define: function( name, mode, effect ) { if ( !effect ) { @@ -2999,7 +2999,7 @@ var effect = $.effects; /*! - * jQuery UI Effects Blind 1.13.1 + * jQuery UI Effects Blind 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -3054,7 +3054,7 @@ var effectsEffectBlind = $.effects.define( "blind", "hide", function( options, d /*! - * jQuery UI Effects Bounce 1.13.1 + * jQuery UI Effects Bounce 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -3149,7 +3149,7 @@ var effectsEffectBounce = $.effects.define( "bounce", function( options, done ) /*! - * jQuery UI Effects Clip 1.13.1 + * jQuery UI Effects Clip 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -3199,7 +3199,7 @@ var effectsEffectClip = $.effects.define( "clip", "hide", function( options, don /*! - * jQuery UI Effects Drop 1.13.1 + * jQuery UI Effects Drop 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -3253,7 +3253,7 @@ var effectsEffectDrop = $.effects.define( "drop", "hide", function( options, don /*! - * jQuery UI Effects Explode 1.13.1 + * jQuery UI Effects Explode 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -3349,7 +3349,7 @@ var effectsEffectExplode = $.effects.define( "explode", "hide", function( option /*! - * jQuery UI Effects Fade 1.13.1 + * jQuery UI Effects Fade 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -3381,7 +3381,7 @@ var effectsEffectFade = $.effects.define( "fade", "toggle", function( options, d /*! - * jQuery UI Effects Fold 1.13.1 + * jQuery UI Effects Fold 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -3455,7 +3455,7 @@ var effectsEffectFold = $.effects.define( "fold", "hide", function( options, don /*! - * jQuery UI Effects Highlight 1.13.1 + * jQuery UI Effects Highlight 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -3497,7 +3497,7 @@ var effectsEffectHighlight = $.effects.define( "highlight", "show", function( op /*! - * jQuery UI Effects Size 1.13.1 + * jQuery UI Effects Size 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -3675,7 +3675,7 @@ var effectsEffectSize = $.effects.define( "size", function( options, done ) { /*! - * jQuery UI Effects Scale 1.13.1 + * jQuery UI Effects Scale 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -3715,7 +3715,7 @@ var effectsEffectScale = $.effects.define( "scale", function( options, done ) { /*! - * jQuery UI Effects Puff 1.13.1 + * jQuery UI Effects Puff 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -3741,7 +3741,7 @@ var effectsEffectPuff = $.effects.define( "puff", "hide", function( options, don /*! - * jQuery UI Effects Pulsate 1.13.1 + * jQuery UI Effects Pulsate 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -3790,7 +3790,7 @@ var effectsEffectPulsate = $.effects.define( "pulsate", "show", function( option /*! - * jQuery UI Effects Shake 1.13.1 + * jQuery UI Effects Shake 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -3849,7 +3849,7 @@ var effectsEffectShake = $.effects.define( "shake", function( options, done ) { /*! - * jQuery UI Effects Slide 1.13.1 + * jQuery UI Effects Slide 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -3910,7 +3910,7 @@ var effectsEffectSlide = $.effects.define( "slide", "show", function( options, d /*! - * jQuery UI Effects Transfer 1.13.1 + * jQuery UI Effects Transfer 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -3935,7 +3935,7 @@ var effectsEffectTransfer = effect; /*! - * jQuery UI Focusable 1.13.1 + * jQuery UI Focusable 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -4017,7 +4017,7 @@ var form = $.fn._form = function() { /*! - * jQuery UI Form Reset Mixin 1.13.1 + * jQuery UI Form Reset Mixin 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -4079,7 +4079,7 @@ var formResetMixin = $.ui.formResetMixin = { /*! - * jQuery UI Support for jQuery core 1.8.x and newer 1.13.1 + * jQuery UI Support for jQuery core 1.8.x and newer 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -4154,7 +4154,7 @@ if ( !$.fn.even || !$.fn.odd ) { ; /*! - * jQuery UI Keycode 1.13.1 + * jQuery UI Keycode 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -4189,7 +4189,7 @@ var keycode = $.ui.keyCode = { /*! - * jQuery UI Labels 1.13.1 + * jQuery UI Labels 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -4244,7 +4244,7 @@ var labels = $.fn.labels = function() { /*! - * jQuery UI Scroll Parent 1.13.1 + * jQuery UI Scroll Parent 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -4278,7 +4278,7 @@ var scrollParent = $.fn.scrollParent = function( includeHidden ) { /*! - * jQuery UI Tabbable 1.13.1 + * jQuery UI Tabbable 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -4302,7 +4302,7 @@ var tabbable = $.extend( $.expr.pseudos, { /*! - * jQuery UI Unique ID 1.13.1 + * jQuery UI Unique ID 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -4340,7 +4340,7 @@ var uniqueId = $.fn.extend( { /*! - * jQuery UI Accordion 1.13.1 + * jQuery UI Accordion 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -4361,7 +4361,7 @@ var uniqueId = $.fn.extend( { var widgetsAccordion = $.widget( "ui.accordion", { - version: "1.13.1", + version: "1.13.2", options: { active: 0, animate: {}, @@ -4972,7 +4972,7 @@ var safeActiveElement = $.ui.safeActiveElement = function( document ) { /*! - * jQuery UI Menu 1.13.1 + * jQuery UI Menu 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -4991,7 +4991,7 @@ var safeActiveElement = $.ui.safeActiveElement = function( document ) { var widgetsMenu = $.widget( "ui.menu", { - version: "1.13.1", + version: "1.13.2", defaultElement: "
 
",x=o?"":"",g=0;g<7;g++)x+="";for(w+=x+"",D=this._getDaysInMonth(U,K),U===t.selectedYear&&K===t.selectedMonth&&(t.selectedDay=Math.min(t.selectedDay,D)),C=(this._getFirstDayOfMonth(U,K)-n+7)%7,D=Math.ceil((C+D)/7),I=Y&&this.maxRows>D?this.maxRows:D,this.maxRows=I,T=this._daylightSavingAdjust(new Date(U,K,1-C)),P=0;P",M=o?"":"",g=0;g<7;g++)S=c?c.apply(t.input?t.input[0]:null,[T]):[!0,""],z=(H=T.getMonth()!==K)&&!d||!S[0]||j&&T"+(H&&!u?" ":z?""+T.getDate()+"":""+T.getDate()+"")+"",T.setDate(T.getDate()+1),T=this._daylightSavingAdjust(T);w+=M+""}11<++K&&(K=0,U++),_+=w+="
"+this._get(t,"weekHeader")+""+r[k]+"
"+this._get(t,"calculateWeek")(T)+"
"+(Y?""+(0":""):"")}f+=_}return f+=F,t._keyEvent=!1,f},_generateMonthYearHeader:function(t,e,i,s,n,o,a,r){var l,h,c,u,d,p,f=this._get(t,"changeMonth"),g=this._get(t,"changeYear"),m=this._get(t,"showMonthAfterYear"),_=this._get(t,"selectMonthLabel"),v=this._get(t,"selectYearLabel"),b="
",y="";if(o||!f)y+=""+a[e]+"";else{for(l=s&&s.getFullYear()===i,h=n&&n.getFullYear()===i,y+=""}if(m||(b+=y+(!o&&f&&g?"":" ")),!t.yearshtml)if(t.yearshtml="",o||!g)b+=""+i+"";else{for(a=this._get(t,"yearRange").split(":"),u=(new Date).getFullYear(),d=(_=function(t){t=t.match(/c[+\-].*/)?i+parseInt(t.substring(1),10):t.match(/[+\-].*/)?u+parseInt(t,10):parseInt(t,10);return isNaN(t)?u:t})(a[0]),p=Math.max(d,_(a[1]||"")),d=s?Math.max(d,s.getFullYear()):d,p=n?Math.min(p,n.getFullYear()):p,t.yearshtml+="",b+=t.yearshtml,t.yearshtml=null}return b+=this._get(t,"yearSuffix"),m&&(b+=(!o&&f&&g?"":" ")+y),b+="
"},_adjustInstDate:function(t,e,i){var s=t.selectedYear+("Y"===i?e:0),n=t.selectedMonth+("M"===i?e:0),e=Math.min(t.selectedDay,this._getDaysInMonth(s,n))+("D"===i?e:0),e=this._restrictMinMax(t,this._daylightSavingAdjust(new Date(s,n,e)));t.selectedDay=e.getDate(),t.drawMonth=t.selectedMonth=e.getMonth(),t.drawYear=t.selectedYear=e.getFullYear(),"M"!==i&&"Y"!==i||this._notifyChange(t)},_restrictMinMax:function(t,e){var i=this._getMinMaxDate(t,"min"),t=this._getMinMaxDate(t,"max"),e=i&&e=i.getTime())&&(!s||e.getTime()<=s.getTime())&&(!n||e.getFullYear()>=n)&&(!o||e.getFullYear()<=o)},_getFormatConfig:function(t){var e=this._get(t,"shortYearCutoff");return{shortYearCutoff:e="string"!=typeof e?e:(new Date).getFullYear()%100+parseInt(e,10),dayNamesShort:this._get(t,"dayNamesShort"),dayNames:this._get(t,"dayNames"),monthNamesShort:this._get(t,"monthNamesShort"),monthNames:this._get(t,"monthNames")}},_formatDate:function(t,e,i,s){e||(t.currentDay=t.selectedDay,t.currentMonth=t.selectedMonth,t.currentYear=t.selectedYear);e=e?"object"==typeof e?e:this._daylightSavingAdjust(new Date(s,i,e)):this._daylightSavingAdjust(new Date(t.currentYear,t.currentMonth,t.currentDay));return this.formatDate(this._get(t,"dateFormat"),e,this._getFormatConfig(t))}}),V.fn.datepicker=function(t){if(!this.length)return this;V.datepicker.initialized||(V(document).on("mousedown",V.datepicker._checkExternalClick),V.datepicker.initialized=!0),0===V("#"+V.datepicker._mainDivId).length&&V("body").append(V.datepicker.dpDiv);var e=Array.prototype.slice.call(arguments,1);return"string"==typeof t&&("isDisabled"===t||"getDate"===t||"widget"===t)||"option"===t&&2===arguments.length&&"string"==typeof arguments[1]?V.datepicker["_"+t+"Datepicker"].apply(V.datepicker,[this[0]].concat(e)):this.each(function(){"string"==typeof t?V.datepicker["_"+t+"Datepicker"].apply(V.datepicker,[this].concat(e)):V.datepicker._attachDatepicker(this,t)})},V.datepicker=new st,V.datepicker.initialized=!1,V.datepicker.uuid=(new Date).getTime(),V.datepicker.version="1.13.2";V.datepicker,V.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase());var rt=!1;V(document).on("mouseup",function(){rt=!1});V.widget("ui.mouse",{version:"1.13.2",options:{cancel:"input, textarea, button, select, option",distance:1,delay:0},_mouseInit:function(){var e=this;this.element.on("mousedown."+this.widgetName,function(t){return e._mouseDown(t)}).on("click."+this.widgetName,function(t){if(!0===V.data(t.target,e.widgetName+".preventClickEvent"))return V.removeData(t.target,e.widgetName+".preventClickEvent"),t.stopImmediatePropagation(),!1}),this.started=!1},_mouseDestroy:function(){this.element.off("."+this.widgetName),this._mouseMoveDelegate&&this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(t){if(!rt){this._mouseMoved=!1,this._mouseStarted&&this._mouseUp(t),this._mouseDownEvent=t;var e=this,i=1===t.which,s=!("string"!=typeof this.options.cancel||!t.target.nodeName)&&V(t.target).closest(this.options.cancel).length;return i&&!s&&this._mouseCapture(t)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){e.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=!1!==this._mouseStart(t),!this._mouseStarted)?(t.preventDefault(),!0):(!0===V.data(t.target,this.widgetName+".preventClickEvent")&&V.removeData(t.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(t){return e._mouseMove(t)},this._mouseUpDelegate=function(t){return e._mouseUp(t)},this.document.on("mousemove."+this.widgetName,this._mouseMoveDelegate).on("mouseup."+this.widgetName,this._mouseUpDelegate),t.preventDefault(),rt=!0)):!0}},_mouseMove:function(t){if(this._mouseMoved){if(V.ui.ie&&(!document.documentMode||document.documentMode<9)&&!t.button)return this._mouseUp(t);if(!t.which)if(t.originalEvent.altKey||t.originalEvent.ctrlKey||t.originalEvent.metaKey||t.originalEvent.shiftKey)this.ignoreMissingWhich=!0;else if(!this.ignoreMissingWhich)return this._mouseUp(t)}return(t.which||t.button)&&(this._mouseMoved=!0),this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=!1!==this._mouseStart(this._mouseDownEvent,t),this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&V.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),this._mouseDelayTimer&&(clearTimeout(this._mouseDelayTimer),delete this._mouseDelayTimer),this.ignoreMissingWhich=!1,rt=!1,t.preventDefault()},_mouseDistanceMet:function(t){return Math.max(Math.abs(this._mouseDownEvent.pageX-t.pageX),Math.abs(this._mouseDownEvent.pageY-t.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),V.ui.plugin={add:function(t,e,i){var s,n=V.ui[t].prototype;for(s in i)n.plugins[s]=n.plugins[s]||[],n.plugins[s].push([e,i[s]])},call:function(t,e,i,s){var n,o=t.plugins[e];if(o&&(s||t.element[0].parentNode&&11!==t.element[0].parentNode.nodeType))for(n=0;n").css("position","absolute").appendTo(t.parent()).outerWidth(t.outerWidth()).outerHeight(t.outerHeight()).offset(t.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_blurActiveElement:function(t){var e=V.ui.safeActiveElement(this.document[0]);V(t.target).closest(e).length||V.ui.safeBlur(e)},_mouseStart:function(t){var e=this.options;return this.helper=this._createHelper(t),this._addClass(this.helper,"ui-draggable-dragging"),this._cacheHelperProportions(),V.ui.ddmanager&&(V.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(!0),this.offsetParent=this.helper.offsetParent(),this.hasFixedAncestor=0i[2]&&(o=i[2]+this.offset.click.left),t.pageY-this.offset.click.top>i[3]&&(a=i[3]+this.offset.click.top)),s.grid&&(t=s.grid[1]?this.originalPageY+Math.round((a-this.originalPageY)/s.grid[1])*s.grid[1]:this.originalPageY,a=!i||t-this.offset.click.top>=i[1]||t-this.offset.click.top>i[3]?t:t-this.offset.click.top>=i[1]?t-s.grid[1]:t+s.grid[1],t=s.grid[0]?this.originalPageX+Math.round((o-this.originalPageX)/s.grid[0])*s.grid[0]:this.originalPageX,o=!i||t-this.offset.click.left>=i[0]||t-this.offset.click.left>i[2]?t:t-this.offset.click.left>=i[0]?t-s.grid[0]:t+s.grid[0]),"y"===s.axis&&(o=this.originalPageX),"x"===s.axis&&(a=this.originalPageY)),{top:a-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.offset.scroll.top:n?0:this.offset.scroll.top),left:o-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.offset.scroll.left:n?0:this.offset.scroll.left)}},_clear:function(){this._removeClass(this.helper,"ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1,this.destroyOnClear&&this.destroy()},_trigger:function(t,e,i){return i=i||this._uiHash(),V.ui.plugin.call(this,t,[e,i,this],!0),/^(drag|start|stop)/.test(t)&&(this.positionAbs=this._convertPositionTo("absolute"),i.offset=this.positionAbs),V.Widget.prototype._trigger.call(this,t,e,i)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),V.ui.plugin.add("draggable","connectToSortable",{start:function(e,t,i){var s=V.extend({},t,{item:i.element});i.sortables=[],V(i.options.connectToSortable).each(function(){var t=V(this).sortable("instance");t&&!t.options.disabled&&(i.sortables.push(t),t.refreshPositions(),t._trigger("activate",e,s))})},stop:function(e,t,i){var s=V.extend({},t,{item:i.element});i.cancelHelperRemoval=!1,V.each(i.sortables,function(){var t=this;t.isOver?(t.isOver=0,i.cancelHelperRemoval=!0,t.cancelHelperRemoval=!1,t._storedCSS={position:t.placeholder.css("position"),top:t.placeholder.css("top"),left:t.placeholder.css("left")},t._mouseStop(e),t.options.helper=t.options._helper):(t.cancelHelperRemoval=!0,t._trigger("deactivate",e,s))})},drag:function(i,s,n){V.each(n.sortables,function(){var t=!1,e=this;e.positionAbs=n.positionAbs,e.helperProportions=n.helperProportions,e.offset.click=n.offset.click,e._intersectsWith(e.containerCache)&&(t=!0,V.each(n.sortables,function(){return this.positionAbs=n.positionAbs,this.helperProportions=n.helperProportions,this.offset.click=n.offset.click,t=this!==e&&this._intersectsWith(this.containerCache)&&V.contains(e.element[0],this.element[0])?!1:t})),t?(e.isOver||(e.isOver=1,n._parent=s.helper.parent(),e.currentItem=s.helper.appendTo(e.element).data("ui-sortable-item",!0),e.options._helper=e.options.helper,e.options.helper=function(){return s.helper[0]},i.target=e.currentItem[0],e._mouseCapture(i,!0),e._mouseStart(i,!0,!0),e.offset.click.top=n.offset.click.top,e.offset.click.left=n.offset.click.left,e.offset.parent.left-=n.offset.parent.left-e.offset.parent.left,e.offset.parent.top-=n.offset.parent.top-e.offset.parent.top,n._trigger("toSortable",i),n.dropped=e.element,V.each(n.sortables,function(){this.refreshPositions()}),n.currentItem=n.element,e.fromOutside=n),e.currentItem&&(e._mouseDrag(i),s.position=e.position)):e.isOver&&(e.isOver=0,e.cancelHelperRemoval=!0,e.options._revert=e.options.revert,e.options.revert=!1,e._trigger("out",i,e._uiHash(e)),e._mouseStop(i,!0),e.options.revert=e.options._revert,e.options.helper=e.options._helper,e.placeholder&&e.placeholder.remove(),s.helper.appendTo(n._parent),n._refreshOffsets(i),s.position=n._generatePosition(i,!0),n._trigger("fromSortable",i),n.dropped=!1,V.each(n.sortables,function(){this.refreshPositions()}))})}}),V.ui.plugin.add("draggable","cursor",{start:function(t,e,i){var s=V("body"),i=i.options;s.css("cursor")&&(i._cursor=s.css("cursor")),s.css("cursor",i.cursor)},stop:function(t,e,i){i=i.options;i._cursor&&V("body").css("cursor",i._cursor)}}),V.ui.plugin.add("draggable","opacity",{start:function(t,e,i){e=V(e.helper),i=i.options;e.css("opacity")&&(i._opacity=e.css("opacity")),e.css("opacity",i.opacity)},stop:function(t,e,i){i=i.options;i._opacity&&V(e.helper).css("opacity",i._opacity)}}),V.ui.plugin.add("draggable","scroll",{start:function(t,e,i){i.scrollParentNotHidden||(i.scrollParentNotHidden=i.helper.scrollParent(!1)),i.scrollParentNotHidden[0]!==i.document[0]&&"HTML"!==i.scrollParentNotHidden[0].tagName&&(i.overflowOffset=i.scrollParentNotHidden.offset())},drag:function(t,e,i){var s=i.options,n=!1,o=i.scrollParentNotHidden[0],a=i.document[0];o!==a&&"HTML"!==o.tagName?(s.axis&&"x"===s.axis||(i.overflowOffset.top+o.offsetHeight-t.pageY").css({overflow:"hidden",position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.resizable("instance")),this.elementIsWrapper=!0,t={marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom"),marginLeft:this.originalElement.css("marginLeft")},this.element.css(t),this.originalElement.css("margin",0),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css(t),this._proportionallyResize()),this._setupHandles(),e.autoHide&&V(this.element).on("mouseenter",function(){e.disabled||(i._removeClass("ui-resizable-autohide"),i._handles.show())}).on("mouseleave",function(){e.disabled||i.resizing||(i._addClass("ui-resizable-autohide"),i._handles.hide())}),this._mouseInit()},_destroy:function(){this._mouseDestroy(),this._addedHandles.remove();function t(t){V(t).removeData("resizable").removeData("ui-resizable").off(".resizable")}var e;return this.elementIsWrapper&&(t(this.element),e=this.element,this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")}).insertAfter(e),e.remove()),this.originalElement.css("resize",this.originalResizeStyle),t(this.originalElement),this},_setOption:function(t,e){switch(this._super(t,e),t){case"handles":this._removeHandles(),this._setupHandles();break;case"aspectRatio":this._aspectRatio=!!e}},_setupHandles:function(){var t,e,i,s,n,o=this.options,a=this;if(this.handles=o.handles||(V(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this._handles=V(),this._addedHandles=V(),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),i=this.handles.split(","),this.handles={},e=0;e"),this._addClass(n,"ui-resizable-handle "+s),n.css({zIndex:o.zIndex}),this.handles[t]=".ui-resizable-"+t,this.element.children(this.handles[t]).length||(this.element.append(n),this._addedHandles=this._addedHandles.add(n));this._renderAxis=function(t){var e,i,s;for(e in t=t||this.element,this.handles)this.handles[e].constructor===String?this.handles[e]=this.element.children(this.handles[e]).first().show():(this.handles[e].jquery||this.handles[e].nodeType)&&(this.handles[e]=V(this.handles[e]),this._on(this.handles[e],{mousedown:a._mouseDown})),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)&&(i=V(this.handles[e],this.element),s=/sw|ne|nw|se|n|s/.test(e)?i.outerHeight():i.outerWidth(),i=["padding",/ne|nw|n/.test(e)?"Top":/se|sw|s/.test(e)?"Bottom":/^e$/.test(e)?"Right":"Left"].join(""),t.css(i,s),this._proportionallyResize()),this._handles=this._handles.add(this.handles[e])},this._renderAxis(this.element),this._handles=this._handles.add(this.element.find(".ui-resizable-handle")),this._handles.disableSelection(),this._handles.on("mouseover",function(){a.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),a.axis=n&&n[1]?n[1]:"se")}),o.autoHide&&(this._handles.hide(),this._addClass("ui-resizable-autohide"))},_removeHandles:function(){this._addedHandles.remove()},_mouseCapture:function(t){var e,i,s=!1;for(e in this.handles)(i=V(this.handles[e])[0])!==t.target&&!V.contains(i,t.target)||(s=!0);return!this.options.disabled&&s},_mouseStart:function(t){var e,i,s=this.options,n=this.element;return this.resizing=!0,this._renderProxy(),e=this._num(this.helper.css("left")),i=this._num(this.helper.css("top")),s.containment&&(e+=V(s.containment).scrollLeft()||0,i+=V(s.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:e,top:i},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:n.width(),height:n.height()},this.originalSize=this._helper?{width:n.outerWidth(),height:n.outerHeight()}:{width:n.width(),height:n.height()},this.sizeDiff={width:n.outerWidth()-n.width(),height:n.outerHeight()-n.height()},this.originalPosition={left:e,top:i},this.originalMousePosition={left:t.pageX,top:t.pageY},this.aspectRatio="number"==typeof s.aspectRatio?s.aspectRatio:this.originalSize.width/this.originalSize.height||1,s=V(".ui-resizable-"+this.axis).css("cursor"),V("body").css("cursor","auto"===s?this.axis+"-resize":s),this._addClass("ui-resizable-resizing"),this._propagate("start",t),!0},_mouseDrag:function(t){var e=this.originalMousePosition,i=this.axis,s=t.pageX-e.left||0,e=t.pageY-e.top||0,i=this._change[i];return this._updatePrevProperties(),i&&(e=i.apply(this,[t,s,e]),this._updateVirtualBoundaries(t.shiftKey),(this._aspectRatio||t.shiftKey)&&(e=this._updateRatio(e,t)),e=this._respectSize(e,t),this._updateCache(e),this._propagate("resize",t),e=this._applyChanges(),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),V.isEmptyObject(e)||(this._updatePrevProperties(),this._trigger("resize",t,this.ui()),this._applyChanges())),!1},_mouseStop:function(t){this.resizing=!1;var e,i,s,n=this.options,o=this;return this._helper&&(s=(e=(i=this._proportionallyResizeElements).length&&/textarea/i.test(i[0].nodeName))&&this._hasScroll(i[0],"left")?0:o.sizeDiff.height,i=e?0:o.sizeDiff.width,e={width:o.helper.width()-i,height:o.helper.height()-s},i=parseFloat(o.element.css("left"))+(o.position.left-o.originalPosition.left)||null,s=parseFloat(o.element.css("top"))+(o.position.top-o.originalPosition.top)||null,n.animate||this.element.css(V.extend(e,{top:s,left:i})),o.helper.height(o.size.height),o.helper.width(o.size.width),this._helper&&!n.animate&&this._proportionallyResize()),V("body").css("cursor","auto"),this._removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updatePrevProperties:function(){this.prevPosition={top:this.position.top,left:this.position.left},this.prevSize={width:this.size.width,height:this.size.height}},_applyChanges:function(){var t={};return this.position.top!==this.prevPosition.top&&(t.top=this.position.top+"px"),this.position.left!==this.prevPosition.left&&(t.left=this.position.left+"px"),this.size.width!==this.prevSize.width&&(t.width=this.size.width+"px"),this.size.height!==this.prevSize.height&&(t.height=this.size.height+"px"),this.helper.css(t),t},_updateVirtualBoundaries:function(t){var e,i,s=this.options,n={minWidth:this._isNumber(s.minWidth)?s.minWidth:0,maxWidth:this._isNumber(s.maxWidth)?s.maxWidth:1/0,minHeight:this._isNumber(s.minHeight)?s.minHeight:0,maxHeight:this._isNumber(s.maxHeight)?s.maxHeight:1/0};(this._aspectRatio||t)&&(e=n.minHeight*this.aspectRatio,i=n.minWidth/this.aspectRatio,s=n.maxHeight*this.aspectRatio,t=n.maxWidth/this.aspectRatio,e>n.minWidth&&(n.minWidth=e),i>n.minHeight&&(n.minHeight=i),st.width,a=this._isNumber(t.height)&&e.minHeight&&e.minHeight>t.height,r=this.originalPosition.left+this.originalSize.width,l=this.originalPosition.top+this.originalSize.height,h=/sw|nw|w/.test(i),i=/nw|ne|n/.test(i);return o&&(t.width=e.minWidth),a&&(t.height=e.minHeight),s&&(t.width=e.maxWidth),n&&(t.height=e.maxHeight),o&&h&&(t.left=r-e.minWidth),s&&h&&(t.left=r-e.maxWidth),a&&i&&(t.top=l-e.minHeight),n&&i&&(t.top=l-e.maxHeight),t.width||t.height||t.left||!t.top?t.width||t.height||t.top||!t.left||(t.left=null):t.top=null,t},_getPaddingPlusBorderDimensions:function(t){for(var e=0,i=[],s=[t.css("borderTopWidth"),t.css("borderRightWidth"),t.css("borderBottomWidth"),t.css("borderLeftWidth")],n=[t.css("paddingTop"),t.css("paddingRight"),t.css("paddingBottom"),t.css("paddingLeft")];e<4;e++)i[e]=parseFloat(s[e])||0,i[e]+=parseFloat(n[e])||0;return{height:i[0]+i[2],width:i[1]+i[3]}},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var t,e=0,i=this.helper||this.element;e").css({overflow:"hidden"}),this._addClass(this.helper,this._helper),this.helper.css({width:this.element.outerWidth(),height:this.element.outerHeight(),position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++e.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(t,e){return{width:this.originalSize.width+e}},w:function(t,e){var i=this.originalSize;return{left:this.originalPosition.left+e,width:i.width-e}},n:function(t,e,i){var s=this.originalSize;return{top:this.originalPosition.top+i,height:s.height-i}},s:function(t,e,i){return{height:this.originalSize.height+i}},se:function(t,e,i){return V.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,e,i]))},sw:function(t,e,i){return V.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,e,i]))},ne:function(t,e,i){return V.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,e,i]))},nw:function(t,e,i){return V.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,e,i]))}},_propagate:function(t,e){V.ui.plugin.call(this,t,[e,this.ui()]),"resize"!==t&&this._trigger(t,e,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),V.ui.plugin.add("resizable","animate",{stop:function(e){var i=V(this).resizable("instance"),t=i.options,s=i._proportionallyResizeElements,n=s.length&&/textarea/i.test(s[0].nodeName),o=n&&i._hasScroll(s[0],"left")?0:i.sizeDiff.height,a=n?0:i.sizeDiff.width,n={width:i.size.width-a,height:i.size.height-o},a=parseFloat(i.element.css("left"))+(i.position.left-i.originalPosition.left)||null,o=parseFloat(i.element.css("top"))+(i.position.top-i.originalPosition.top)||null;i.element.animate(V.extend(n,o&&a?{top:o,left:a}:{}),{duration:t.animateDuration,easing:t.animateEasing,step:function(){var t={width:parseFloat(i.element.css("width")),height:parseFloat(i.element.css("height")),top:parseFloat(i.element.css("top")),left:parseFloat(i.element.css("left"))};s&&s.length&&V(s[0]).css({width:t.width,height:t.height}),i._updateCache(t),i._propagate("resize",e)}})}}),V.ui.plugin.add("resizable","containment",{start:function(){var i,s,n=V(this).resizable("instance"),t=n.options,e=n.element,o=t.containment,a=o instanceof V?o.get(0):/parent/.test(o)?e.parent().get(0):o;a&&(n.containerElement=V(a),/document/.test(o)||o===document?(n.containerOffset={left:0,top:0},n.containerPosition={left:0,top:0},n.parentData={element:V(document),left:0,top:0,width:V(document).width(),height:V(document).height()||document.body.parentNode.scrollHeight}):(i=V(a),s=[],V(["Top","Right","Left","Bottom"]).each(function(t,e){s[t]=n._num(i.css("padding"+e))}),n.containerOffset=i.offset(),n.containerPosition=i.position(),n.containerSize={height:i.innerHeight()-s[3],width:i.innerWidth()-s[1]},t=n.containerOffset,e=n.containerSize.height,o=n.containerSize.width,o=n._hasScroll(a,"left")?a.scrollWidth:o,e=n._hasScroll(a)?a.scrollHeight:e,n.parentData={element:a,left:t.left,top:t.top,width:o,height:e}))},resize:function(t){var e=V(this).resizable("instance"),i=e.options,s=e.containerOffset,n=e.position,o=e._aspectRatio||t.shiftKey,a={top:0,left:0},r=e.containerElement,t=!0;r[0]!==document&&/static/.test(r.css("position"))&&(a=s),n.left<(e._helper?s.left:0)&&(e.size.width=e.size.width+(e._helper?e.position.left-s.left:e.position.left-a.left),o&&(e.size.height=e.size.width/e.aspectRatio,t=!1),e.position.left=i.helper?s.left:0),n.top<(e._helper?s.top:0)&&(e.size.height=e.size.height+(e._helper?e.position.top-s.top:e.position.top),o&&(e.size.width=e.size.height*e.aspectRatio,t=!1),e.position.top=e._helper?s.top:0),i=e.containerElement.get(0)===e.element.parent().get(0),n=/relative|absolute/.test(e.containerElement.css("position")),i&&n?(e.offset.left=e.parentData.left+e.position.left,e.offset.top=e.parentData.top+e.position.top):(e.offset.left=e.element.offset().left,e.offset.top=e.element.offset().top),n=Math.abs(e.sizeDiff.width+(e._helper?e.offset.left-a.left:e.offset.left-s.left)),s=Math.abs(e.sizeDiff.height+(e._helper?e.offset.top-a.top:e.offset.top-s.top)),n+e.size.width>=e.parentData.width&&(e.size.width=e.parentData.width-n,o&&(e.size.height=e.size.width/e.aspectRatio,t=!1)),s+e.size.height>=e.parentData.height&&(e.size.height=e.parentData.height-s,o&&(e.size.width=e.size.height*e.aspectRatio,t=!1)),t||(e.position.left=e.prevPosition.left,e.position.top=e.prevPosition.top,e.size.width=e.prevSize.width,e.size.height=e.prevSize.height)},stop:function(){var t=V(this).resizable("instance"),e=t.options,i=t.containerOffset,s=t.containerPosition,n=t.containerElement,o=V(t.helper),a=o.offset(),r=o.outerWidth()-t.sizeDiff.width,o=o.outerHeight()-t.sizeDiff.height;t._helper&&!e.animate&&/relative/.test(n.css("position"))&&V(this).css({left:a.left-s.left-i.left,width:r,height:o}),t._helper&&!e.animate&&/static/.test(n.css("position"))&&V(this).css({left:a.left-s.left-i.left,width:r,height:o})}}),V.ui.plugin.add("resizable","alsoResize",{start:function(){var t=V(this).resizable("instance").options;V(t.alsoResize).each(function(){var t=V(this);t.data("ui-resizable-alsoresize",{width:parseFloat(t.width()),height:parseFloat(t.height()),left:parseFloat(t.css("left")),top:parseFloat(t.css("top"))})})},resize:function(t,i){var e=V(this).resizable("instance"),s=e.options,n=e.originalSize,o=e.originalPosition,a={height:e.size.height-n.height||0,width:e.size.width-n.width||0,top:e.position.top-o.top||0,left:e.position.left-o.left||0};V(s.alsoResize).each(function(){var t=V(this),s=V(this).data("ui-resizable-alsoresize"),n={},e=t.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];V.each(e,function(t,e){var i=(s[e]||0)+(a[e]||0);i&&0<=i&&(n[e]=i||null)}),t.css(n)})},stop:function(){V(this).removeData("ui-resizable-alsoresize")}}),V.ui.plugin.add("resizable","ghost",{start:function(){var t=V(this).resizable("instance"),e=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:e.height,width:e.width,margin:0,left:0,top:0}),t._addClass(t.ghost,"ui-resizable-ghost"),!1!==V.uiBackCompat&&"string"==typeof t.options.ghost&&t.ghost.addClass(this.options.ghost),t.ghost.appendTo(t.helper)},resize:function(){var t=V(this).resizable("instance");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=V(this).resizable("instance");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),V.ui.plugin.add("resizable","grid",{resize:function(){var t,e=V(this).resizable("instance"),i=e.options,s=e.size,n=e.originalSize,o=e.originalPosition,a=e.axis,r="number"==typeof i.grid?[i.grid,i.grid]:i.grid,l=r[0]||1,h=r[1]||1,c=Math.round((s.width-n.width)/l)*l,u=Math.round((s.height-n.height)/h)*h,d=n.width+c,p=n.height+u,f=i.maxWidth&&i.maxWidthd,s=i.minHeight&&i.minHeight>p;i.grid=r,m&&(d+=l),s&&(p+=h),f&&(d-=l),g&&(p-=h),/^(se|s|e)$/.test(a)?(e.size.width=d,e.size.height=p):/^(ne)$/.test(a)?(e.size.width=d,e.size.height=p,e.position.top=o.top-u):/^(sw)$/.test(a)?(e.size.width=d,e.size.height=p,e.position.left=o.left-c):((p-h<=0||d-l<=0)&&(t=e._getPaddingPlusBorderDimensions(this)),0=+this.uiDialog.css("z-index")&&(this.uiDialog.css("z-index",s+1),i=!0),i&&!e&&this._trigger("focus",t),i},open:function(){var t=this;this._isOpen?this._moveToTop()&&this._focusTabbable():(this._isOpen=!0,this.opener=V(V.ui.safeActiveElement(this.document[0])),this._size(),this._position(),this._createOverlay(),this._moveToTop(null,!0),this.overlay&&this.overlay.css("z-index",this.uiDialog.css("z-index")-1),this._show(this.uiDialog,this.options.show,function(){t._focusTabbable(),t._trigger("focus")}),this._makeFocusTarget(),this._trigger("open"))},_focusTabbable:function(){var t=this._focusedElement;(t=!(t=!(t=!(t=!(t=t||this.element.find("[autofocus]")).length?this.element.find(":tabbable"):t).length?this.uiDialogButtonPane.find(":tabbable"):t).length?this.uiDialogTitlebarClose.filter(":tabbable"):t).length?this.uiDialog:t).eq(0).trigger("focus")},_restoreTabbableFocus:function(){var t=V.ui.safeActiveElement(this.document[0]);this.uiDialog[0]===t||V.contains(this.uiDialog[0],t)||this._focusTabbable()},_keepFocus:function(t){t.preventDefault(),this._restoreTabbableFocus(),this._delay(this._restoreTabbableFocus)},_createWrapper:function(){this.uiDialog=V("
").hide().attr({tabIndex:-1,role:"dialog"}).appendTo(this._appendTo()),this._addClass(this.uiDialog,"ui-dialog","ui-widget ui-widget-content ui-front"),this._on(this.uiDialog,{keydown:function(t){if(this.options.closeOnEscape&&!t.isDefaultPrevented()&&t.keyCode&&t.keyCode===V.ui.keyCode.ESCAPE)return t.preventDefault(),void this.close(t);var e,i,s;t.keyCode!==V.ui.keyCode.TAB||t.isDefaultPrevented()||(e=this.uiDialog.find(":tabbable"),i=e.first(),s=e.last(),t.target!==s[0]&&t.target!==this.uiDialog[0]||t.shiftKey?t.target!==i[0]&&t.target!==this.uiDialog[0]||!t.shiftKey||(this._delay(function(){s.trigger("focus")}),t.preventDefault()):(this._delay(function(){i.trigger("focus")}),t.preventDefault()))},mousedown:function(t){this._moveToTop(t)&&this._focusTabbable()}}),this.element.find("[aria-describedby]").length||this.uiDialog.attr({"aria-describedby":this.element.uniqueId().attr("id")})},_createTitlebar:function(){var t;this.uiDialogTitlebar=V("
"),this._addClass(this.uiDialogTitlebar,"ui-dialog-titlebar","ui-widget-header ui-helper-clearfix"),this._on(this.uiDialogTitlebar,{mousedown:function(t){V(t.target).closest(".ui-dialog-titlebar-close")||this.uiDialog.trigger("focus")}}),this.uiDialogTitlebarClose=V("").button({label:V("").text(this.options.closeText).html(),icon:"ui-icon-closethick",showLabel:!1}).appendTo(this.uiDialogTitlebar),this._addClass(this.uiDialogTitlebarClose,"ui-dialog-titlebar-close"),this._on(this.uiDialogTitlebarClose,{click:function(t){t.preventDefault(),this.close(t)}}),t=V("").uniqueId().prependTo(this.uiDialogTitlebar),this._addClass(t,"ui-dialog-title"),this._title(t),this.uiDialogTitlebar.prependTo(this.uiDialog),this.uiDialog.attr({"aria-labelledby":t.attr("id")})},_title:function(t){this.options.title?t.text(this.options.title):t.html(" ")},_createButtonPane:function(){this.uiDialogButtonPane=V("
"),this._addClass(this.uiDialogButtonPane,"ui-dialog-buttonpane","ui-widget-content ui-helper-clearfix"),this.uiButtonSet=V("
").appendTo(this.uiDialogButtonPane),this._addClass(this.uiButtonSet,"ui-dialog-buttonset"),this._createButtons()},_createButtons:function(){var s=this,t=this.options.buttons;this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),V.isEmptyObject(t)||Array.isArray(t)&&!t.length?this._removeClass(this.uiDialog,"ui-dialog-buttons"):(V.each(t,function(t,e){var i;e=V.extend({type:"button"},e="function"==typeof e?{click:e,text:t}:e),i=e.click,t={icon:e.icon,iconPosition:e.iconPosition,showLabel:e.showLabel,icons:e.icons,text:e.text},delete e.click,delete e.icon,delete e.iconPosition,delete e.showLabel,delete e.icons,"boolean"==typeof e.text&&delete e.text,V("",e).button(t).appendTo(s.uiButtonSet).on("click",function(){i.apply(s.element[0],arguments)})}),this._addClass(this.uiDialog,"ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog))},_makeDraggable:function(){var n=this,o=this.options;function a(t){return{position:t.position,offset:t.offset}}this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(t,e){n._addClass(V(this),"ui-dialog-dragging"),n._blockFrames(),n._trigger("dragStart",t,a(e))},drag:function(t,e){n._trigger("drag",t,a(e))},stop:function(t,e){var i=e.offset.left-n.document.scrollLeft(),s=e.offset.top-n.document.scrollTop();o.position={my:"left top",at:"left"+(0<=i?"+":"")+i+" top"+(0<=s?"+":"")+s,of:n.window},n._removeClass(V(this),"ui-dialog-dragging"),n._unblockFrames(),n._trigger("dragStop",t,a(e))}})},_makeResizable:function(){var n=this,o=this.options,t=o.resizable,e=this.uiDialog.css("position"),t="string"==typeof t?t:"n,e,s,w,se,sw,ne,nw";function a(t){return{originalPosition:t.originalPosition,originalSize:t.originalSize,position:t.position,size:t.size}}this.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:this.element,maxWidth:o.maxWidth,maxHeight:o.maxHeight,minWidth:o.minWidth,minHeight:this._minHeight(),handles:t,start:function(t,e){n._addClass(V(this),"ui-dialog-resizing"),n._blockFrames(),n._trigger("resizeStart",t,a(e))},resize:function(t,e){n._trigger("resize",t,a(e))},stop:function(t,e){var i=n.uiDialog.offset(),s=i.left-n.document.scrollLeft(),i=i.top-n.document.scrollTop();o.height=n.uiDialog.height(),o.width=n.uiDialog.width(),o.position={my:"left top",at:"left"+(0<=s?"+":"")+s+" top"+(0<=i?"+":"")+i,of:n.window},n._removeClass(V(this),"ui-dialog-resizing"),n._unblockFrames(),n._trigger("resizeStop",t,a(e))}}).css("position",e)},_trackFocus:function(){this._on(this.widget(),{focusin:function(t){this._makeFocusTarget(),this._focusedElement=V(t.target)}})},_makeFocusTarget:function(){this._untrackInstance(),this._trackingInstances().unshift(this)},_untrackInstance:function(){var t=this._trackingInstances(),e=V.inArray(this,t);-1!==e&&t.splice(e,1)},_trackingInstances:function(){var t=this.document.data("ui-dialog-instances");return t||this.document.data("ui-dialog-instances",t=[]),t},_minHeight:function(){var t=this.options;return"auto"===t.height?t.minHeight:Math.min(t.minHeight,t.height)},_position:function(){var t=this.uiDialog.is(":visible");t||this.uiDialog.show(),this.uiDialog.position(this.options.position),t||this.uiDialog.hide()},_setOptions:function(t){var i=this,s=!1,n={};V.each(t,function(t,e){i._setOption(t,e),t in i.sizeRelatedOptions&&(s=!0),t in i.resizableRelatedOptions&&(n[t]=e)}),s&&(this._size(),this._position()),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option",n)},_setOption:function(t,e){var i,s=this.uiDialog;"disabled"!==t&&(this._super(t,e),"appendTo"===t&&this.uiDialog.appendTo(this._appendTo()),"buttons"===t&&this._createButtons(),"closeText"===t&&this.uiDialogTitlebarClose.button({label:V("").text(""+this.options.closeText).html()}),"draggable"===t&&((i=s.is(":data(ui-draggable)"))&&!e&&s.draggable("destroy"),!i&&e&&this._makeDraggable()),"position"===t&&this._position(),"resizable"===t&&((i=s.is(":data(ui-resizable)"))&&!e&&s.resizable("destroy"),i&&"string"==typeof e&&s.resizable("option","handles",e),i||!1===e||this._makeResizable()),"title"===t&&this._title(this.uiDialogTitlebar.find(".ui-dialog-title")))},_size:function(){var t,e,i,s=this.options;this.element.show().css({width:"auto",minHeight:0,maxHeight:"none",height:0}),s.minWidth>s.width&&(s.width=s.minWidth),t=this.uiDialog.css({height:"auto",width:s.width}).outerHeight(),e=Math.max(0,s.minHeight-t),i="number"==typeof s.maxHeight?Math.max(0,s.maxHeight-t):"none","auto"===s.height?this.element.css({minHeight:e,maxHeight:i,height:"auto"}):this.element.height(Math.max(0,s.height-t)),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())},_blockFrames:function(){this.iframeBlocks=this.document.find("iframe").map(function(){var t=V(this);return V("
").css({position:"absolute",width:t.outerWidth(),height:t.outerHeight()}).appendTo(t.parent()).offset(t.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_allowInteraction:function(t){return!!V(t.target).closest(".ui-dialog").length||!!V(t.target).closest(".ui-datepicker").length},_createOverlay:function(){var i,s;this.options.modal&&(i=V.fn.jquery.substring(0,4),s=!0,this._delay(function(){s=!1}),this.document.data("ui-dialog-overlays")||this.document.on("focusin.ui-dialog",function(t){var e;s||((e=this._trackingInstances()[0])._allowInteraction(t)||(t.preventDefault(),e._focusTabbable(),"3.4."!==i&&"3.5."!==i||e._delay(e._restoreTabbableFocus)))}.bind(this)),this.overlay=V("
").appendTo(this._appendTo()),this._addClass(this.overlay,null,"ui-widget-overlay ui-front"),this._on(this.overlay,{mousedown:"_keepFocus"}),this.document.data("ui-dialog-overlays",(this.document.data("ui-dialog-overlays")||0)+1))},_destroyOverlay:function(){var t;this.options.modal&&this.overlay&&((t=this.document.data("ui-dialog-overlays")-1)?this.document.data("ui-dialog-overlays",t):(this.document.off("focusin.ui-dialog"),this.document.removeData("ui-dialog-overlays")),this.overlay.remove(),this.overlay=null)}}),!1!==V.uiBackCompat&&V.widget("ui.dialog",V.ui.dialog,{options:{dialogClass:""},_createWrapper:function(){this._super(),this.uiDialog.addClass(this.options.dialogClass)},_setOption:function(t,e){"dialogClass"===t&&this.uiDialog.removeClass(this.options.dialogClass).addClass(e),this._superApply(arguments)}});V.ui.dialog;function lt(t,e,i){return e<=t&&t").appendTo(this.element),this._addClass(this.valueDiv,"ui-progressbar-value","ui-widget-header"),this._refreshValue()},_destroy:function(){this.element.removeAttr("role aria-valuemin aria-valuemax aria-valuenow"),this.valueDiv.remove()},value:function(t){if(void 0===t)return this.options.value;this.options.value=this._constrainedValue(t),this._refreshValue()},_constrainedValue:function(t){return void 0===t&&(t=this.options.value),this.indeterminate=!1===t,"number"!=typeof t&&(t=0),!this.indeterminate&&Math.min(this.options.max,Math.max(this.min,t))},_setOptions:function(t){var e=t.value;delete t.value,this._super(t),this.options.value=this._constrainedValue(e),this._refreshValue()},_setOption:function(t,e){"max"===t&&(e=Math.max(this.min,e)),this._super(t,e)},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",t),this._toggleClass(null,"ui-state-disabled",!!t)},_percentage:function(){return this.indeterminate?100:100*(this.options.value-this.min)/(this.options.max-this.min)},_refreshValue:function(){var t=this.options.value,e=this._percentage();this.valueDiv.toggle(this.indeterminate||t>this.min).width(e.toFixed(0)+"%"),this._toggleClass(this.valueDiv,"ui-progressbar-complete",null,t===this.options.max)._toggleClass("ui-progressbar-indeterminate",null,this.indeterminate),this.indeterminate?(this.element.removeAttr("aria-valuenow"),this.overlayDiv||(this.overlayDiv=V("
").appendTo(this.valueDiv),this._addClass(this.overlayDiv,"ui-progressbar-overlay"))):(this.element.attr({"aria-valuemax":this.options.max,"aria-valuenow":t}),this.overlayDiv&&(this.overlayDiv.remove(),this.overlayDiv=null)),this.oldValue!==t&&(this.oldValue=t,this._trigger("change")),t===this.options.max&&this._trigger("complete")}}),V.widget("ui.selectable",V.ui.mouse,{version:"1.13.2",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch",selected:null,selecting:null,start:null,stop:null,unselected:null,unselecting:null},_create:function(){var i=this;this._addClass("ui-selectable"),this.dragged=!1,this.refresh=function(){i.elementPos=V(i.element[0]).offset(),i.selectees=V(i.options.filter,i.element[0]),i._addClass(i.selectees,"ui-selectee"),i.selectees.each(function(){var t=V(this),e=t.offset(),e={left:e.left-i.elementPos.left,top:e.top-i.elementPos.top};V.data(this,"selectable-item",{element:this,$element:t,left:e.left,top:e.top,right:e.left+t.outerWidth(),bottom:e.top+t.outerHeight(),startselected:!1,selected:t.hasClass("ui-selected"),selecting:t.hasClass("ui-selecting"),unselecting:t.hasClass("ui-unselecting")})})},this.refresh(),this._mouseInit(),this.helper=V("
"),this._addClass(this.helper,"ui-selectable-helper")},_destroy:function(){this.selectees.removeData("selectable-item"),this._mouseDestroy()},_mouseStart:function(i){var s=this,t=this.options;this.opos=[i.pageX,i.pageY],this.elementPos=V(this.element[0]).offset(),this.options.disabled||(this.selectees=V(t.filter,this.element[0]),this._trigger("start",i),V(t.appendTo).append(this.helper),this.helper.css({left:i.pageX,top:i.pageY,width:0,height:0}),t.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var t=V.data(this,"selectable-item");t.startselected=!0,i.metaKey||i.ctrlKey||(s._removeClass(t.$element,"ui-selected"),t.selected=!1,s._addClass(t.$element,"ui-unselecting"),t.unselecting=!0,s._trigger("unselecting",i,{unselecting:t.element}))}),V(i.target).parents().addBack().each(function(){var t,e=V.data(this,"selectable-item");if(e)return t=!i.metaKey&&!i.ctrlKey||!e.$element.hasClass("ui-selected"),s._removeClass(e.$element,t?"ui-unselecting":"ui-selected")._addClass(e.$element,t?"ui-selecting":"ui-unselecting"),e.unselecting=!t,e.selecting=t,(e.selected=t)?s._trigger("selecting",i,{selecting:e.element}):s._trigger("unselecting",i,{unselecting:e.element}),!1}))},_mouseDrag:function(s){if(this.dragged=!0,!this.options.disabled){var t,n=this,o=this.options,a=this.opos[0],r=this.opos[1],l=s.pageX,h=s.pageY;return ll||i.righth||i.bottoma&&i.rightr&&i.bottom",options:{appendTo:null,classes:{"ui-selectmenu-button-open":"ui-corner-top","ui-selectmenu-button-closed":"ui-corner-all"},disabled:null,icons:{button:"ui-icon-triangle-1-s"},position:{my:"left top",at:"left bottom",collision:"none"},width:!1,change:null,close:null,focus:null,open:null,select:null},_create:function(){var t=this.element.uniqueId().attr("id");this.ids={element:t,button:t+"-button",menu:t+"-menu"},this._drawButton(),this._drawMenu(),this._bindFormResetHandler(),this._rendered=!1,this.menuItems=V()},_drawButton:function(){var t,e=this,i=this._parseOption(this.element.find("option:selected"),this.element[0].selectedIndex);this.labels=this.element.labels().attr("for",this.ids.button),this._on(this.labels,{click:function(t){this.button.trigger("focus"),t.preventDefault()}}),this.element.hide(),this.button=V("",{tabindex:this.options.disabled?-1:0,id:this.ids.button,role:"combobox","aria-expanded":"false","aria-autocomplete":"list","aria-owns":this.ids.menu,"aria-haspopup":"true",title:this.element.attr("title")}).insertAfter(this.element),this._addClass(this.button,"ui-selectmenu-button ui-selectmenu-button-closed","ui-button ui-widget"),t=V("").appendTo(this.button),this._addClass(t,"ui-selectmenu-icon","ui-icon "+this.options.icons.button),this.buttonItem=this._renderButtonItem(i).appendTo(this.button),!1!==this.options.width&&this._resizeButton(),this._on(this.button,this._buttonEvents),this.button.one("focusin",function(){e._rendered||e._refreshMenu()})},_drawMenu:function(){var i=this;this.menu=V("
    ",{"aria-hidden":"true","aria-labelledby":this.ids.button,id:this.ids.menu}),this.menuWrap=V("
    ").append(this.menu),this._addClass(this.menuWrap,"ui-selectmenu-menu","ui-front"),this.menuWrap.appendTo(this._appendTo()),this.menuInstance=this.menu.menu({classes:{"ui-menu":"ui-corner-bottom"},role:"listbox",select:function(t,e){t.preventDefault(),i._setSelection(),i._select(e.item.data("ui-selectmenu-item"),t)},focus:function(t,e){e=e.item.data("ui-selectmenu-item");null!=i.focusIndex&&e.index!==i.focusIndex&&(i._trigger("focus",t,{item:e}),i.isOpen||i._select(e,t)),i.focusIndex=e.index,i.button.attr("aria-activedescendant",i.menuItems.eq(e.index).attr("id"))}}).menu("instance"),this.menuInstance._off(this.menu,"mouseleave"),this.menuInstance._closeOnDocumentClick=function(){return!1},this.menuInstance._isDivider=function(){return!1}},refresh:function(){this._refreshMenu(),this.buttonItem.replaceWith(this.buttonItem=this._renderButtonItem(this._getSelectedItem().data("ui-selectmenu-item")||{})),null===this.options.width&&this._resizeButton()},_refreshMenu:function(){var t=this.element.find("option");this.menu.empty(),this._parseOptions(t),this._renderMenu(this.menu,this.items),this.menuInstance.refresh(),this.menuItems=this.menu.find("li").not(".ui-selectmenu-optgroup").find(".ui-menu-item-wrapper"),this._rendered=!0,t.length&&(t=this._getSelectedItem(),this.menuInstance.focus(null,t),this._setAria(t.data("ui-selectmenu-item")),this._setOption("disabled",this.element.prop("disabled")))},open:function(t){this.options.disabled||(this._rendered?(this._removeClass(this.menu.find(".ui-state-active"),null,"ui-state-active"),this.menuInstance.focus(null,this._getSelectedItem())):this._refreshMenu(),this.menuItems.length&&(this.isOpen=!0,this._toggleAttr(),this._resizeMenu(),this._position(),this._on(this.document,this._documentClick),this._trigger("open",t)))},_position:function(){this.menuWrap.position(V.extend({of:this.button},this.options.position))},close:function(t){this.isOpen&&(this.isOpen=!1,this._toggleAttr(),this.range=null,this._off(this.document),this._trigger("close",t))},widget:function(){return this.button},menuWidget:function(){return this.menu},_renderButtonItem:function(t){var e=V("");return this._setText(e,t.label),this._addClass(e,"ui-selectmenu-text"),e},_renderMenu:function(s,t){var n=this,o="";V.each(t,function(t,e){var i;e.optgroup!==o&&(i=V("
  • ",{text:e.optgroup}),n._addClass(i,"ui-selectmenu-optgroup","ui-menu-divider"+(e.element.parent("optgroup").prop("disabled")?" ui-state-disabled":"")),i.appendTo(s),o=e.optgroup),n._renderItemData(s,e)})},_renderItemData:function(t,e){return this._renderItem(t,e).data("ui-selectmenu-item",e)},_renderItem:function(t,e){var i=V("
  • "),s=V("
    ",{title:e.element.attr("title")});return e.disabled&&this._addClass(i,null,"ui-state-disabled"),this._setText(s,e.label),i.append(s).appendTo(t)},_setText:function(t,e){e?t.text(e):t.html(" ")},_move:function(t,e){var i,s=".ui-menu-item";this.isOpen?i=this.menuItems.eq(this.focusIndex).parent("li"):(i=this.menuItems.eq(this.element[0].selectedIndex).parent("li"),s+=":not(.ui-state-disabled)"),(s="first"===t||"last"===t?i["first"===t?"prevAll":"nextAll"](s).eq(-1):i[t+"All"](s).eq(0)).length&&this.menuInstance.focus(e,s)},_getSelectedItem:function(){return this.menuItems.eq(this.element[0].selectedIndex).parent("li")},_toggle:function(t){this[this.isOpen?"close":"open"](t)},_setSelection:function(){var t;this.range&&(window.getSelection?((t=window.getSelection()).removeAllRanges(),t.addRange(this.range)):this.range.select(),this.button.trigger("focus"))},_documentClick:{mousedown:function(t){this.isOpen&&(V(t.target).closest(".ui-selectmenu-menu, #"+V.escapeSelector(this.ids.button)).length||this.close(t))}},_buttonEvents:{mousedown:function(){var t;window.getSelection?(t=window.getSelection()).rangeCount&&(this.range=t.getRangeAt(0)):this.range=document.selection.createRange()},click:function(t){this._setSelection(),this._toggle(t)},keydown:function(t){var e=!0;switch(t.keyCode){case V.ui.keyCode.TAB:case V.ui.keyCode.ESCAPE:this.close(t),e=!1;break;case V.ui.keyCode.ENTER:this.isOpen&&this._selectFocusedItem(t);break;case V.ui.keyCode.UP:t.altKey?this._toggle(t):this._move("prev",t);break;case V.ui.keyCode.DOWN:t.altKey?this._toggle(t):this._move("next",t);break;case V.ui.keyCode.SPACE:this.isOpen?this._selectFocusedItem(t):this._toggle(t);break;case V.ui.keyCode.LEFT:this._move("prev",t);break;case V.ui.keyCode.RIGHT:this._move("next",t);break;case V.ui.keyCode.HOME:case V.ui.keyCode.PAGE_UP:this._move("first",t);break;case V.ui.keyCode.END:case V.ui.keyCode.PAGE_DOWN:this._move("last",t);break;default:this.menu.trigger(t),e=!1}e&&t.preventDefault()}},_selectFocusedItem:function(t){var e=this.menuItems.eq(this.focusIndex).parent("li");e.hasClass("ui-state-disabled")||this._select(e.data("ui-selectmenu-item"),t)},_select:function(t,e){var i=this.element[0].selectedIndex;this.element[0].selectedIndex=t.index,this.buttonItem.replaceWith(this.buttonItem=this._renderButtonItem(t)),this._setAria(t),this._trigger("select",e,{item:t}),t.index!==i&&this._trigger("change",e,{item:t}),this.close(e)},_setAria:function(t){t=this.menuItems.eq(t.index).attr("id");this.button.attr({"aria-labelledby":t,"aria-activedescendant":t}),this.menu.attr("aria-activedescendant",t)},_setOption:function(t,e){var i;"icons"===t&&(i=this.button.find("span.ui-icon"),this._removeClass(i,null,this.options.icons.button)._addClass(i,null,e.button)),this._super(t,e),"appendTo"===t&&this.menuWrap.appendTo(this._appendTo()),"width"===t&&this._resizeButton()},_setOptionDisabled:function(t){this._super(t),this.menuInstance.option("disabled",t),this.button.attr("aria-disabled",t),this._toggleClass(this.button,null,"ui-state-disabled",t),this.element.prop("disabled",t),t?(this.button.attr("tabindex",-1),this.close()):this.button.attr("tabindex",0)},_appendTo:function(){var t=this.options.appendTo;return t=!(t=!(t=t&&(t.jquery||t.nodeType?V(t):this.document.find(t).eq(0)))||!t[0]?this.element.closest(".ui-front, dialog"):t).length?this.document[0].body:t},_toggleAttr:function(){this.button.attr("aria-expanded",this.isOpen),this._removeClass(this.button,"ui-selectmenu-button-"+(this.isOpen?"closed":"open"))._addClass(this.button,"ui-selectmenu-button-"+(this.isOpen?"open":"closed"))._toggleClass(this.menuWrap,"ui-selectmenu-open",null,this.isOpen),this.menu.attr("aria-hidden",!this.isOpen)},_resizeButton:function(){var t=this.options.width;!1!==t?(null===t&&(t=this.element.show().outerWidth(),this.element.hide()),this.button.outerWidth(t)):this.button.css("width","")},_resizeMenu:function(){this.menu.outerWidth(Math.max(this.button.outerWidth(),this.menu.width("").outerWidth()+1))},_getCreateOptions:function(){var t=this._super();return t.disabled=this.element.prop("disabled"),t},_parseOptions:function(t){var i=this,s=[];t.each(function(t,e){e.hidden||s.push(i._parseOption(V(e),t))}),this.items=s},_parseOption:function(t,e){var i=t.parent("optgroup");return{element:t,index:e,value:t.val(),label:t.text(),optgroup:i.attr("label")||"",disabled:i.prop("disabled")||t.prop("disabled")}},_destroy:function(){this._unbindFormResetHandler(),this.menuWrap.remove(),this.button.remove(),this.element.show(),this.element.removeUniqueId(),this.labels.attr("for",this.ids.element)}}]),V.widget("ui.slider",V.ui.mouse,{version:"1.13.2",widgetEventPrefix:"slide",options:{animate:!1,classes:{"ui-slider":"ui-corner-all","ui-slider-handle":"ui-corner-all","ui-slider-range":"ui-corner-all ui-widget-header"},distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null,change:null,slide:null,start:null,stop:null},numPages:5,_create:function(){this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this._calculateNewMax(),this._addClass("ui-slider ui-slider-"+this.orientation,"ui-widget ui-widget-content"),this._refresh(),this._animateOff=!1},_refresh:function(){this._createRange(),this._createHandles(),this._setupEvents(),this._refreshValue()},_createHandles:function(){var t,e=this.options,i=this.element.find(".ui-slider-handle"),s=[],n=e.values&&e.values.length||1;for(i.length>n&&(i.slice(n).remove(),i=i.slice(0,n)),t=i.length;t");this.handles=i.add(V(s.join("")).appendTo(this.element)),this._addClass(this.handles,"ui-slider-handle","ui-state-default"),this.handle=this.handles.eq(0),this.handles.each(function(t){V(this).data("ui-slider-handle-index",t).attr("tabIndex",0)})},_createRange:function(){var t=this.options;t.range?(!0===t.range&&(t.values?t.values.length&&2!==t.values.length?t.values=[t.values[0],t.values[0]]:Array.isArray(t.values)&&(t.values=t.values.slice(0)):t.values=[this._valueMin(),this._valueMin()]),this.range&&this.range.length?(this._removeClass(this.range,"ui-slider-range-min ui-slider-range-max"),this.range.css({left:"",bottom:""})):(this.range=V("
    ").appendTo(this.element),this._addClass(this.range,"ui-slider-range")),"min"!==t.range&&"max"!==t.range||this._addClass(this.range,"ui-slider-range-"+t.range)):(this.range&&this.range.remove(),this.range=null)},_setupEvents:function(){this._off(this.handles),this._on(this.handles,this._handleEvents),this._hoverable(this.handles),this._focusable(this.handles)},_destroy:function(){this.handles.remove(),this.range&&this.range.remove(),this._mouseDestroy()},_mouseCapture:function(t){var i,s,n,o,e,a,r=this,l=this.options;return!l.disabled&&(this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()},this.elementOffset=this.element.offset(),a={x:t.pageX,y:t.pageY},i=this._normValueFromMouse(a),s=this._valueMax()-this._valueMin()+1,this.handles.each(function(t){var e=Math.abs(i-r.values(t));(e=this._valueMax())return this._valueMax();var e=0=e&&(t+=0this.options.max&&(t-=i),this.max=parseFloat(t.toFixed(this._precision()))},_precision:function(){var t=this._precisionOf(this.options.step);return t=null!==this.options.min?Math.max(t,this._precisionOf(this.options.min)):t},_precisionOf:function(t){var e=t.toString(),t=e.indexOf(".");return-1===t?0:e.length-t-1},_valueMin:function(){return this.options.min},_valueMax:function(){return this.max},_refreshRange:function(t){"vertical"===t&&this.range.css({width:"",left:""}),"horizontal"===t&&this.range.css({height:"",bottom:""})},_refreshValue:function(){var e,i,t,s,n,o=this.options.range,a=this.options,r=this,l=!this._animateOff&&a.animate,h={};this._hasMultipleValues()?this.handles.each(function(t){i=(r.values(t)-r._valueMin())/(r._valueMax()-r._valueMin())*100,h["horizontal"===r.orientation?"left":"bottom"]=i+"%",V(this).stop(1,1)[l?"animate":"css"](h,a.animate),!0===r.options.range&&("horizontal"===r.orientation?(0===t&&r.range.stop(1,1)[l?"animate":"css"]({left:i+"%"},a.animate),1===t&&r.range[l?"animate":"css"]({width:i-e+"%"},{queue:!1,duration:a.animate})):(0===t&&r.range.stop(1,1)[l?"animate":"css"]({bottom:i+"%"},a.animate),1===t&&r.range[l?"animate":"css"]({height:i-e+"%"},{queue:!1,duration:a.animate}))),e=i}):(t=this.value(),s=this._valueMin(),n=this._valueMax(),i=n!==s?(t-s)/(n-s)*100:0,h["horizontal"===this.orientation?"left":"bottom"]=i+"%",this.handle.stop(1,1)[l?"animate":"css"](h,a.animate),"min"===o&&"horizontal"===this.orientation&&this.range.stop(1,1)[l?"animate":"css"]({width:i+"%"},a.animate),"max"===o&&"horizontal"===this.orientation&&this.range.stop(1,1)[l?"animate":"css"]({width:100-i+"%"},a.animate),"min"===o&&"vertical"===this.orientation&&this.range.stop(1,1)[l?"animate":"css"]({height:i+"%"},a.animate),"max"===o&&"vertical"===this.orientation&&this.range.stop(1,1)[l?"animate":"css"]({height:100-i+"%"},a.animate))},_handleEvents:{keydown:function(t){var e,i,s,n=V(t.target).data("ui-slider-handle-index");switch(t.keyCode){case V.ui.keyCode.HOME:case V.ui.keyCode.END:case V.ui.keyCode.PAGE_UP:case V.ui.keyCode.PAGE_DOWN:case V.ui.keyCode.UP:case V.ui.keyCode.RIGHT:case V.ui.keyCode.DOWN:case V.ui.keyCode.LEFT:if(t.preventDefault(),!this._keySliding&&(this._keySliding=!0,this._addClass(V(t.target),null,"ui-state-active"),!1===this._start(t,n)))return}switch(s=this.options.step,e=i=this._hasMultipleValues()?this.values(n):this.value(),t.keyCode){case V.ui.keyCode.HOME:i=this._valueMin();break;case V.ui.keyCode.END:i=this._valueMax();break;case V.ui.keyCode.PAGE_UP:i=this._trimAlignValue(e+(this._valueMax()-this._valueMin())/this.numPages);break;case V.ui.keyCode.PAGE_DOWN:i=this._trimAlignValue(e-(this._valueMax()-this._valueMin())/this.numPages);break;case V.ui.keyCode.UP:case V.ui.keyCode.RIGHT:if(e===this._valueMax())return;i=this._trimAlignValue(e+s);break;case V.ui.keyCode.DOWN:case V.ui.keyCode.LEFT:if(e===this._valueMin())return;i=this._trimAlignValue(e-s)}this._slide(t,n,i)},keyup:function(t){var e=V(t.target).data("ui-slider-handle-index");this._keySliding&&(this._keySliding=!1,this._stop(t,e),this._change(t,e),this._removeClass(V(t.target),null,"ui-state-active"))}}}),V.widget("ui.sortable",V.ui.mouse,{version:"1.13.2",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3,activate:null,beforeStop:null,change:null,deactivate:null,out:null,over:null,receive:null,remove:null,sort:null,start:null,stop:null,update:null},_isOverAxis:function(t,e,i){return e<=t&&t*{ cursor: "+o.cursor+" !important; }").appendTo(n)),o.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",o.zIndex)),o.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",o.opacity)),this.scrollParent[0]!==this.document[0]&&"HTML"!==this.scrollParent[0].tagName&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",t,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions(),!i)for(s=this.containers.length-1;0<=s;s--)this.containers[s]._trigger("activate",t,this._uiHash(this));return V.ui.ddmanager&&(V.ui.ddmanager.current=this),V.ui.ddmanager&&!o.dropBehaviour&&V.ui.ddmanager.prepareOffsets(this,t),this.dragging=!0,this._addClass(this.helper,"ui-sortable-helper"),this.helper.parent().is(this.appendTo)||(this.helper.detach().appendTo(this.appendTo),this.offset.parent=this._getParentOffset()),this.position=this.originalPosition=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,this.lastPositionAbs=this.positionAbs=this._convertPositionTo("absolute"),this._mouseDrag(t),!0},_scroll:function(t){var e=this.options,i=!1;return this.scrollParent[0]!==this.document[0]&&"HTML"!==this.scrollParent[0].tagName?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-t.pageYt[this.floating?"width":"height"]?h&&c:o",i.document[0]);return i._addClass(t,"ui-sortable-placeholder",s||i.currentItem[0].className)._removeClass(t,"ui-sortable-helper"),"tbody"===n?i._createTrPlaceholder(i.currentItem.find("tr").eq(0),V("
 
'; if (!empty($conf->accounting->enabled)) { print $formaccounting->select_account($object->account_number, 'account_number', 1, '', 1, 1); From 6858b47542cb13c15ef8557e9e6a6b1d76e03e98 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 10 Aug 2022 18:47:33 +0200 Subject: [PATCH 500/826] FIX #yogosha12006 --- htdocs/core/filemanagerdol/browser/default/browser.php | 2 ++ htdocs/core/filemanagerdol/browser/default/frmactualfolder.php | 2 ++ htdocs/core/filemanagerdol/browser/default/frmcreatefolder.php | 2 ++ htdocs/core/filemanagerdol/browser/default/frmfolders.php | 2 ++ htdocs/core/filemanagerdol/browser/default/frmresourceslist.php | 2 ++ htdocs/core/filemanagerdol/browser/default/frmupload.php | 2 ++ 6 files changed, 12 insertions(+) diff --git a/htdocs/core/filemanagerdol/browser/default/browser.php b/htdocs/core/filemanagerdol/browser/default/browser.php index b5bce100d39..e296a9ac5b2 100644 --- a/htdocs/core/filemanagerdol/browser/default/browser.php +++ b/htdocs/core/filemanagerdol/browser/default/browser.php @@ -25,6 +25,8 @@ require '../../connectors/php/config.php'; // This include the define('NOTOKENRE global $Config; +top_httphead(); + ?> diff --git a/htdocs/core/filemanagerdol/browser/default/frmactualfolder.php b/htdocs/core/filemanagerdol/browser/default/frmactualfolder.php index c66187ee433..949307c0624 100644 --- a/htdocs/core/filemanagerdol/browser/default/frmactualfolder.php +++ b/htdocs/core/filemanagerdol/browser/default/frmactualfolder.php @@ -23,6 +23,8 @@ define('NOTOKENRENEWAL', 1); // Disables token renewal require '../../../../main.inc.php'; +top_httphead(); + ?> "; diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 61b0c4b6302..0c53be74ef7 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -3785,7 +3785,7 @@ if ($action == 'create') { // Calcul contrat->price (HT), contrat->total (TTC), contrat->tva $objectsrc->remise_absolue = $remise_absolue; $objectsrc->remise_percent = $remise_percent; - $objectsrc->update_price(1, - 1, 1); + $objectsrc->update_price(1, 'auto', 1); } print "\n\n"; diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index aead087a9bc..a18341cc179 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -3512,7 +3512,7 @@ abstract class CommonObject * * @param int $exclspec >0 = Exclude special product (product_type=9) * @param string $roundingadjust 'none'=Do nothing, 'auto'=Use default method (MAIN_ROUNDOFTOTAL_NOT_TOTALOFROUND if defined, or '0'), '0'=Force mode Total of rounding, '1'=Force mode Rounding of total - * @param int $nodatabaseupdate 1=Do not update database. Update only properties of object. + * @param int $nodatabaseupdate 1=Do not update database total fields of the main object. Update only properties in memory. Can be used to save SQL when this method is called several times, so we can do it only once at end. * @param Societe $seller If roundingadjust is '0' or '1' or maybe 'auto', it means we recalculate total for lines before calculating total for object and for this, we need seller object (used to analyze lines to check corrupted data). * @return int <0 if KO, >0 if OK */ @@ -3558,10 +3558,6 @@ abstract class CommonObject include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php'; - if ($roundingadjust == '-1') { - $roundingadjust = 'auto'; // For backward compatibility - } - $forcedroundingmode = $roundingadjust; if ($forcedroundingmode == 'auto' && isset($conf->global->MAIN_ROUNDOFTOTAL_NOT_TOTALOFROUND)) { $forcedroundingmode = $conf->global->MAIN_ROUNDOFTOTAL_NOT_TOTALOFROUND; @@ -3573,7 +3569,7 @@ abstract class CommonObject $multicurrency_tx = !empty($this->multicurrency_tx) ? $this->multicurrency_tx : 1; - // Define constants to find lines to sum + // Define constants to find lines to sum (field name int the table_element_line not into table_element) $fieldtva = 'total_tva'; $fieldlocaltax1 = 'total_localtax1'; $fieldlocaltax2 = 'total_localtax2'; @@ -3609,6 +3605,7 @@ abstract class CommonObject $sql .= ' ORDER by rowid'; // We want to be sure to always use same order of line to not change lines differently when option MAIN_ROUNDOFTOTAL_NOT_TOTALOFROUND is used dol_syslog(get_class($this)."::update_price", LOG_DEBUG); + $resql = $this->db->query($sql); if ($resql) { $this->total_ht = 0; @@ -3637,14 +3634,26 @@ abstract class CommonObject $localtax_array = array($obj->localtax1_type, $obj->localtax1_tx, $obj->localtax2_type, $obj->localtax2_tx); $tmpcal = calcul_price_total($obj->qty, $obj->up, $obj->remise_percent, $obj->vatrate, $obj->localtax1_tx, $obj->localtax2_tx, 0, 'HT', $obj->info_bits, $obj->product_type, $seller, $localtax_array, (isset($obj->situation_percent) ? $obj->situation_percent : 100), $multicurrency_tx); - $diff_when_using_price_ht = price2num($tmpcal[1] - $obj->total_tva, 'MT', 1); // If price was set with tax price adn unit price HT has a low number of digits, then we may have a diff on recalculation from unit price HT. + $diff_when_using_price_ht = price2num($tmpcal[1] - $obj->total_tva, 'MT', 1); // If price was set with tax price and unit price HT has a low number of digits, then we may have a diff on recalculation from unit price HT. $diff_on_current_total = price2num($obj->total_ttc - $obj->total_ht - $obj->total_tva - $obj->total_localtax1 - $obj->total_localtax2, 'MT', 1); - //var_dump($obj->total_ht.' '.$obj->total_tva.' '.$obj->total_localtax1.' '.$obj->total_localtax2.' =? '.$obj->total_ttc); + //var_dump($obj->total_ht.' '.$obj->total_tva.' '.$obj->total_localtax1.' '.$obj->total_localtax2.' => '.$obj->total_ttc); //var_dump($diff_when_using_price_ht.' '.$diff_on_current_total); - if ($diff_when_using_price_ht && $diff_on_current_total) { + if ($diff_on_current_total) { + // This should not happen, we should always have in table: total_ttc = total_ht + total_vat + total_localtax1 + total_localtax2 $sqlfix = "UPDATE ".$this->db->prefix().$this->table_element_line." SET ".$fieldtva." = ".price2num((float) $tmpcal[1]).", total_ttc = ".price2num((float) $tmpcal[2])." WHERE rowid = ".((int) $obj->rowid); - dol_syslog('We found unconsistent data into detailed line (diff_when_using_price_ht = '.$diff_when_using_price_ht.' and diff_on_current_total = '.$diff_on_current_total.') for line rowid = '.$obj->rowid." (total vat of line calculated=".$tmpcal[1].", database=".$obj->total_tva."). We fix the total_vat and total_ttc of line by running sqlfix = ".$sqlfix, LOG_WARNING); + dol_syslog('We found unconsistent data into detailed line (diff_on_current_total = '.$diff_on_current_total.') for line rowid = '.$obj->rowid." (ht=".$obj->total_ht." vat=".$obj->total_tva." tax1=".$obj->total_localtax1." tax2=".$obj->total_localtax2." ttc=".$obj->total_ttc."). We fix the total_vat and total_ttc of line by running sqlfix = ".$sqlfix, LOG_WARNING); + $resqlfix = $this->db->query($sqlfix); + if (!$resqlfix) { + dol_print_error($this->db, 'Failed to update line'); + } + $obj->total_tva = $tmpcal[1]; + $obj->total_ttc = $tmpcal[2]; + } elseif ($diff_when_using_price_ht && $roundingadjust == '0') { + // After calculation from HT, total is consistent but we have found a difference between VAT part in calculation and into database and + // we ask to force the use of rounding on line (like done on calculation) so we force update of line + $sqlfix = "UPDATE ".$this->db->prefix().$this->table_element_line." SET ".$fieldtva." = ".price2num((float) $tmpcal[1]).", total_ttc = ".price2num((float) $tmpcal[2])." WHERE rowid = ".((int) $obj->rowid); + dol_syslog('We found a line with different rounding data into detailed line (diff_when_using_price_ht = '.$diff_when_using_price_ht.' and diff_on_current_total = '.$diff_on_current_total.') for line rowid = '.$obj->rowid." (total vat of line calculated=".$tmpcal[1].", database=".$obj->total_tva."). We fix the total_vat and total_ttc of line by running sqlfix = ".$sqlfix); $resqlfix = $this->db->query($sqlfix); if (!$resqlfix) { dol_print_error($this->db, 'Failed to update line'); @@ -3725,7 +3734,7 @@ abstract class CommonObject $this->db->free($resql); - // Now update global field total_ht, total_ttc, total_tva, total_localtax1, total_localtax2, multicurrency_total_* + // Now update global fields total_ht, total_ttc, total_tva, total_localtax1, total_localtax2, multicurrency_total_* of main object $fieldht = 'total_ht'; $fieldtva = 'tva'; $fieldlocaltax1 = 'localtax1'; diff --git a/htdocs/supplier_proposal/card.php b/htdocs/supplier_proposal/card.php index 6253d9b86b2..3ef3e2bd737 100644 --- a/htdocs/supplier_proposal/card.php +++ b/htdocs/supplier_proposal/card.php @@ -1358,7 +1358,7 @@ if ($action == 'create') { // Calcul contrat->price (HT), contrat->total (TTC), contrat->tva $objectsrc->remise_absolue = $remise_absolue; $objectsrc->remise_percent = $remise_percent; - $objectsrc->update_price(1, - 1, 1); + $objectsrc->update_price(1, 'auto', 1); } print "\n"; From a6c6f2d50bbad766b4ba1029f9d755a1603efabc Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 11 Aug 2022 20:49:18 +0200 Subject: [PATCH 532/826] Fix avoid error message when pressing enter into bank reconciliation --- htdocs/compta/bank/bankentries_list.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/htdocs/compta/bank/bankentries_list.php b/htdocs/compta/bank/bankentries_list.php index 511d75a12c8..f24afc0700b 100644 --- a/htdocs/compta/bank/bankentries_list.php +++ b/htdocs/compta/bank/bankentries_list.php @@ -235,8 +235,12 @@ if (empty($reshook)) { include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; } +$rowids = GETPOST('rowid', 'array'); + // Conciliation -if ((GETPOST('confirm_savestatement', 'alpha') || GETPOST('confirm_reconcile', 'alpha')) && !empty($user->rights->banque->consolidate) +if ((GETPOST('confirm_savestatement', 'alpha') || GETPOST('confirm_reconcile', 'alpha')) + && (GETPOST("num_releve", "alpha") || !empty($rowids)) + && !empty($user->rights->banque->consolidate) && (!GETPOSTISSET('pageplusone') || (GETPOST('pageplusone') == GETPOST('pageplusoneold')))) { $error = 0; From c3d5d990444e68599a2a6293fe6b27f2a3b85fc6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 11 Aug 2022 23:28:13 +0200 Subject: [PATCH 533/826] Fix lang --- htdocs/langs/en_US/website.lang | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/langs/en_US/website.lang b/htdocs/langs/en_US/website.lang index 59a23e65d9b..3d5a57e91d3 100644 --- a/htdocs/langs/en_US/website.lang +++ b/htdocs/langs/en_US/website.lang @@ -150,3 +150,4 @@ ErrorFaviconSize=Favicon must be sized 16x16, 32x32 or 64x64 FaviconTooltip=Upload an image which needs to be a png (16x16, 32x32 or 64x64) NextContainer=Next page/container PreviousContainer=Previous page/container +WebsiteMustBeDisabled=The website must have the status "Disabled" From 0f3ed254fd10509860c64755fd9d346ed1911fb6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 11 Aug 2022 23:36:13 +0200 Subject: [PATCH 534/826] Add version and date of website template generation in the sql. --- htdocs/website/class/website.class.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index aa405861e6a..811c0e9c7cc 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -1034,7 +1034,10 @@ class Website extends CommonObject $allaliases = $objectpageold->pageurl; $allaliases .= ($objectpageold->aliasalt ? ','.$objectpageold->aliasalt : ''); - $line = '-- Page ID '.$objectpageold->id.' -> '.$objectpageold->newid.'__+MAX_llx_website_page__ - Aliases '.$allaliases.' --;'; // newid start at 1, 2... + $line = '-- File generated by Dolibarr '.DOL_VERSION.' -- '.dol_print_date(dol_now('gmt'), 'standard', 'gmt').' UTC --;'; + $line .= "\n"; + + $line .= '-- Page ID '.$objectpageold->id.' -> '.$objectpageold->newid.'__+MAX_llx_website_page__ - Aliases '.$allaliases.' --;'; // newid start at 1, 2... $line .= "\n"; fputs($fp, $line); From 9bc6c41ca7d5e06ec0222b6b110919a193fb0ac0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 11 Aug 2022 23:59:25 +0200 Subject: [PATCH 535/826] Clean code: No more fetch to clone --- htdocs/adherents/card.php | 2 +- htdocs/adherents/type.php | 3 ++- htdocs/comm/action/card.php | 4 ++-- htdocs/comm/action/index.php | 2 +- htdocs/comm/action/pertype.php | 2 +- htdocs/comm/action/peruser.php | 2 +- htdocs/contact/perso.php | 2 +- htdocs/contrat/class/contrat.class.php | 3 +-- htdocs/core/class/comment.class.php | 6 +++--- htdocs/fichinter/class/fichinter.class.php | 4 ++-- htdocs/product/class/product.class.php | 4 +--- htdocs/product/stock/class/productlot.class.php | 4 +--- htdocs/resource/class/dolresource.class.php | 4 +--- htdocs/user/bank.php | 2 +- 14 files changed, 19 insertions(+), 25 deletions(-) diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php index f7b900feaa4..43747513c96 100644 --- a/htdocs/adherents/card.php +++ b/htdocs/adherents/card.php @@ -278,7 +278,7 @@ if (empty($reshook)) { } // Create new object if ($result > 0 && !$error) { - $object->oldcopy = clone $object; + $object->oldcopy = dol_clone($object); // Change values $object->civility_id = trim(GETPOST("civility_id", 'alphanohtml')); diff --git a/htdocs/adherents/type.php b/htdocs/adherents/type.php index f3d5f96a78a..e37d52480fa 100644 --- a/htdocs/adherents/type.php +++ b/htdocs/adherents/type.php @@ -170,7 +170,8 @@ if ($action == 'add' && $user->rights->adherent->configurer) { if ($action == 'update' && $user->rights->adherent->configurer) { $object->fetch($rowid); - $object->oldcopy = clone $object; + $object->oldcopy = dol_clone($object); + $object->label= trim($label); $object->morphy = trim($morphy); $object->status = (int) $status; diff --git a/htdocs/comm/action/card.php b/htdocs/comm/action/card.php index 6f97b3f134d..6dd6cd5663b 100644 --- a/htdocs/comm/action/card.php +++ b/htdocs/comm/action/card.php @@ -677,7 +677,7 @@ if (empty($reshook) && $action == 'update') { $object->fetch($id); $object->fetch_optionals(); $object->fetch_userassigned(); - $object->oldcopy = clone $object; + $object->oldcopy = dol_clone($object); // Clean parameters if ($fulldayevent) { @@ -927,7 +927,7 @@ if (empty($reshook) && $action == 'confirm_delete' && GETPOST("confirm") == 'yes $object->fetch($id); $object->fetch_optionals(); $object->fetch_userassigned(); - $object->oldcopy = clone $object; + $object->oldcopy = dol_clone($object); if ($user->rights->agenda->myactions->delete || $user->rights->agenda->allactions->delete) { diff --git a/htdocs/comm/action/index.php b/htdocs/comm/action/index.php index 2afad30c454..c60f10be857 100644 --- a/htdocs/comm/action/index.php +++ b/htdocs/comm/action/index.php @@ -212,7 +212,7 @@ if (GETPOST("viewperuser", 'alpha') || $mode == 'show_peruser') { $event->fetch($actionid); $event->fetch_optionals(); $event->fetch_userassigned(); - $event->oldcopy = clone $event; + $event->oldcopy = dol_clone($event); $result = $event->delete(); } diff --git a/htdocs/comm/action/pertype.php b/htdocs/comm/action/pertype.php index 85eb355f2b6..d21b20bbfaf 100644 --- a/htdocs/comm/action/pertype.php +++ b/htdocs/comm/action/pertype.php @@ -189,7 +189,7 @@ if ($action == 'delete_action' && $user->rights->agenda->delete) { $event->fetch($actionid); $event->fetch_optionals(); $event->fetch_userassigned(); - $event->oldcopy = clone $event; + $event->oldcopy = dol_clone($event); $result = $event->delete(); } diff --git a/htdocs/comm/action/peruser.php b/htdocs/comm/action/peruser.php index 87def7240f5..b30ef8f7ba9 100644 --- a/htdocs/comm/action/peruser.php +++ b/htdocs/comm/action/peruser.php @@ -196,7 +196,7 @@ if ($action == 'delete_action' && $user->rights->agenda->delete) { $event->fetch($actionid); $event->fetch_optionals(); $event->fetch_userassigned(); - $event->oldcopy = clone $event; + $event->oldcopy = dol_clone($event); $result = $event->delete(); } diff --git a/htdocs/contact/perso.php b/htdocs/contact/perso.php index 6030fc1e6bd..aa7ba34d9f0 100644 --- a/htdocs/contact/perso.php +++ b/htdocs/contact/perso.php @@ -60,7 +60,7 @@ if ($action == 'update' && !GETPOST("cancel") && $user->rights->societe->contact $result = $object->update_perso($id, $user); if ($result > 0) { - $object->oldcopy = clone $object; + $object->oldcopy = dol_clone($object); // Logo/Photo save $dir = $conf->societe->dir_output.'/contact/'.get_exdir($object->id, 0, 0, 1, $object, 'contact').'/photos'; diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 1e8da8a9a81..8dbcde19d0d 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -3135,8 +3135,7 @@ class ContratLigne extends CommonObjectLine $this->db->begin(); - $this->oldcopy = new ContratLigne($this->db); - $this->oldcopy->fetch($this->id); + $this->oldcopy = dol_clone($this); // Update request $sql = "UPDATE ".MAIN_DB_PREFIX."contratdet SET"; diff --git a/htdocs/core/class/comment.class.php b/htdocs/core/class/comment.class.php index 937ca6f7875..960d2ac4744 100644 --- a/htdocs/core/class/comment.class.php +++ b/htdocs/core/class/comment.class.php @@ -71,19 +71,19 @@ class Comment extends CommonObject public $fk_user_modif; /** - * @var int Entity + * @var int Entity */ public $entity; /** - * @var string import key + * @var string Import key */ public $import_key; public $comments = array(); /** - * @var Comment Object oldcopy + * @var Comment Object oldcopy */ public $oldcopy; diff --git a/htdocs/fichinter/class/fichinter.class.php b/htdocs/fichinter/class/fichinter.class.php index 029c5651a32..b832bceb822 100644 --- a/htdocs/fichinter/class/fichinter.class.php +++ b/htdocs/fichinter/class/fichinter.class.php @@ -533,7 +533,7 @@ class Fichinter extends CommonObject $resql = $this->db->query($sql); if ($resql) { if (!$error) { - $this->oldcopy = clone $this; + $this->oldcopy = dol_clone($this); } if (!$error) { @@ -1422,7 +1422,7 @@ class Fichinter extends CommonObject } if (!$error) { - $this->oldcopy = clone $this; + $this->oldcopy = dol_clone($this); $this->ref_client = $ref_client; } diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index fde8c453a2e..28ddb32624b 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -1051,9 +1051,7 @@ class Product extends CommonObject if ($result >= 0) { if (empty($this->oldcopy)) { - $org = new self($this->db); - $org->fetch($this->id); - $this->oldcopy = $org; + $this->oldcopy = dol_clone($this); } // Test if batch management is activated on existing product diff --git a/htdocs/product/stock/class/productlot.class.php b/htdocs/product/stock/class/productlot.class.php index 0e0f8883f99..3b169055bfa 100644 --- a/htdocs/product/stock/class/productlot.class.php +++ b/htdocs/product/stock/class/productlot.class.php @@ -388,9 +388,7 @@ class Productlot extends CommonObject // Put here code to add a control on parameters values if (empty($this->oldcopy)) { - $org = new self($this->db); - $org->fetch($this->id); - $this->oldcopy = $org; + $this->oldcopy = dol_clone($this); } // Update request diff --git a/htdocs/resource/class/dolresource.class.php b/htdocs/resource/class/dolresource.class.php index da99b2f2e97..2188d3b0a23 100644 --- a/htdocs/resource/class/dolresource.class.php +++ b/htdocs/resource/class/dolresource.class.php @@ -263,9 +263,7 @@ class Dolresource extends CommonObject } if (empty($this->oldcopy)) { - $org = new self($this->db); - $org->fetch($this->id); - $this->oldcopy = $org; + $this->oldcopy = dol_clone($this); } // Update request diff --git a/htdocs/user/bank.php b/htdocs/user/bank.php index 6be5afb3753..edae0a6a89a 100644 --- a/htdocs/user/bank.php +++ b/htdocs/user/bank.php @@ -149,7 +149,7 @@ if ($action == 'update' && !$cancel && $permissiontoaddbankaccount) { { $objectuser->fetch($id); - $objectuser->oldcopy = clone $objectuser; + $objectuser->oldcopy = dol_clone($objectuser); $db->begin(); From 15c0d1e3f06356f2dfc24a886afdc632226dc331 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 12 Aug 2022 00:38:10 +0200 Subject: [PATCH 536/826] doc --- htdocs/product/class/product.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 28ddb32624b..acdb88da9f5 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -1927,7 +1927,7 @@ class Product extends CommonObject global $conf; $result = 0; - // We do a first seach with a select by searching with couple prodfournprice and qty only (later we will search on triplet qty/product_id/fourn_ref) + // We do a first search with a select by searching with couple prodfournprice and qty only (later we will search on triplet qty/product_id/fourn_ref) $sql = "SELECT pfp.rowid, pfp.price as price, pfp.quantity as quantity, pfp.remise_percent,"; $sql .= " pfp.fk_product, pfp.ref_fourn, pfp.desc_fourn, pfp.fk_soc, pfp.tva_tx, pfp.fk_supplier_price_expression,"; $sql .= " pfp.default_vat_code,"; From a698c60a7d063ea4d8a92182d502b3f51d0b10aa Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 12 Aug 2022 09:12:09 +0200 Subject: [PATCH 537/826] update code for PHP8 compliance --- htdocs/accountancy/closure/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/accountancy/closure/index.php b/htdocs/accountancy/closure/index.php index a1d75440b56..999e2ce5bd1 100644 --- a/htdocs/accountancy/closure/index.php +++ b/htdocs/accountancy/closure/index.php @@ -75,7 +75,7 @@ if (empty($user->rights->accounting->fiscalyear->write)) { $now = dol_now(); -if ($action == 'validate_movements_confirm' && !empty($user->rights->accounting->fiscalyear->write)) { +if ($action == 'validate_movements_confirm' && $user->hasRight('accounting', 'fiscalyear', 'write')) { $date_start = dol_mktime(0, 0, 0, GETPOST('date_startmonth', 'int'), GETPOST('date_startday', 'int'), GETPOST('date_startyear', 'int')); $date_end = dol_mktime(23, 59, 59, GETPOST('date_endmonth', 'int'), GETPOST('date_endday', 'int'), GETPOST('date_endyear', 'int')); From 29cb0ce68719645f69c5e48d47c0ea6c992562b4 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 12 Aug 2022 09:13:12 +0200 Subject: [PATCH 538/826] update code for PHP8 compliance --- htdocs/accountancy/admin/productaccount.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/accountancy/admin/productaccount.php b/htdocs/accountancy/admin/productaccount.php index c8cb62cd7e0..d520c82bf35 100644 --- a/htdocs/accountancy/admin/productaccount.php +++ b/htdocs/accountancy/admin/productaccount.php @@ -522,7 +522,7 @@ if ($resql) { // Filter on categories $moreforfilter = ''; - if (!empty($conf->categorie->enabled) && $user->rights->categorie->lire) { + if (!empty($conf->categorie->enabled) && $user->hasRight('categorie', 'lire')) { $moreforfilter .= '
'; $moreforfilter .= img_picto($langs->trans('Categories'), 'category', 'class="pictofixedwidth"'); $categoriesProductArr = $form->select_all_categories(Categorie::TYPE_PRODUCT, '', '', 64, 0, 1); From 723d90f33f0732b851d141b4a5cb568ad9930d32 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 12 Aug 2022 09:13:34 +0200 Subject: [PATCH 539/826] update code for PHP8 compliance --- htdocs/accountancy/admin/fiscalyear.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/accountancy/admin/fiscalyear.php b/htdocs/accountancy/admin/fiscalyear.php index 2eb77815b60..6a6135dad40 100644 --- a/htdocs/accountancy/admin/fiscalyear.php +++ b/htdocs/accountancy/admin/fiscalyear.php @@ -121,7 +121,7 @@ if ($result) { $i = 0; - $addbutton .= dolGetButtonTitle($langs->trans('NewFiscalYear'), '', 'fa fa-plus-circle', 'fiscalyear_card.php?action=create', '', $user->rights->accounting->fiscalyear->write); + $addbutton .= dolGetButtonTitle($langs->trans('NewFiscalYear'), '', 'fa fa-plus-circle', 'fiscalyear_card.php?action=create', '', $user->hasRight('accounting', 'fiscalyear', 'write')); $title = $langs->trans('AccountingPeriods'); From 71f138caba8755b9c18ed3ac3407fc2d9cd3e717 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 12 Aug 2022 09:13:52 +0200 Subject: [PATCH 540/826] update code for PHP8 compliance --- htdocs/accountancy/admin/fiscalyear_card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/accountancy/admin/fiscalyear_card.php b/htdocs/accountancy/admin/fiscalyear_card.php index 2aa33f21645..f6e765caf13 100644 --- a/htdocs/accountancy/admin/fiscalyear_card.php +++ b/htdocs/accountancy/admin/fiscalyear_card.php @@ -299,7 +299,7 @@ if ($action == 'create') { /* * Action bar */ - if (!empty($user->rights->accounting->fiscalyear->write)) { + if ($user->hasRight('accounting', 'fiscalyear', 'write')) { print '
'; print ''.$langs->trans('Modify').''; From d9dcecb6be15acc925faa3808b2ecfe50a81d795 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 12 Aug 2022 09:14:41 +0200 Subject: [PATCH 541/826] update code for PHP8 compliance --- htdocs/accountancy/admin/card.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/htdocs/accountancy/admin/card.php b/htdocs/accountancy/admin/card.php index 02b95cfd043..5c1044380f9 100644 --- a/htdocs/accountancy/admin/card.php +++ b/htdocs/accountancy/admin/card.php @@ -66,7 +66,7 @@ if (GETPOST('cancel', 'alpha')) { exit; } -if ($action == 'add' && $user->rights->accounting->chartofaccount) { +if ($action == 'add' && $user->hasRight('accounting', 'chartofaccount')) { if (!$cancel) { if (!$account_number) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("AccountNumber")), null, 'errors'); @@ -127,7 +127,7 @@ if ($action == 'add' && $user->rights->accounting->chartofaccount) { } } } -} elseif ($action == 'edit' && $user->rights->accounting->chartofaccount) { +} elseif ($action == 'edit' && $user->hasRight('accounting', 'chartofaccount')) { if (!$cancel) { if (!$account_number) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("AccountNumber")), null, 'errors'); @@ -184,7 +184,7 @@ if ($action == 'add' && $user->rights->accounting->chartofaccount) { header("Location: ".$urltogo); exit(); } -} elseif ($action == 'delete' && $user->rights->accounting->chartofaccount) { +} elseif ($action == 'delete' && $user->hasRight('accounting', 'chartofaccount')) { $result = $object->fetch($id); if (!empty($object->id)) { @@ -419,13 +419,13 @@ if ($action == 'create') { */ print '
'; - if (!empty($user->rights->accounting->chartofaccount)) { + if ($user->hasRight('accounting', 'chartofaccount')) { print 'id.'">'.$langs->trans('Modify').''; } else { print ''.$langs->trans('Modify').''; } - if (!empty($user->rights->accounting->chartofaccount)) { + if ($user->hasRight('accounting', 'chartofaccount')) { print 'id.'">'.$langs->trans('Delete').''; } else { print ''.$langs->trans('Delete').''; From 6298dc2f0d7f25b138272bc6131fa4ca7953ad84 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 12 Aug 2022 09:14:58 +0200 Subject: [PATCH 542/826] update code for PHP8 compliance --- htdocs/accountancy/admin/account.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/accountancy/admin/account.php b/htdocs/accountancy/admin/account.php index 4d74237e2e4..f818e9a0a1a 100644 --- a/htdocs/accountancy/admin/account.php +++ b/htdocs/accountancy/admin/account.php @@ -52,8 +52,8 @@ $confirm = GETPOST('confirm', 'alpha'); $chartofaccounts = GETPOST('chartofaccounts', 'int'); -$permissiontoadd = !empty($user->rights->accounting->chartofaccount); -$permissiontodelete = !empty($user->rights->accounting->chartofaccount); +$permissiontoadd = $user->hasRight('accounting', 'chartofaccount'); +$permissiontodelete = $user->hasRight('accounting', 'chartofaccount'); // Security check if ($user->socid > 0) { @@ -294,7 +294,7 @@ if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { } // List of mass actions available -if ($user->rights->accounting->chartofaccount) { +if ($user->hasRight('accounting', 'chartofaccount')) { $arrayofmassactions['predelete'] = ''.$langs->trans("Delete"); } if (in_array($massaction, array('presend', 'predelete', 'closed'))) { @@ -590,7 +590,7 @@ if ($resql) { // Action print '
'; - if ($user->rights->accounting->chartofaccount) { + if ($user->hasRight('accounting', 'chartofaccount')) { print ''; print img_edit(); print ''; From a9b6d97217072ea9c1c04621c4079eb2c55ca584 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 12 Aug 2022 09:15:32 +0200 Subject: [PATCH 543/826] update code for PHP8 compliance --- htdocs/accountancy/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/accountancy/index.php b/htdocs/accountancy/index.php index 926097c1509..cf0d94980fa 100644 --- a/htdocs/accountancy/index.php +++ b/htdocs/accountancy/index.php @@ -49,7 +49,7 @@ if (empty($user->rights->accounting->mouvements->lire)) { if (empty($conf->comptabilite->enabled) && empty($conf->accounting->enabled) && empty($conf->asset->enabled) && empty($conf->intracommreport->enabled)) { accessforbidden(); } -if (empty($user->hasRight('compta', 'resultat', 'lire')) && empty($user->hasRight('accounting', 'comptarapport', 'lire')) && empty($user->hasRight('accounting', 'mouvements', 'lire')) && empty($user->hasRight('asset', 'read')) && empty($user->hasRight('intracommreport', 'read'))) { +if ($user->hasRight('compta', 'resultat', 'lire') && $user->hasRight('accounting', 'comptarapport', 'lire') && $user->hasRight('accounting', 'mouvements', 'lire') && $user->hasRight('asset', 'read') && $user->hasRight('intracommreport', 'read')) { accessforbidden(); } From d113cf3689ad3a579c0d723c42329bfaeff27617 Mon Sep 17 00:00:00 2001 From: atm-florian Date: Fri, 12 Aug 2022 09:20:18 +0200 Subject: [PATCH 544/826] Ticket `oldcopy`: use dol_clone() instead of fetching; keep oldcopy up to date if the methods are called several times --- htdocs/ticket/class/ticket.class.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/htdocs/ticket/class/ticket.class.php b/htdocs/ticket/class/ticket.class.php index 95c60480cfa..f6a4773c58f 100644 --- a/htdocs/ticket/class/ticket.class.php +++ b/htdocs/ticket/class/ticket.class.php @@ -870,9 +870,8 @@ class Ticket extends CommonObject global $conf, $langs, $hookmanager; $error = 0; - if (empty($this->oldcopy) && empty($notrigger)) { - $this->oldcopy = new self($this->db); - $this->oldcopy->fetch($this->id); + if (empty($notrigger)) { + $this->oldcopy = dol_clone($this, 1); } // Clean parameters @@ -1464,9 +1463,8 @@ class Ticket extends CommonObject $error = 0; if ($this->statut != self::STATUS_CANCELED) { // no closed - if (empty($this->oldcopy) && empty($notrigger)) { - $this->oldcopy = new self($this->db); - $this->oldcopy->fetch($this->id); + if (empty($notrigger)) { + $this->oldcopy = dol_clone($this, 1); } $this->db->begin(); From 56fa4d3413fb1bb92cf9d83c04d803c40c11001a Mon Sep 17 00:00:00 2001 From: Faustin Date: Fri, 12 Aug 2022 10:30:22 +0200 Subject: [PATCH 545/826] Mail collection --- htdocs/admin/emailcollector_card.php | 2 +- htdocs/core/db/mysqli.class.php | 2 +- .../class/emailcollector.class.php | 536 +++++++++++------- 3 files changed, 326 insertions(+), 214 deletions(-) diff --git a/htdocs/admin/emailcollector_card.php b/htdocs/admin/emailcollector_card.php index bc8267f9ef9..8600638eef7 100644 --- a/htdocs/admin/emailcollector_card.php +++ b/htdocs/admin/emailcollector_card.php @@ -224,7 +224,7 @@ if ($action == 'deleteoperation') { } } -if ($action == 'confirm_collect') { +if ($action == 'collect') { dol_include_once('/emailcollector/class/emailcollector.class.php'); $res = $object->doCollectOneCollector(); diff --git a/htdocs/core/db/mysqli.class.php b/htdocs/core/db/mysqli.class.php index 9b1d78f1694..5dd7f366a7e 100644 --- a/htdocs/core/db/mysqli.class.php +++ b/htdocs/core/db/mysqli.class.php @@ -236,7 +236,7 @@ class DoliDBMysqli extends DoliDB // return mysqli::real_connect($host, $user, $pass, $db, $port); $tmp = false; try { - $tmp = new mysqli($host, $login, $passwd, $name, $port); + $tmp = new mysqli("127.0.0.1", $login, $passwd, $name, $port); } catch (Exception $e) { dol_syslog(get_class($this)."::connect failed", LOG_DEBUG); } diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index 4f95a44652e..87f2757b83b 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -40,9 +40,17 @@ require_once DOL_DOCUMENT_ROOT.'/supplier_proposal/class/supplier_proposal.class require_once DOL_DOCUMENT_ROOT.'/reception/class/reception.class.php'; // reception include_once DOL_DOCUMENT_ROOT.'/emailcollector/lib/emailcollector.lib.php'; //require_once DOL_DOCUMENT_ROOT.'/holiday/class/holiday.class.php'; // Holidays (leave request) -//require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php'; // expernse report +//require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php'; // expernse repor +// use Webklex\PHPIMAP; +require DOL_DOCUMENT_ROOT.'/includes/webklex/php-imap/vendor/autoload.php'; +use Webklex\PHPIMAP\ClientManager; + +use Webklex\PHPIMAP\Exceptions\ConnectionFailedException; +use Webklex\PHPIMAP\Exceptions\InvalidWhereQueryCriteriaException; +use Webklex\PHPIMAP\Exceptions\GetMessagesFailedException; + /** * Class for EmailCollector */ @@ -115,7 +123,7 @@ class EmailCollector extends CommonObject 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'visible'=>1, 'enabled'=>1, 'position'=>30, 'notnull'=>-1, 'searchall'=>1, 'help'=>'Example: My Email collector', 'csslist'=>'tdoverflowmax150'), 'description' => array('type'=>'text', 'label'=>'Description', 'visible'=>-1, 'enabled'=>1, 'position'=>60, 'notnull'=>-1, 'csslist'=>'small'), 'host' => array('type'=>'varchar(255)', 'label'=>'EMailHost', 'visible'=>1, 'enabled'=>1, 'position'=>90, 'notnull'=>1, 'searchall'=>1, 'comment'=>"IMAP server", 'help'=>'Example: imap.gmail.com', 'csslist'=>'tdoverflow125'), - 'port' => array('type'=>'varchar(10)', 'label'=>'EMailHostPort', 'visible'=>1, 'enabled'=>1, 'position'=>91, 'notnull'=>1, 'searchall'=>0, 'comment'=>"IMAP server port", 'help'=>'Example: 993', 'csslist'=>'tdoverflow125', 'default'=>'993'), + // 'port' => array('type'=>'varchar(10)', 'label'=>'EMailHostPort', 'visible'=>1, 'enabled'=>1, 'position'=>91, 'notnull'=>1, 'searchall'=>0, 'comment'=>"IMAP server port", 'help'=>'Example: 993', 'csslist'=>'tdoverflow125', 'default'=>'993'), 'hostcharset' => array('type'=>'varchar(16)', 'label'=>'HostCharset', 'visible'=>-1, 'enabled'=>1, 'position'=>92, 'notnull'=>0, 'searchall'=>0, 'comment'=>"IMAP server charset", 'help'=>'Example: "UTF-8" (May be "US-ASCII" with some Office365)', 'default'=>'UTF-8'), 'login' => array('type'=>'varchar(128)', 'label'=>'Login', 'visible'=>-1, 'enabled'=>1, 'position'=>101, 'notnull'=>-1, 'index'=>1, 'comment'=>"IMAP login", 'help'=>'Example: myaccount@gmail.com'), 'password' => array('type'=>'password', 'label'=>'Password', 'visible'=>-1, 'enabled'=>1, 'position'=>102, 'notnull'=>-1, 'comment'=>"IMAP password", 'help'=>'WithGMailYouCanCreateADedicatedPassword'), @@ -968,239 +976,329 @@ class EmailCollector extends CommonObject $now = dol_now(); - if (empty($this->host)) { - $this->error = $langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('EMailHost')); - return -1; - } - if (empty($this->login)) { - $this->error = $langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Login')); - return -1; - } - if (empty($this->source_directory)) { - $this->error = $langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('MailboxSourceDirectory')); - return -1; - } - if (!function_exists('imap_open')) { - $this->error = 'IMAP function not enabled on your PHP'; - return -2; - } + // if (empty($this->host)) { + // $this->error = $langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('EMailHost')); + // return -1; + // } + // if (empty($this->login)) { + // $this->error = $langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Login')); + // return -1; + // } $this->fetchFilters(); $this->fetchActions(); - $sourcedir = $this->source_directory; - $targetdir = ($this->target_directory ? $this->target_directory : ''); // Can be '[Gmail]/Trash' or 'mytag' + if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP)) { + $cm = new ClientManager(); + $client = $cm->make([ + 'host' => 'smtp.gmail.com', + 'port' => 993, + 'encryption' => 'ssl', + 'validate_cert' => true, + 'protocol' => 'imap', + 'username' => 'boitel.faustin@gmail.com', + 'password' => 'ya29.A0AVA9y1siEZ-DibQtRUpD-FKBsCxAdm_m70o9SET8F8X9_VBlOk2RErA70mXNgrGScmShhGR1QTcHbYuROT1KyMUQiFOe_VsyTqiFVt9ry41VTLnCICybvMvvfcHcXQjo4AGhofK8xB2qWVJPHhvOdJABHexmaCgYKATASATASFQE65dr8Pgiz_lRG76Aea35N2cFGFw0163', + 'authentication' => "oauth", + ]); - $connectstringserver = $this->getConnectStringIMAP(); - $connectstringsource = $connectstringserver.imap_utf7_encode($sourcedir); - $connectstringtarget = $connectstringserver.imap_utf7_encode($targetdir); - - $connection = imap_open($connectstringsource, $this->login, $this->password); - if (!$connection) { - $this->error = 'Failed to open IMAP connection '.$connectstringsource; - return -3; - } - imap_errors(); // Clear stack of errors. - - $host = dol_getprefix('email'); - //$host = '123456'; - - // Define the IMAP search string - // See https://tools.ietf.org/html/rfc3501#section-6.4.4 for IMAPv4 (PHP not yet compatible) - // See https://tools.ietf.org/html/rfc1064 page 13 for IMAPv2 - //$search='ALL'; - $search = 'UNDELETED'; // Seems not supported by some servers - $searchhead = ''; - $searchfilterdoltrackid = 0; - $searchfilternodoltrackid = 0; - $searchfilterisanswer = 0; - $searchfilterisnotanswer = 0; - foreach ($this->filters as $rule) { - if (empty($rule['status'])) { - continue; + try { + $client->connect(); + } catch (ConnectionFailedException $e) { + $this->error = $e->getMessage(); + $this->errors[] = $this->error; + dol_syslog("EmailCollector::doCollectOneCollector ".$this->error, LOG_ERR); + return -1; } + } else { + if (empty($this->source_directory)) { + $this->error = $langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('MailboxSourceDirectory')); + return -1; + } + if (!function_exists('imap_open')) { + $this->error = 'IMAP function not enabled on your PHP'; + return -2; + } + $sourcedir = $this->source_directory; + $targetdir = ($this->target_directory ? $this->target_directory : ''); // Can be '[Gmail]/Trash' or 'mytag' - if ($rule['type'] == 'to') { - $tmprulevaluearray = explode('*', $rule['rulevalue']); - if (count($tmprulevaluearray) >= 2) { - foreach ($tmprulevaluearray as $tmprulevalue) { - $search .= ($search ? ' ' : '').'TO "'.str_replace('"', '', $tmprulevalue).'"'; + $connectstringserver = $this->getConnectStringIMAP(); + $connectstringsource = $connectstringserver.imap_utf7_encode($sourcedir); + $connectstringtarget = $connectstringserver.imap_utf7_encode($targetdir); + + $connection = imap_open($connectstringsource, $this->login, $this->password); + if (!$connection) { + $this->error = 'Failed to open IMAP connection '.$connectstringsource; + return -3; + } + imap_errors(); // Clear stack of errors. + + $host = dol_getprefix('email'); + //$host = '123456'; + + // Define the IMAP search string + // See https://tools.ietf.org/html/rfc3501#section-6.4.4 for IMAPv4 (PHP not yet compatible) + // See https://tools.ietf.org/html/rfc1064 page 13 for IMAPv2 + //$search='ALL'; + } + + if ($conf->global->MAIN_IMAP_USE_PHPIMAP) { + $criteria = array(array('UNDELETED')); // Seems not supported by some servers + // $searchhead = ''; + // $searchfilterdoltrackid = 0; + // $searchfilternodoltrackid = 0; + // $searchfilterisanswer = 0; + // $searchfilterisnotanswer = 0; + foreach ($this->filters as $rule) { + if (empty($rule['status'])) { + continue; + } + if ($rule['type'] == 'to') { + $tmprulevaluearray = explode('*', $rule['rulevalue']); + if (count($tmprulevaluearray) >= 2) { + foreach ($tmprulevaluearray as $tmprulevalue) { + array_push($criteria, array("TO" => $tmprulevalue)); + } + } else { + array_push($criteria, array("TO" => $rule['rulevalue'])); } - } else { - $search .= ($search ? ' ' : '').'TO "'.str_replace('"', '', $rule['rulevalue']).'"'; + } + if ($rule['type'] == 'bcc') { + array_push($criteria, array("BCC" => $rule['rulevalue'])); + } + if ($rule['type'] == 'cc') { + array_push($criteria, array("CC" => $rule['rulevalue'])); + } + if ($rule['type'] == 'from') { + array_push($criteria, array("FROM" => $rule['rulevalue'])); + } + if ($rule['type'] == 'subject') { + array_push($criteria, array("SUBJECT" => $rule['rulevalue'])); + } + if ($rule['type'] == 'body') { + array_push($criteria, array("BODY" => $rule['rulevalue'])); + } + if ($rule['type'] == 'header') { + array_push($criteria, array("HEADER" => $rule['rulevalue'])); + } + + if ($rule['type'] == 'notinsubject') { + array_push($criteria, array("SUBJECT NOT" => $rule['rulevalue'])); + } + if ($rule['type'] == 'notinbody') { + array_push($criteria, array("BODY NOT" => $rule['rulevalue'])); + } + + if ($rule['type'] == 'seen') { + array_push($criteria, array("SEEN")); + } + if ($rule['type'] == 'unseen') { + array_push($criteria, array("UNSEEN")); + } + if ($rule['type'] == 'unanswered') { + array_push($criteria, array("UNANSWERED")); + } + if ($rule['type'] == 'answered') { + array_push($criteria, array("ANSWERED")); } } - if ($rule['type'] == 'bcc') { - $search .= ($search ? ' ' : '').'BCC'; + + if (empty($targetdir)) { // Use last date as filter if there is no targetdir defined. + $fromdate = 0; + if ($this->datelastok) { + $fromdate = $this->datelastok; + } + if ($fromdate > 0) { + // $search .= ($search ? ' ' : '').'SINCE '.date('j-M-Y', $fromdate - 1); // SENTSINCE not supported. Date must be X-Abc-9999 (X on 1 digit if < 10) + array_push($criteria, array("SINCE" => date('j-M-Y', $fromdate - 1))); + } + //$search.=($search?' ':'').'SINCE 8-Apr-2018'; } - if ($rule['type'] == 'cc') { - $search .= ($search ? ' ' : '').'CC'; - } - if ($rule['type'] == 'from') { - $search .= ($search ? ' ' : '').'FROM "'.str_replace('"', '', $rule['rulevalue']).'"'; - } - if ($rule['type'] == 'subject') { - $search .= ($search ? ' ' : '').'SUBJECT "'.str_replace('"', '', $rule['rulevalue']).'"'; - } - if ($rule['type'] == 'body') { - $search .= ($search ? ' ' : '').'BODY "'.str_replace('"', '', $rule['rulevalue']).'"'; - } - if ($rule['type'] == 'header') { - $search .= ($search ? ' ' : '').'HEADER '.$rule['rulevalue']; + dol_syslog("IMAP search string = ".$search); + //var_dump($search); + } else { + $search = 'UNDELETED'; // Seems not supported by some servers + $searchhead = ''; + $searchfilterdoltrackid = 0; + $searchfilternodoltrackid = 0; + $searchfilterisanswer = 0; + $searchfilterisnotanswer = 0; + foreach ($this->filters as $rule) { + if (empty($rule['status'])) { + continue; + } + + if ($rule['type'] == 'to') { + $tmprulevaluearray = explode('*', $rule['rulevalue']); + if (count($tmprulevaluearray) >= 2) { + foreach ($tmprulevaluearray as $tmprulevalue) { + $search .= ($search ? ' ' : '').'TO "'.str_replace('"', '', $tmprulevalue).'"'; + } + } else { + $search .= ($search ? ' ' : '').'TO "'.str_replace('"', '', $rule['rulevalue']).'"'; + } + } + if ($rule['type'] == 'bcc') { + $search .= ($search ? ' ' : '').'BCC'; + } + if ($rule['type'] == 'cc') { + $search .= ($search ? ' ' : '').'CC'; + } + if ($rule['type'] == 'from') { + $search .= ($search ? ' ' : '').'FROM "'.str_replace('"', '', $rule['rulevalue']).'"'; + } + if ($rule['type'] == 'subject') { + $search .= ($search ? ' ' : '').'SUBJECT "'.str_replace('"', '', $rule['rulevalue']).'"'; + } + if ($rule['type'] == 'body') { + $search .= ($search ? ' ' : '').'BODY "'.str_replace('"', '', $rule['rulevalue']).'"'; + } + if ($rule['type'] == 'header') { + $search .= ($search ? ' ' : '').'HEADER '.$rule['rulevalue']; + } + + if ($rule['type'] == 'notinsubject') { + $search .= ($search ? ' ' : '').'SUBJECT NOT "'.str_replace('"', '', $rule['rulevalue']).'"'; + } + if ($rule['type'] == 'notinbody') { + $search .= ($search ? ' ' : '').'BODY NOT "'.str_replace('"', '', $rule['rulevalue']).'"'; + } + + if ($rule['type'] == 'seen') { + $search .= ($search ? ' ' : '').'SEEN'; + } + if ($rule['type'] == 'unseen') { + $search .= ($search ? ' ' : '').'UNSEEN'; + } + if ($rule['type'] == 'unanswered') { + $search .= ($search ? ' ' : '').'UNANSWERED'; + } + if ($rule['type'] == 'answered') { + $search .= ($search ? ' ' : '').'ANSWERED'; + } + if ($rule['type'] == 'smaller') { + $search .= ($search ? ' ' : '').'SMALLER "'.str_replace('"', '', $rule['rulevalue']).'"'; + } + if ($rule['type'] == 'larger') { + $search .= ($search ? ' ' : '').'LARGER "'.str_replace('"', '', $rule['rulevalue']).'"'; + } + + if ($rule['type'] == 'withtrackingidinmsgid') { + $searchfilterdoltrackid++; $searchhead .= '/Message-ID.*@'.preg_quote($host, '/').'/'; + } + if ($rule['type'] == 'withouttrackingidinmsgid') { + $searchfilterdoltrackid++; $searchhead .= '/Message-ID.*@'.preg_quote($host, '/').'/'; + } + if ($rule['type'] == 'withtrackingid') { + $searchfilterdoltrackid++; $searchhead .= '/References.*@'.preg_quote($host, '/').'/'; + } + if ($rule['type'] == 'withouttrackingid') { + $searchfilternodoltrackid++; $searchhead .= '! /References.*@'.preg_quote($host, '/').'/'; + } + + if ($rule['type'] == 'isanswer') { + $searchfilterisanswer++; $searchhead .= '/References.*@.*/'; + } + if ($rule['type'] == 'isnotanswer') { + $searchfilterisnotanswer++; $searchhead .= '! /References.*@.*/'; + } } - if ($rule['type'] == 'notinsubject') { - $search .= ($search ? ' ' : '').'SUBJECT NOT "'.str_replace('"', '', $rule['rulevalue']).'"'; - } - if ($rule['type'] == 'notinbody') { - $search .= ($search ? ' ' : '').'BODY NOT "'.str_replace('"', '', $rule['rulevalue']).'"'; - } - - if ($rule['type'] == 'seen') { - $search .= ($search ? ' ' : '').'SEEN'; - } - if ($rule['type'] == 'unseen') { - $search .= ($search ? ' ' : '').'UNSEEN'; - } - if ($rule['type'] == 'unanswered') { - $search .= ($search ? ' ' : '').'UNANSWERED'; - } - if ($rule['type'] == 'answered') { - $search .= ($search ? ' ' : '').'ANSWERED'; - } - if ($rule['type'] == 'smaller') { - $search .= ($search ? ' ' : '').'SMALLER "'.str_replace('"', '', $rule['rulevalue']).'"'; - } - if ($rule['type'] == 'larger') { - $search .= ($search ? ' ' : '').'LARGER "'.str_replace('"', '', $rule['rulevalue']).'"'; - } - - if ($rule['type'] == 'withtrackingidinmsgid') { - $searchfilterdoltrackid++; $searchhead .= '/Message-ID.*@'.preg_quote($host, '/').'/'; - } - if ($rule['type'] == 'withouttrackingidinmsgid') { - $searchfilterdoltrackid++; $searchhead .= '/Message-ID.*@'.preg_quote($host, '/').'/'; - } - if ($rule['type'] == 'withtrackingid') { - $searchfilterdoltrackid++; $searchhead .= '/References.*@'.preg_quote($host, '/').'/'; - } - if ($rule['type'] == 'withouttrackingid') { - $searchfilternodoltrackid++; $searchhead .= '! /References.*@'.preg_quote($host, '/').'/'; - } - - if ($rule['type'] == 'isanswer') { - $searchfilterisanswer++; $searchhead .= '/References.*@.*/'; - } - if ($rule['type'] == 'isnotanswer') { - $searchfilterisnotanswer++; $searchhead .= '! /References.*@.*/'; + if (empty($targetdir)) { // Use last date as filter if there is no targetdir defined. + $fromdate = 0; + if ($this->datelastok) { + $fromdate = $this->datelastok; + } + if ($fromdate > 0) { + $search .= ($search ? ' ' : '').'SINCE '.date('j-M-Y', $fromdate - 1); // SENTSINCE not supported. Date must be X-Abc-9999 (X on 1 digit if < 10) + } + //$search.=($search?' ':'').'SINCE 8-Apr-2018'; } + dol_syslog("IMAP search string = ".$search); + //var_dump($search); } - if (empty($targetdir)) { // Use last date as filter if there is no targetdir defined. - $fromdate = 0; - if ($this->datelastok) { - $fromdate = $this->datelastok; - } - if ($fromdate > 0) { - $search .= ($search ? ' ' : '').'SINCE '.date('j-M-Y', $fromdate - 1); // SENTSINCE not supported. Date must be X-Abc-9999 (X on 1 digit if < 10) - } - //$search.=($search?' ':'').'SINCE 8-Apr-2018'; - } - dol_syslog("IMAP search string = ".$search); - //var_dump($search); - $nbemailprocessed = 0; $nbemailok = 0; $nbactiondone = 0; $charset = ($this->hostcharset ? $this->hostcharset : "UTF-8"); - // Scan IMAP inbox - $arrayofemail = imap_search($connection, $search, null, $charset); - if ($arrayofemail === false) { - // Nothing found or search string not understood - $mapoferrrors = imap_errors(); - if ($mapoferrrors !== false) { - $error++; - $this->error = "Search string not understood - ".join(',', $mapoferrrors); + if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP)) { + try { + $Query = $client->getFolders()[0]->messages()->where($criteria);//->all(); + } catch (InvalidWhereQueryCriteriaException $e) { + $this->error = $e->getMessage(); $this->errors[] = $this->error; + dol_syslog("EmailCollector::doCollectOneCollector ".$this->error, LOG_ERR); + return -1; + } + + try { + $arrayofemail = $Query->limit($this->maxemailpercollect)->setFetchOrder("desc")->get(); + } catch (GetMessagesFailedException $e) { + $this->error = $e->getMessage(); + $this->errors[] = $this->error; + dol_syslog("EmailCollector::doCollectOneCollector ".$this->error, LOG_ERR); + return -1; + } + // for debug + + + $found = count($arrayofemail); + print_r($criteria); + print "
".$found." mails found
"; + + for ($i = 0; $i < $found; $i++) { + $sub = $arrayofemail[$found - 1 - $i]->getSubject(); + $message = $arrayofemail[$found - 1 - $i]->getHTMLBody(); + $header = $arrayofemail[$found - 1 - $i]->getHeader(); + $flags = $arrayofemail[$found - 1 - $i]->getFlags()->keys(); + $attributes = $arrayofemail[$found - 1 - $i]->getAttributes(); + + print '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
'; + print '
'.$i.'
'; + print "FLAGS: ".$flags."
Header:"; + print_r($header->getAttributes()); + print "
Sub header:".$header->getAttributes()['message-id']."
"; + print $sub."
"; + print $message."
"; + print "FROM:".$attributes['subject']."
"; + // print_r($attributes)."


"; + print '
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


'; + } + } else { + // Scan IMAP inbox + $arrayofemail = imap_search($connection, $search, null, $charset); + if ($arrayofemail === false) { + // Nothing found or search string not understood + $mapoferrrors = imap_errors(); + if ($mapoferrrors !== false) { + $error++; + $this->error = "Search string not understood - ".join(',', $mapoferrrors); + $this->errors[] = $this->error; + } } } + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Loop on each email found if (!$error && !empty($arrayofemail) && count($arrayofemail) > 0) { // Loop to get part html and plain /* - 0 multipart/mixed - 1 multipart/alternative - 1.1 text/plain - 1.2 text/html - 2 message/rfc822 - 2 multipart/mixed - 2.1 multipart/alternative - 2.1.1 text/plain - 2.1.2 text/html + 0 multipart/mixed + 1 multipart/alternative + 1.1 text/plain + 1.2 text/html + 2 message/rfc822 + 2 multipart/mixed + 2.1 multipart/alternative + 2.1.1 text/plain + 2.1.2 text/html 2.2 message/rfc822 2.2 multipart/alternative 2.2.1 text/plain 2.2.2 text/html */ - /** - * create_part_array - * - * @param Object $structure Structure - * @param string $prefix prefix - * @return array Array with number and object - */ - /*function createPartArray($structure, $prefix = "") - { - //print_r($structure); - $part_array=array(); - if (count($structure->parts) > 0) { // There some sub parts - foreach ($structure->parts as $count => $part) { - addPartToArray($part, $prefix.($count+1), $part_array); - } - }else{ // Email does not have a seperate mime attachment for text - $part_array[] = array('part_number' => $prefix.'1', 'part_object' => $structure); - } - return $part_array; - }*/ - - /** - * Sub function for createPartArray(). Only called by createPartArray() and itself. - * - * @param Object $obj Structure - * @param string $partno Part no - * @param array $part_array array - * @return void - */ - /*function addPartToArray($obj, $partno, &$part_array) - { - $part_array[] = array('part_number' => $partno, 'part_object' => $obj); - if ($obj->type == 2) { // Check to see if the part is an attached email message, as in the RFC-822 type - //print_r($obj); - if (array_key_exists('parts', $obj)) { // Check to see if the email has parts - foreach ($obj->parts as $count => $part) { - // Iterate here again to compensate for the broken way that imap_fetchbody() handles attachments - if (count($part->parts) > 0) { - foreach ($part->parts as $count2 => $part2) { - addPartToArray($part2, $partno.".".($count2+1), $part_array); - } - }else{ // Attached email does not have a seperate mime attachment for text - $part_array[] = array('part_number' => $partno.'.'.($count+1), 'part_object' => $obj); - } - } - }else{ // Not sure if this is possible - $part_array[] = array('part_number' => $partno.'.1', 'part_object' => $obj); - } - }else{ // If there are more sub-parts, expand them out. - if (array_key_exists('parts', $obj)) { - foreach ($obj->parts as $count => $p) { - addPartToArray($p, $partno.".".($count+1), $part_array); - } - } - } - }*/ - dol_syslog("Start of loop on email", LOG_INFO, 1); $iforemailloop = 0; @@ -1208,24 +1306,32 @@ class EmailCollector extends CommonObject if ($nbemailprocessed > 1000) { break; // Do not process more than 1000 email per launch (this is a different protection than maxnbcollectedpercollect) } - $iforemailloop++; - // GET header and overview datas - $header = imap_fetchheader($connection, $imapemail, 0); - $overview = imap_fetch_overview($connection, $imapemail, 0); + // GET header and overview datas + if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP)) { + $header = $imapemail->getHeader(); + $overview = $imapemail->getAttributes(); + } else { + $header = imap_headerinfo($connection, $imapemail); + $overview = imap_fetch_overview($connection, $imapemail, 0); + } + // print $header; // var_dump($overview); // Process $header of email - $header = preg_replace('/\r\n\s+/m', ' ', $header); // When a header line is on several lines, merge lines - - $matches = array(); - preg_match_all('/([^: ]+): (.+?(?:\r\n\s(?:.+?))*)\r\n/m', $header, $matches); - $headers = array_combine($matches[1], $matches[2]); + if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP)) { + $headers = $header->getAttributes(); + } else { + $header = preg_replace('/\r\n\s+/m', ' ', $header); // When a header line is on several lines, merge lines + $matches = array(); + preg_match_all('/([^: ]+): (.+?(?:\r\n\s(?:.+?))*)\r\n/m', $header, $matches); + $headers = array_combine($matches[1], $matches[2]); + } if (!empty($headers['in-reply-to']) && empty($headers['In-Reply-To'])) { $headers['In-Reply-To'] = $headers['in-reply-to']; } @@ -1235,13 +1341,19 @@ class EmailCollector extends CommonObject if (!empty($headers['message-id']) && empty($headers['Message-ID'])) { $headers['Message-ID'] = $headers['message-id']; } + if (!empty($headers['subject']) && empty($headers['Subject'])) { + $headers['Subject'] = $headers['subject']; + } $headers['Subject'] = $this->decodeSMTPSubject($headers['Subject']); + dol_syslog("** Process email ".$iforemailloop." References: ".$headers['References']." Subject: ".$headers['Subject']); //print "Process mail ".$iforemailloop." Subject: ".dol_escape_htmltag($headers['Subject'])." References: ".dol_escape_htmltag($headers['References'])." In-Reply-To: ".dol_escape_htmltag($headers['In-Reply-To'])."
\n"; - + $err = "** Process email ".$iforemailloop." References: ".$headers['References']." Subject: ".$headers['Subject']; + $this->error = $langs->trans($err, $langs->transnoentitiesnoconv('EMailHost')); + return -1; // If there is a filter on trackid if ($searchfilterdoltrackid > 0) { if (empty($headers['References']) || !preg_match('/@'.preg_quote($host, '/').'/', $headers['References'])) { @@ -2406,7 +2518,7 @@ class EmailCollector extends CommonObject 'header'=>$header, 'attachments'=>$attachments, ); - $reshook = $hookmanager->executeHooks('doCollectOneCollector', $parameters, $this, $operation['type']); + $reshook = $hookmanager->executeHooks('doColleimapctOneCollector', $parameters, $this, $operation['type']); if ($reshook < 0) { $errorforthisaction++; From b226f51ef48e37df634bc4c497b265c4b1f1994d Mon Sep 17 00:00:00 2001 From: Faustin Date: Fri, 12 Aug 2022 10:33:06 +0200 Subject: [PATCH 546/826] Mail collection --- .../.github/ISSUE_TEMPLATE/bug_report.md | 31 + .../.github/ISSUE_TEMPLATE/feature_request.md | 17 + .../ISSUE_TEMPLATE/general-help-request.md | 12 + htdocs/includes/webklex/php-imap/.gitignore | 4 + htdocs/includes/webklex/php-imap/.travis.yml | 34 + htdocs/includes/webklex/php-imap/CHANGELOG.md | 577 +++++++ .../webklex/php-imap/CODE_OF_CONDUCT.md | 46 + htdocs/includes/webklex/php-imap/LICENSE | 21 + htdocs/includes/webklex/php-imap/LICENSE.md | 21 + htdocs/includes/webklex/php-imap/README.md | 158 ++ htdocs/includes/webklex/php-imap/_config.yml | 1 + .../includes/webklex/php-imap/composer.json | 55 + .../examples/custom_attachment_mask.php | 56 + .../php-imap/examples/custom_message_mask.php | 50 + .../examples/folder_structure.blade.php | 42 + .../php-imap/examples/message_table.blade.php | 46 + htdocs/includes/webklex/php-imap/phpunit.xml | 32 + .../includes/webklex/php-imap/src/Address.php | 90 ++ .../webklex/php-imap/src/Attachment.php | 344 ++++ .../webklex/php-imap/src/Attribute.php | 274 ++++ .../includes/webklex/php-imap/src/Client.php | 669 ++++++++ .../webklex/php-imap/src/ClientManager.php | 262 +++ .../src/Connection/Protocols/ImapProtocol.php | 1074 +++++++++++++ .../Connection/Protocols/LegacyProtocol.php | 607 +++++++ .../src/Connection/Protocols/Protocol.php | 224 +++ .../Protocols/ProtocolInterface.php | 375 +++++ .../webklex/php-imap/src/EncodingAliases.php | 482 ++++++ .../webklex/php-imap/src/Events/Event.php | 28 + .../php-imap/src/Events/FlagDeletedEvent.php | 22 + .../php-imap/src/Events/FlagNewEvent.php | 39 + .../src/Events/FolderDeletedEvent.php | 22 + .../php-imap/src/Events/FolderMovedEvent.php | 38 + .../php-imap/src/Events/FolderNewEvent.php | 35 + .../src/Events/MessageCopiedEvent.php | 22 + .../src/Events/MessageDeletedEvent.php | 22 + .../php-imap/src/Events/MessageMovedEvent.php | 38 + .../php-imap/src/Events/MessageNewEvent.php | 35 + .../src/Events/MessageRestoredEvent.php | 22 + .../src/Exceptions/AuthFailedException.php | 24 + .../Exceptions/ConnectionFailedException.php | 24 + .../src/Exceptions/EventNotFoundException.php | 24 + .../Exceptions/FolderFetchingException.php | 24 + .../Exceptions/GetMessagesFailedException.php | 24 + .../InvalidMessageDateException.php | 24 + .../InvalidWhereQueryCriteriaException.php | 24 + .../src/Exceptions/MaskNotFoundException.php | 24 + .../MessageContentFetchingException.php | 24 + .../src/Exceptions/MessageFlagException.php | 24 + .../MessageHeaderFetchingException.php | 24 + .../Exceptions/MessageNotFoundException.php | 24 + .../MessageSearchValidationException.php | 24 + .../Exceptions/MethodNotFoundException.php | 24 + .../MethodNotSupportedException.php | 24 + .../ProtocolNotSupportedException.php | 24 + .../src/Exceptions/RuntimeException.php | 24 + .../includes/webklex/php-imap/src/Folder.php | 444 ++++++ .../includes/webklex/php-imap/src/Header.php | 753 +++++++++ htdocs/includes/webklex/php-imap/src/IMAP.php | 375 +++++ .../includes/webklex/php-imap/src/Message.php | 1419 +++++++++++++++++ htdocs/includes/webklex/php-imap/src/Part.php | 312 ++++ .../webklex/php-imap/src/Query/Query.php | 842 ++++++++++ .../webklex/php-imap/src/Query/WhereQuery.php | 551 +++++++ .../webklex/php-imap/src/Structure.php | 174 ++ .../src/Support/AttachmentCollection.php | 22 + .../php-imap/src/Support/FlagCollection.php | 22 + .../php-imap/src/Support/FolderCollection.php | 22 + .../src/Support/Masks/AttachmentMask.php | 44 + .../php-imap/src/Support/Masks/Mask.php | 137 ++ .../src/Support/Masks/MessageMask.php | 86 + .../src/Support/MessageCollection.php | 22 + .../src/Support/PaginatedCollection.php | 82 + .../webklex/php-imap/src/Traits/HasEvents.php | 77 + .../webklex/php-imap/src/config/imap.php | 216 +++ .../webklex/php-imap/tests/InitialTest.php | 26 + 74 files changed, 11961 insertions(+) create mode 100644 htdocs/includes/webklex/php-imap/.github/ISSUE_TEMPLATE/bug_report.md create mode 100644 htdocs/includes/webklex/php-imap/.github/ISSUE_TEMPLATE/feature_request.md create mode 100644 htdocs/includes/webklex/php-imap/.github/ISSUE_TEMPLATE/general-help-request.md create mode 100644 htdocs/includes/webklex/php-imap/.gitignore create mode 100644 htdocs/includes/webklex/php-imap/.travis.yml create mode 100755 htdocs/includes/webklex/php-imap/CHANGELOG.md create mode 100644 htdocs/includes/webklex/php-imap/CODE_OF_CONDUCT.md create mode 100644 htdocs/includes/webklex/php-imap/LICENSE create mode 100644 htdocs/includes/webklex/php-imap/LICENSE.md create mode 100755 htdocs/includes/webklex/php-imap/README.md create mode 100644 htdocs/includes/webklex/php-imap/_config.yml create mode 100644 htdocs/includes/webklex/php-imap/composer.json create mode 100644 htdocs/includes/webklex/php-imap/examples/custom_attachment_mask.php create mode 100644 htdocs/includes/webklex/php-imap/examples/custom_message_mask.php create mode 100644 htdocs/includes/webklex/php-imap/examples/folder_structure.blade.php create mode 100644 htdocs/includes/webklex/php-imap/examples/message_table.blade.php create mode 100644 htdocs/includes/webklex/php-imap/phpunit.xml create mode 100644 htdocs/includes/webklex/php-imap/src/Address.php create mode 100755 htdocs/includes/webklex/php-imap/src/Attachment.php create mode 100644 htdocs/includes/webklex/php-imap/src/Attribute.php create mode 100755 htdocs/includes/webklex/php-imap/src/Client.php create mode 100644 htdocs/includes/webklex/php-imap/src/ClientManager.php create mode 100644 htdocs/includes/webklex/php-imap/src/Connection/Protocols/ImapProtocol.php create mode 100644 htdocs/includes/webklex/php-imap/src/Connection/Protocols/LegacyProtocol.php create mode 100644 htdocs/includes/webklex/php-imap/src/Connection/Protocols/Protocol.php create mode 100644 htdocs/includes/webklex/php-imap/src/Connection/Protocols/ProtocolInterface.php create mode 100644 htdocs/includes/webklex/php-imap/src/EncodingAliases.php create mode 100644 htdocs/includes/webklex/php-imap/src/Events/Event.php create mode 100644 htdocs/includes/webklex/php-imap/src/Events/FlagDeletedEvent.php create mode 100644 htdocs/includes/webklex/php-imap/src/Events/FlagNewEvent.php create mode 100644 htdocs/includes/webklex/php-imap/src/Events/FolderDeletedEvent.php create mode 100644 htdocs/includes/webklex/php-imap/src/Events/FolderMovedEvent.php create mode 100644 htdocs/includes/webklex/php-imap/src/Events/FolderNewEvent.php create mode 100644 htdocs/includes/webklex/php-imap/src/Events/MessageCopiedEvent.php create mode 100644 htdocs/includes/webklex/php-imap/src/Events/MessageDeletedEvent.php create mode 100644 htdocs/includes/webklex/php-imap/src/Events/MessageMovedEvent.php create mode 100644 htdocs/includes/webklex/php-imap/src/Events/MessageNewEvent.php create mode 100644 htdocs/includes/webklex/php-imap/src/Events/MessageRestoredEvent.php create mode 100644 htdocs/includes/webklex/php-imap/src/Exceptions/AuthFailedException.php create mode 100644 htdocs/includes/webklex/php-imap/src/Exceptions/ConnectionFailedException.php create mode 100644 htdocs/includes/webklex/php-imap/src/Exceptions/EventNotFoundException.php create mode 100644 htdocs/includes/webklex/php-imap/src/Exceptions/FolderFetchingException.php create mode 100644 htdocs/includes/webklex/php-imap/src/Exceptions/GetMessagesFailedException.php create mode 100644 htdocs/includes/webklex/php-imap/src/Exceptions/InvalidMessageDateException.php create mode 100644 htdocs/includes/webklex/php-imap/src/Exceptions/InvalidWhereQueryCriteriaException.php create mode 100644 htdocs/includes/webklex/php-imap/src/Exceptions/MaskNotFoundException.php create mode 100644 htdocs/includes/webklex/php-imap/src/Exceptions/MessageContentFetchingException.php create mode 100644 htdocs/includes/webklex/php-imap/src/Exceptions/MessageFlagException.php create mode 100644 htdocs/includes/webklex/php-imap/src/Exceptions/MessageHeaderFetchingException.php create mode 100644 htdocs/includes/webklex/php-imap/src/Exceptions/MessageNotFoundException.php create mode 100644 htdocs/includes/webklex/php-imap/src/Exceptions/MessageSearchValidationException.php create mode 100644 htdocs/includes/webklex/php-imap/src/Exceptions/MethodNotFoundException.php create mode 100644 htdocs/includes/webklex/php-imap/src/Exceptions/MethodNotSupportedException.php create mode 100644 htdocs/includes/webklex/php-imap/src/Exceptions/ProtocolNotSupportedException.php create mode 100644 htdocs/includes/webklex/php-imap/src/Exceptions/RuntimeException.php create mode 100755 htdocs/includes/webklex/php-imap/src/Folder.php create mode 100644 htdocs/includes/webklex/php-imap/src/Header.php create mode 100644 htdocs/includes/webklex/php-imap/src/IMAP.php create mode 100755 htdocs/includes/webklex/php-imap/src/Message.php create mode 100644 htdocs/includes/webklex/php-imap/src/Part.php create mode 100644 htdocs/includes/webklex/php-imap/src/Query/Query.php create mode 100755 htdocs/includes/webklex/php-imap/src/Query/WhereQuery.php create mode 100644 htdocs/includes/webklex/php-imap/src/Structure.php create mode 100644 htdocs/includes/webklex/php-imap/src/Support/AttachmentCollection.php create mode 100644 htdocs/includes/webklex/php-imap/src/Support/FlagCollection.php create mode 100644 htdocs/includes/webklex/php-imap/src/Support/FolderCollection.php create mode 100644 htdocs/includes/webklex/php-imap/src/Support/Masks/AttachmentMask.php create mode 100755 htdocs/includes/webklex/php-imap/src/Support/Masks/Mask.php create mode 100644 htdocs/includes/webklex/php-imap/src/Support/Masks/MessageMask.php create mode 100644 htdocs/includes/webklex/php-imap/src/Support/MessageCollection.php create mode 100644 htdocs/includes/webklex/php-imap/src/Support/PaginatedCollection.php create mode 100644 htdocs/includes/webklex/php-imap/src/Traits/HasEvents.php create mode 100644 htdocs/includes/webklex/php-imap/src/config/imap.php create mode 100644 htdocs/includes/webklex/php-imap/tests/InitialTest.php diff --git a/htdocs/includes/webklex/php-imap/.github/ISSUE_TEMPLATE/bug_report.md b/htdocs/includes/webklex/php-imap/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000000..735fbe018f9 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,31 @@ +--- +name: Bug report +about: Create a report to help us improve + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**Used config** +Please provide the used config, if you are not using the package default config. + +**Code to Reproduce** +The troubling code section which produces the reported bug. +```php +echo "Bug"; +``` + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop / Server (please complete the following information):** +- OS: [e.g. Debian 10] +- PHP: [e.g. 5.5.9] +- Version [e.g. v2.3.1] + +**Additional context** +Add any other context about the problem here. diff --git a/htdocs/includes/webklex/php-imap/.github/ISSUE_TEMPLATE/feature_request.md b/htdocs/includes/webklex/php-imap/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000000..066b2d920a2 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,17 @@ +--- +name: Feature request +about: Suggest an idea for this project + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/htdocs/includes/webklex/php-imap/.github/ISSUE_TEMPLATE/general-help-request.md b/htdocs/includes/webklex/php-imap/.github/ISSUE_TEMPLATE/general-help-request.md new file mode 100644 index 00000000000..49809d14033 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/.github/ISSUE_TEMPLATE/general-help-request.md @@ -0,0 +1,12 @@ +--- +name: General help request +about: Feel free to ask about any project related stuff + +--- + +Please be aware that these issues will be closed if inactive for more then 14 days. + +Also make sure to use https://github.com/Webklex/php-imap/issues/new?template=bug_report.md if you want to report a bug +or https://github.com/Webklex/php-imap/issues/new?template=feature_request.md if you want to suggest a feature. + +Still here? Well clean this out and go ahead :) diff --git a/htdocs/includes/webklex/php-imap/.gitignore b/htdocs/includes/webklex/php-imap/.gitignore new file mode 100644 index 00000000000..77d608c3327 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/.gitignore @@ -0,0 +1,4 @@ +vendor +composer.lock +.idea +/build/ diff --git a/htdocs/includes/webklex/php-imap/.travis.yml b/htdocs/includes/webklex/php-imap/.travis.yml new file mode 100644 index 00000000000..26e564efd77 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/.travis.yml @@ -0,0 +1,34 @@ +language: php + +os: linux +dist: xenial + +php: + - 5.6 + - 7.0 + - 7.1 + - 7.2 + - 7.3 + - 7.4 + - hhvm + +jobs: + fast_finish: true + allow_failures: + - php: 7.3 + - php: 7.4 + - php: hhvm + +before_install: + - COMPOSER_MEMORY_LIMIT=-1 composer install --prefer-source --no-interaction --dev + +install: + - COMPOSER_MEMORY_LIMIT=-1 composer install --no-interaction + +script: + - ./vendor/bin/phpunit + +notifications: + email: + on_success: always + on_failure: always diff --git a/htdocs/includes/webklex/php-imap/CHANGELOG.md b/htdocs/includes/webklex/php-imap/CHANGELOG.md new file mode 100755 index 00000000000..a2ce640de53 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/CHANGELOG.md @@ -0,0 +1,577 @@ +# Changelog + +All notable changes to `webklex/php-imap` will be documented in this file. + +Updates should follow the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [UNRELEASED] +### Fixed +- NaN + +### Added +- NaN + +### Affected Classes +- NaN + +### Breaking changes +- NaN + +## [2.7.2] - 2021-09-27 +### Fixed +- Fixed problem with skipping last line of the response. #166 (thanks @szymekjanaczek) + +## [2.7.1] - 2021-09-08 +### Added +- Added `UID` as available search criteria #161 (thanks @szymekjanaczek) + +## [2.7.0] - 2021-09-04 +### Fixed +- Fixes handling of long header lines which are seperated by `\r\n\t` (thanks @Oliver-Holz) +- Fixes to line parsing with multiple addresses (thanks @Oliver-Holz) + +### Added +- Expose message folder path #154 (thanks @Magiczne) +- Adds mailparse_rfc822_parse_addresses integration (thanks @Oliver-Holz) +- Added moveManyMessages method (thanks @Magiczne) +- Added copyManyMessages method (thanks @Magiczne) + +### Affected Classes +- [Header::class](src/Header.php) +- [Message::class](src/Message.php) + +## [2.6.0] - 2021-08-20 +### Fixed +- POP3 fixes #151 (thanks @Korko) + +### Added +- Added imap 4 handling. #146 (thanks @szymekjanaczek) +- Added laravel's conditionable methods. #147 (thanks @szymekjanaczek) + +### Affected Classes +- [Query::class](src/Query/Query.php) +- [Client::class](src/Client.php) + +## [2.5.1] - 2021-06-19 +### Fixed +- Fix setting default mask from config #133 (thanks @shacky) +- Chunked fetch fails in case of less available mails than page size #114 +- Protocol::createStream() exception information fixed #137 +- Legacy methods (headers, content, flags) fixed #125 +- Legacy connection cycle fixed #124 (thanks @zssarkany) + +### Added +- Disable rfc822 header parsing via config option #115 + +## [2.5.0] - 2021-02-01 +### Fixed +- Attachment saving filename fixed +- Unnecessary parameter removed from `Client::getTimeout()` +- Missing encryption variable added - could have caused problems with unencrypted communications +- Prefer attachment filename attribute over name attribute #82 +- Missing connection settings added to `Folder:idle()` auto mode #89 +- Message move / copy expect a folder path #79 +- `Client::getFolder()` updated to circumvent special edge cases #79 +- Missing connection status checks added to various methods +- Unused default attribute `message_no` removed from `Message::class` + +### Added +- Dynamic Attribute access support added (e.g `$message->from[0]`) +- Message not found exception added #93 +- Chunked fetching support added `Query::chunked()`. Just in case you can't fetch all messages at once +- "Soft fail" support added +- Count method added to `Attribute:class` +- Convert an Attribute instance into a Carbon date object #95 + +### Affected Classes +- [Attachment::class](src/Attachment.php) +- [Attribute::class](src/Attribute.php) +- [Query::class](src/Query/Query.php) +- [Message::class](src/Message.php) +- [Client::class](src/Client.php) +- [Folder::class](src/Folder.php) + +### Breaking changes +- A new exception can occur if a message can't be fetched (`\Webklex\PHPIMAP\Exceptions\MessageNotFoundException::class`) +- `Message::move()` and `Message::copy()` no longer accept folder names as folder path +- A `Message::class` instance might no longer have a `message_no` attribute + +## [2.4.4] - 2021-01-22 +### Fixed +- Boundary detection simplified #90 +- Prevent potential body overwriting #90 +- CSV files are no longer regarded as plain body +- Boundary detection overhauled to support "related" and "alternative" multipart messages #90 #91 + +### Affected Classes +- [Structure::class](src/Structure.php) +- [Message::class](src/Message.php) +- [Header::class](src/Header.php) +- [Part::class](src/Part.php) + +## [2.4.3] - 2021-01-21 +### Fixed +- Attachment detection updated #82 #90 +- Timeout handling improved +- Additional utf-8 checks added to prevent decoding of unencoded values #76 + +### Added +- Auto reconnect option added to `Folder::idle()` #89 + +### Affected Classes +- [Folder::class](src/Folder.php) +- [Part::class](src/Part.php) +- [Client::class](src/Client.php) +- [Header::class](src/Header.php) + +## [2.4.2] - 2021-01-09 +### Fixed +- Attachment::save() return error 'A facade root has not been set' #87 +- Unused dependencies removed +- Fix PHP 8 error that changes null back in to an empty string. #88 (thanks @mennovanhout) +- Fix regex to be case insensitive #88 (thanks @mennovanhout) + +### Affected Classes +- [Attachment::class](src/Attachment.php) +- [Address::class](src/Address.php) +- [Attribute::class](src/Attribute.php) +- [Structure::class](src/Structure.php) + +## [2.4.1] - 2021-01-06 +### Fixed +- Debug line position fixed +- Handle incomplete address to string conversion #83 +- Configured message key gets overwritten by the first fetched message #84 + +### Affected Classes +- [Address::class](src/Address.php) +- [Query::class](src/Query/Query.php) + +## [2.4.0] - 2021-01-03 +### Fixed +- Get partial overview when `IMAP::ST_UID` is set #74 +- Unnecessary "'" removed from address names +- Folder referral typo fixed +- Legacy protocol fixed +- Treat message collection keys always as strings + +### Added +- Configurable supported default flags added +- Message attribute class added to unify value handling +- Address class added and integrated +- Alias `Message::attachments()` for `Message::getAttachments()` added +- Alias `Message::addFlag()` for `Message::setFlag()` added +- Alias `Message::removeFlag()` for `Message::unsetFlag()` added +- Alias `Message::flags()` for `Message::getFlags()` added +- New Exception `MessageFlagException::class` added +- New method `Message::setSequenceId($id)` added +- Optional Header attributizion option added + +### Affected Classes +- [Folder::class](src/Folder.php) +- [Header::class](src/Header.php) +- [Message::class](src/Message.php) +- [Address::class](src/Address.php) +- [Query::class](src/Query/Query.php) +- [Attribute::class](src/Attribute.php) + +### Breaking changes +- Stringified message headers are now separated by ", " instead of " ". +- All message header values such as subject, message_id, from, to, etc now consists of an `Àttribute::class` instance (should behave the same way as before, but might cause some problem in certain edge cases) +- The formal address object "from", "to", etc now consists of an `Address::class` instance (should behave the same way as before, but might cause some problem in certain edge cases) +- When fetching or manipulating message flags a `MessageFlagException::class` exception can be thrown if a runtime error occurs +- Learn more about the new `Attribute` class here: [www.php-imap.com/api/attribute](https://www.php-imap.com/api/attribute) +- Learn more about the new `Address` class here: [www.php-imap.com/api/address](https://www.php-imap.com/api/address) +- Folder attribute "referal" is now called "referral" + +## [2.3.1] - 2020-12-30 +### Fixed +- Missing RFC attributes added +- Set the message sequence when idling +- Missing UID commands added #64 + +### Added +- Get a message by its message number +- Get a message by its uid #72 #66 #63 + +### Affected Classes +- [Message::class](src/Message.php) +- [Folder::class](src/Folder.php) +- [Query::class](src/Query/Query.php) + +## [2.3.0] - 2020-12-21 +### Fixed +- Cert validation issue fixed +- Allow boundaries ending with a space or semicolon (thanks [@smartilabs](https://github.com/smartilabs)) +- Ignore IMAP DONE command response #57 +- Default `options.fetch` set to `IMAP::FT_PEEK` +- Address parsing fixed #60 +- Alternative rfc822 header parsing fixed #60 +- Parse more than one Received: header #61 +- Fetch folder overview fixed +- `Message::getTextBody()` fallback value fixed + +### Added +- Proxy support added +- Flexible disposition support added #58 +- New `options.message_key` option `uid` added +- Protocol UID support added +- Flexible sequence type support added + +### Affected Classes +- [Structure::class](src/Structure.php) +- [Query::class](src/Query/Query.php) +- [Client::class](src/Client.php) +- [Header::class](src/Header.php) +- [Folder::class](src/Folder.php) +- [Part::class](src/Part.php) + +### Breaking changes +- Depending on your configuration, your certificates actually get checked. Which can cause an aborted connection if the certificate can not be validated. +- Messages don't get flagged as read unless you are using your own custom config. +- All `Header::class` attribute keys are now in a snake_format and no longer minus-separated. +- `Message::getTextBody()` no longer returns false if no text body is present. `null` is returned instead. + +## [2.2.5] - 2020-12-11 +### Fixed +- Missing array decoder method added #51 (thanks [@lutchin](https://github.com/lutchin)) +- Additional checks added to prevent message from getting marked as seen #33 +- Boundary parsing improved #39 #36 (thanks [@AntonioDiPassio-AppSys](https://github.com/AntonioDiPassio-AppSys)) +- Idle operation updated #44 + +### Added +- Force a folder to be opened + +### Affected Classes +- [Header::class](src/Header.php) +- [Folder::class](src/Folder.php) +- [Query::class](src/Query/Query.php) +- [Message::class](src/Message.php) +- [Structure::class](src/Structure.php) + +## [2.2.4] - 2020-12-08 +### Fixed +- Search performance increased by fetching all headers, bodies and flags at once #42 +- Legacy protocol support updated +- Fix Query pagination. (#52 [@mikemiller891](https://github.com/mikemiller891)) + +### Added +- Missing message setter methods added +- `Folder::overview()` method added to fetch all headers of all messages in the current folder + +### Affected Classes +- [Message::class](src/Message.php) +- [Folder::class](src/Folder.php) +- [Query::class](src/Query/Query.php) +- [PaginatedCollection::class](src/Support/PaginatedCollection.php) + +## [2.2.3] - 2020-11-02 +### Fixed +- Text/Html body fetched as attachment if subtype is null #34 +- Potential header overwriting through header extensions #35 +- Prevent empty attachments #37 + +### Added +- Set fetch order during query #41 [@Max13](https://github.com/Max13) + +### Affected Classes +- [Message::class](src/Message.php) +- [Part::class](src/Part.php) +- [Header::class](src/Header.php) +- [Query::class](src/Query/Query.php) + + +## [2.2.2] - 2020-10-20 +### Fixed +- IMAP::FT_PEEK removing "Seen" flag issue fixed #33 + +### Affected Classes +- [Message::class](src/Message.php) + +## [2.2.1] - 2020-10-19 +### Fixed +- Header decoding problem fixed #31 + +### Added +- Search for messages by message-Id +- Search for messages by In-Reply-To +- Message threading added `Message::thread()` +- Default folder locations added + +### Affected Classes +- [Query::class](src/Query/Query.php) +- [Message::class](src/Message.php) +- [Header::class](src/Header.php) + + +## [2.2.0] - 2020-10-16 +### Fixed +- Prevent text bodies from being fetched as attachment #27 +- Missing variable check added to prevent exception while parsing an address [webklex/laravel-imap #356](https://github.com/Webklex/laravel-imap/issues/356) +- Missing variable check added to prevent exception while parsing a part subtype #27 +- Missing variable check added to prevent exception while parsing a part content-type [webklex/laravel-imap #356](https://github.com/Webklex/laravel-imap/issues/356) +- Mixed message header attribute `in_reply_to` "unified" to be always an array #26 +- Potential message moving / copying problem fixed #29 +- Move messages by using `Protocol::moveMessage()` instead of `Protocol::copyMessage()` and `Message::delete()` #29 + +### Added +- `Protocol::moveMessage()` method added #29 + +### Affected Classes +- [Message::class](src/Message.php) +- [Header::class](src/Header.php) +- [Part::class](src/Part.php) + +### Breaking changes +- Text bodies might no longer get fetched as attachment +- `Message::$in_reply_to` type changed from mixed to array + +## [2.1.13] - 2020-10-13 +### Fixed +- Boundary detection problem fixed (#28 [@DasTobbel](https://github.com/DasTobbel)) +- Content-Type detection problem fixed (#28 [@DasTobbel](https://github.com/DasTobbel)) + +### Affected Classes +- [Structure::class](src/Structure.php) + +## [2.1.12] - 2020-10-13 +### Fixed +- If content disposition is multiline, implode the array to a simple string (#25 [@DasTobbel](https://github.com/DasTobbel)) + +### Affected Classes +- [Part::class](src/Part.php) + +## [2.1.11] - 2020-10-13 +### Fixed +- Potential problematic prefixed white-spaces removed from header attributes + +### Added +- Expended `Client::getFolder($name, $deleimiter = null)` to accept either a folder name or path ([@DasTobbel](https://github.com/DasTobbel)) +- Special MS-Exchange header decoding support added + +### Affected Classes +- [Client::class](src/Client.php) +- [Header::class](src/Header.php) + +## [2.1.10] - 2020-10-09 +### Added +- `ClientManager::make()` method added to support undefined accounts + +### Affected Classes +- [ClientManager::class](src/ClientManager.php) + +## [2.1.9] - 2020-10-08 +### Fixed +- Fix inline attachments and embedded images (#22 [@dwalczyk](https://github.com/dwalczyk)) + +### Added +- Alternative attachment names support added (#20 [@oneFoldSoftware](https://github.com/oneFoldSoftware)) +- Fetch message content without leaving a "Seen" flag behind + +### Affected Classes +- [Attachment::class](src/Attachment.php) +- [Message::class](src/Message.php) +- [Part::class](src/Part.php) +- [Query::class](src/Query/Query.php) + +## [2.1.8] - 2020-10-08 +### Fixed +- Possible error during address decoding fixed (#16 [@Slauta](https://github.com/Slauta)) +- Flag event dispatching fixed #15 + +### Added +- Support multiple boundaries (#17, #19 [@dwalczyk](https://github.com/dwalczyk)) + +### Affected Classes +- [Structure::class](src/Structure.php) + +## [2.1.7] - 2020-10-03 +### Fixed +- Fixed `Query::paginate()` (#13 #14 by [@Max13](https://github.com/Max13)) + +### Affected Classes +- [Query::class](src/Query/Query.php) + +## [2.1.6] - 2020-10-02 +### Fixed +- `Message::getAttributes()` hasn't returned all parameters + +### Affected Classes +- [Message::class](src/Message.php) + +### Added +- Part number added to attachment +- `Client::getFolderByPath()` added (#12 by [@Max13](https://github.com/Max13)) +- `Client::getFolderByName()` added (#12 by [@Max13](https://github.com/Max13)) +- Throws exceptions if the authentication fails (#11 by [@Max13](https://github.com/Max13)) + +### Affected Classes +- [Client::class](src/Client.php) + +## [2.1.5] - 2020-09-30 +### Fixed +- Wrong message content property reference fixed (#10) + +## [2.1.4] - 2020-09-30 +### Fixed +- Fix header extension values +- Part header detection method changed (#10) + +### Affected Classes +- [Header::class](src/Header.php) +- [Part::class](src/Part.php) + +## [2.1.3] - 2020-09-29 +### Fixed +- Possible decoding problem fixed +- `Str::class` dependency removed from `Header::class` + +### Affected Classes +- [Header::class](src/Header.php) + +## [2.1.2] - 2020-09-28 +### Fixed +- Dependency problem in `Attachement::getExtension()` fixed (#9) + +### Affected Classes +- [Attachment::class](src/Attachment.php) + +## [2.1.1] - 2020-09-23 +### Fixed +- Missing default config parameter added + +### Added +- Default account config fallback added + +### Affected Classes +- [Client::class](src/Client.php) + +## [2.1.0] - 2020-09-22 +### Fixed +- Quota handling fixed + +### Added +- Event system and callbacks added + +### Affected Classes +- [Client::class](src/Client.php) +- [Folder::class](src/Folder.php) +- [Message::class](src/Message.php) + +## [2.0.1] - 2020-09-20 +### Fixed +- Carbon dependency fixed + +## [2.0.0] - 2020-09-20 +### Fixed +- Missing pagination item records fixed + +### Added +- php-imap module replaced by direct socket communication +- Legacy support added +- IDLE support added +- oAuth support added +- Charset detection method updated +- Decoding fallback charsets added + +### Affected Classes +- All + +## [1.4.5] - 2019-01-23 +### Fixed +- .csv attachement is not processed +- mail part structure property comparison changed to lowercase +- Replace helper functions for Laravel 6.0 #4 (@koenhoeijmakers) +- Date handling in Folder::appendMessage() fixed +- Carbon Exception Parse Data +- Convert sender name from non-utf8 to uf8 (@hwilok) +- Convert encoding of personal data struct + +### Added +- Path prefix option added to Client::getFolder() method +- Attachment size handling added +- Find messages by custom search criteria + +### Affected Classes +- [Query::class](src/Query/WhereQuery.php) +- [Mask::class](src/Support/Masks/Mask.php) +- [Attachment::class](src/Attachment.php) +- [Client::class](src/Client.php) +- [Folder::class](src/Folder.php) +- [Message::class](src/Message.php) + +## [1.4.2.1] - 2019-07-03 +### Fixed +- Error in Attachment::__construct #3 +- Examples added + +## [1.4.2] - 2019-07-02 +### Fixed +- Pagination count total bug #213 +- Changed internal message move and copy methods #210 +- Query::since() query returning empty response #215 +- Carbon Exception Parse Data #45 +- Reading a blank body (text / html) but only from this sender #203 +- Problem with Message::moveToFolder() and multiple moves #31 +- Problem with encoding conversion #203 +- Message null value attribute problem fixed +- Client connection path handling changed to be handled inside the calling method #31 +- iconv(): error suppressor for //IGNORE added #184 +- Typo Folder attribute fullName changed to full_name +- Query scope error fixed #153 +- Replace embedded image with URL #151 +- Fix sender name in non-latin emails sent from Gmail (#155) +- Fix broken non-latin characters in body in ASCII (us-ascii) charset #156 +- Message::getMessageId() returns wrong value #197 +- Message date validation extended #45 #192 +- Removed "-i" from "iso-8859-8-i" in Message::parseBody #146 + +### Added +- Message::getFolder() method +- Create a fast count method for queries #216 +- STARTTLS encryption alias added +- Mailbox fetching exception added #201 +- Message::moveToFolder() fetches new Message::class afterwards #31 +- Message structure accessor added #182 +- Shadow Imap const class added #188 +- Connectable "NOT" queries added +- Additional where methods added +- Message attribute handling changed +- Attachment attribute handling changed +- Message flag handling updated +- Message::getHTMLBody($callback) extended +- Masks added (take look at the examples for more information on masks) +- More examples added +- Query::paginate() method added +- Imap client timeout can be modified and read #186 +- Decoder config options added #175 +- Message search criteria "NOT" added #181 +- Invalid message date exception added +- Blade examples + +### Breaking changes +- Message::moveToFolder() returns either a Message::class instance or null and not a boolean +- Folder::fullName is now Folder::full_name +- Attachment::image_src might no longer work as expected - use Attachment::getImageSrc() instead + +### Affected Classes +- [Folder::class](src/Folder.php) +- [Client::class](src/Client.php) +- [Message::class](src/Message.php) +- [Attachment::class](src/Attachment.php) +- [Query::class](src/Query/Query.php) +- [WhereQuery::class](src/Query/WhereQuery.php) + +## 0.0.3 - 2018-12-02 +### Fixed +- Folder delimiter check added #137 +- Config setting not getting loaded +- Date parsing updated + +### Affected Classes +- [Folder::class](src/IMAP/Client.php) +- [Folder::class](src/IMAP/Message.php) + +## 0.0.1 - 2018-08-13 +### Added +- new php-imap package (fork from [webklex/laravel-imap](https://github.com/Webklex/laravel-imap)) diff --git a/htdocs/includes/webklex/php-imap/CODE_OF_CONDUCT.md b/htdocs/includes/webklex/php-imap/CODE_OF_CONDUCT.md new file mode 100644 index 00000000000..2ed07c83f5f --- /dev/null +++ b/htdocs/includes/webklex/php-imap/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at github@webklex.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/htdocs/includes/webklex/php-imap/LICENSE b/htdocs/includes/webklex/php-imap/LICENSE new file mode 100644 index 00000000000..6c13191e712 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 Webklex + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/htdocs/includes/webklex/php-imap/LICENSE.md b/htdocs/includes/webklex/php-imap/LICENSE.md new file mode 100644 index 00000000000..feae5f320dc --- /dev/null +++ b/htdocs/includes/webklex/php-imap/LICENSE.md @@ -0,0 +1,21 @@ +# The MIT License (MIT) + +Copyright (c) 2016 Malte Goldenbaum + +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in +> all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +> THE SOFTWARE. diff --git a/htdocs/includes/webklex/php-imap/README.md b/htdocs/includes/webklex/php-imap/README.md new file mode 100755 index 00000000000..65012298af2 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/README.md @@ -0,0 +1,158 @@ + +# IMAP Library for PHP + +[![Latest Version on Packagist][ico-version]][link-packagist] +[![Software License][ico-license]][link-license] +[![Build Status][ico-travis]][link-scrutinizer] +[![Total Downloads][ico-downloads]][link-downloads] +[![Hits][ico-hits]][link-hits] + + +## Description +PHP-IMAP is a wrapper for common IMAP communication without the need to have the php-imap module installed / enabled. +The protocol is completely integrated and therefore supports IMAP IDLE operation and the "new" oAuth authentication +process as well. +You can enable the `php-imap` module in order to handle edge cases, improve message decoding quality and is required if +you want to use legacy protocols such as pop3. + +Official documentation: [php-imap.com](https://www.php-imap.com/) + +Laravel wrapper: [webklex/laravel-imap](https://github.com/Webklex/laravel-imap) + + +## Table of Contents +- [Documentations](#documentations) +- [Basic usage example](#basic-usage-example) +- [Known issues](#known-issues) +- [Support](#support) +- [Features & pull requests](#features--pull-requests) +- [Security](#security) +- [Credits](#credits) +- [License](#license) + + +## Documentations +- Legacy (< v2.0.0): [legacy documentation](https://github.com/Webklex/php-imap/tree/1.4.5) +- Core documentation: [php-imap.com](https://www.php-imap.com/) + + +## Basic usage example +This is a basic example, which will echo out all Mails within all imap folders +and will move every message into INBOX.read. Please be aware that this should not be +tested in real life and is only meant to gives an impression on how things work. + +```php +use Webklex\PHPIMAP\ClientManager; + +$cm = new ClientManager('path/to/config/imap.php'); + +/** @var \Webklex\PHPIMAP\Client $client */ +$client = $cm->account('account_identifier'); + +//Connect to the IMAP Server +$client->connect(); + +//Get all Mailboxes +/** @var \Webklex\PHPIMAP\Support\FolderCollection $folders */ +$folders = $client->getFolders(); + +//Loop through every Mailbox +/** @var \Webklex\PHPIMAP\Folder $folder */ +foreach($folders as $folder){ + + //Get all Messages of the current Mailbox $folder + /** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */ + $messages = $folder->messages()->all()->get(); + + /** @var \Webklex\PHPIMAP\Message $message */ + foreach($messages as $message){ + echo $message->getSubject().'
'; + echo 'Attachments: '.$message->getAttachments()->count().'
'; + echo $message->getHTMLBody(); + + //Move the current Message to 'INBOX.read' + if($message->move('INBOX.read') == true){ + echo 'Message has ben moved'; + }else{ + echo 'Message could not be moved'; + } + } +} +``` + + +### Known issues +| Error | Solution | +| ------------------------------------------------------------------------- | ---------------------------------------------------------- | +| Kerberos error: No credentials cache file found (try running kinit) (...) | Uncomment "DISABLE_AUTHENTICATOR" inside your config and use the `legacy-imap` protocol | + + +## Support +If you encounter any problems or if you find a bug, please don't hesitate to create a new [issue](https://github.com/Webklex/php-imap/issues). +However please be aware that it might take some time to get an answer. +Off topic, rude or abusive issues will be deleted without any notice. + +If you need **commercial** support, feel free to send me a mail at github@webklex.com. + + +##### A little notice +If you write source code in your issue, please consider to format it correctly. This makes it so much nicer to read +and people are more likely to comment and help :) + +```php + +echo 'your php code...'; + +``` + +will turn into: +```php +echo 'your php code...'; +``` + + +## Features & pull requests +Everyone can contribute to this project. Every pull request will be considered but it can also happen to be declined. +To prevent unnecessary work, please consider to create a [feature issue](https://github.com/Webklex/php-imap/issues/new?template=feature_request.md) +first, if you're planning to do bigger changes. Of course you can also create a new [feature issue](https://github.com/Webklex/php-imap/issues/new?template=feature_request.md) +if you're just wishing a feature ;) + + +## Change log +Please see [CHANGELOG][link-changelog] for more information what has changed recently. + + +## Security +If you discover any security related issues, please email github@webklex.com instead of using the issue tracker. + + +## Credits +- [Webklex][link-author] +- [All Contributors][link-contributors] + + +## License +The MIT License (MIT). Please see [License File][link-license] for more information. + + +[ico-version]: https://img.shields.io/packagist/v/Webklex/php-imap.svg?style=flat-square +[ico-license]: https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square +[ico-travis]: https://img.shields.io/travis/Webklex/php-imap/master.svg?style=flat-square +[ico-scrutinizer]: https://img.shields.io/scrutinizer/coverage/g/Webklex/php-imap.svg?style=flat-square +[ico-code-quality]: https://img.shields.io/scrutinizer/g/Webklex/php-imap.svg?style=flat-square +[ico-downloads]: https://img.shields.io/packagist/dt/Webklex/php-imap.svg?style=flat-square +[ico-build]: https://img.shields.io/scrutinizer/build/g/Webklex/php-imap/master?style=flat-square +[ico-quality]: https://img.shields.io/scrutinizer/quality/g/Webklex/php-imap/master?style=flat-square +[ico-hits]: https://hits.webklex.com/svg/webklex/php-imap + +[link-packagist]: https://packagist.org/packages/Webklex/php-imap +[link-travis]: https://travis-ci.org/Webklex/php-imap +[link-scrutinizer]: https://scrutinizer-ci.com/g/Webklex/php-imap/code-structure +[link-code-quality]: https://scrutinizer-ci.com/g/Webklex/php-imap +[link-downloads]: https://packagist.org/packages/Webklex/php-imap +[link-author]: https://github.com/webklex +[link-contributors]: https://github.com/Webklex/php-imap/graphs/contributors +[link-license]: https://github.com/Webklex/php-imap/blob/master/LICENSE +[link-changelog]: https://github.com/Webklex/php-imap/blob/master/CHANGELOG.md +[link-jetbrains]: https://www.jetbrains.com +[link-hits]: https://hits.webklex.com diff --git a/htdocs/includes/webklex/php-imap/_config.yml b/htdocs/includes/webklex/php-imap/_config.yml new file mode 100644 index 00000000000..c4192631f25 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-cayman \ No newline at end of file diff --git a/htdocs/includes/webklex/php-imap/composer.json b/htdocs/includes/webklex/php-imap/composer.json new file mode 100644 index 00000000000..9bc3849a98f --- /dev/null +++ b/htdocs/includes/webklex/php-imap/composer.json @@ -0,0 +1,55 @@ +{ + "name": "webklex/php-imap", + "type": "library", + "description": "PHP IMAP client", + "keywords": [ + "webklex", + "imap", + "pop3", + "php-imap", + "mail" + ], + "homepage": "https://github.com/webklex/php-imap", + "license": "MIT", + "authors": [ + { + "name": "Malte Goldenbaum", + "email": "github@webklex.com", + "role": "Developer" + } + ], + "require": { + "php": ">=5.5.9", + "ext-openssl": "*", + "ext-json": "*", + "ext-mbstring": "*", + "ext-iconv": "*", + "ext-fileinfo": "*", + "nesbot/carbon": ">=1.0", + "symfony/http-foundation": ">=2.8.0", + "illuminate/pagination": ">=5.0.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "autoload": { + "psr-4": { + "Webklex\\PHPIMAP\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "Tests\\": "tests" + } + }, + "scripts": { + "test": "phpunit" + }, + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "minimum-stability": "dev", + "prefer-stable": true +} diff --git a/htdocs/includes/webklex/php-imap/examples/custom_attachment_mask.php b/htdocs/includes/webklex/php-imap/examples/custom_attachment_mask.php new file mode 100644 index 00000000000..32b7b91ef32 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/examples/custom_attachment_mask.php @@ -0,0 +1,56 @@ +id, $this->getMessage()->getUid(), $this->name]); + } + + /** + * Custom attachment saving method + * @return bool + */ + public function custom_save() { + $path = "foo".DIRECTORY_SEPARATOR."bar".DIRECTORY_SEPARATOR; + $filename = $this->token(); + + return file_put_contents($path.$filename, $this->getContent()) !== false; + } + +} + +/** @var \Webklex\PHPIMAP\Client $client */ +$cm = new \Webklex\PHPIMAP\ClientManager('path/to/config/imap.php'); +$client = $cm->account('default'); +$client->connect(); +$client->setDefaultAttachmentMask(CustomAttachmentMask::class); + +/** @var \Webklex\PHPIMAP\Folder $folder */ +$folder = $client->getFolder('INBOX'); + +/** @var \Webklex\PHPIMAP\Message $message */ +$message = $folder->query()->limit(1)->get()->first(); + +/** @var \Webklex\PHPIMAP\Attachment $attachment */ +$attachment = $message->getAttachments()->first(); + +/** @var CustomAttachmentMask $masked_attachment */ +$masked_attachment = $attachment->mask(); + +echo 'Token for uid ['.$masked_attachment->getMessage()->getUid().']: '.$masked_attachment->token(); + +$masked_attachment->custom_save(); \ No newline at end of file diff --git a/htdocs/includes/webklex/php-imap/examples/custom_message_mask.php b/htdocs/includes/webklex/php-imap/examples/custom_message_mask.php new file mode 100644 index 00000000000..25d05667623 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/examples/custom_message_mask.php @@ -0,0 +1,50 @@ +message_id, $this->uid, $this->message_no]); + } + + /** + * Get number of message attachments + * @return integer + */ + public function getAttachmentCount() { + return $this->getAttachments()->count(); + } + +} + +/** @var \Webklex\PHPIMAP\Client $client */ +$cm = new \Webklex\PHPIMAP\ClientManager('path/to/config/imap.php'); +$client = $cm->account('default'); +$client->connect(); + +/** @var \Webklex\PHPIMAP\Folder $folder */ +$folder = $client->getFolder('INBOX'); + +/** @var \Webklex\PHPIMAP\Message $message */ +$message = $folder->query()->limit(1)->get()->first(); + +/** @var CustomMessageMask $masked_message */ +$masked_message = $message->mask(CustomMessageMask::class); + +echo 'Token for uid ['.$masked_message->uid.']: '.$masked_message->token().' @atms:'.$masked_message->getAttachmentCount(); + +$masked_message->setFlag('seen'); + diff --git a/htdocs/includes/webklex/php-imap/examples/folder_structure.blade.php b/htdocs/includes/webklex/php-imap/examples/folder_structure.blade.php new file mode 100644 index 00000000000..a80dfb6cece --- /dev/null +++ b/htdocs/includes/webklex/php-imap/examples/folder_structure.blade.php @@ -0,0 +1,42 @@ + + + + + + + + + + count() > 0): ?> + + + + + + + + + + + + +
FolderUnread messages
name; ?>search()->unseen()->setFetchBody(false)->count(); ?>
No folders found
+ +links(); ?> \ No newline at end of file diff --git a/htdocs/includes/webklex/php-imap/examples/message_table.blade.php b/htdocs/includes/webklex/php-imap/examples/message_table.blade.php new file mode 100644 index 00000000000..c3bd7af8eb5 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/examples/message_table.blade.php @@ -0,0 +1,46 @@ + + + + + + + + + + + + count() > 0): ?> + + + + + + + + + + + + + + +
UIDSubjectFromAttachments
getUid(); ?>getSubject(); ?>getFrom()[0]->mail; ?>getAttachments()->count() > 0 ? 'yes' : 'no'; ?>
No messages found
+ +links(); ?> \ No newline at end of file diff --git a/htdocs/includes/webklex/php-imap/phpunit.xml b/htdocs/includes/webklex/php-imap/phpunit.xml new file mode 100644 index 00000000000..bfbb0b093c9 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/phpunit.xml @@ -0,0 +1,32 @@ + + + + + tests + + + + + src/ + + + + + + + + + + + + + \ No newline at end of file diff --git a/htdocs/includes/webklex/php-imap/src/Address.php b/htdocs/includes/webklex/php-imap/src/Address.php new file mode 100644 index 00000000000..644158dd18d --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/Address.php @@ -0,0 +1,90 @@ +personal = $object->personal; } + if (property_exists($object, "mailbox")){ $this->mailbox = $object->mailbox; } + if (property_exists($object, "host")){ $this->host = $object->host; } + if (property_exists($object, "mail")){ $this->mail = $object->mail; } + if (property_exists($object, "full")){ $this->full = $object->full; } + } + + + /** + * Return the stringified address + * + * @return string + */ + public function __toString() { + return $this->full ? $this->full : ""; + } + + /** + * Return the serialized address + * + * @return array + */ + public function __serialize(){ + return [ + "personal" => $this->personal, + "mailbox" => $this->mailbox, + "host" => $this->host, + "mail" => $this->mail, + "full" => $this->full, + ]; + } + + /** + * Convert instance to array + * + * @return array + */ + public function toArray(){ + return $this->__serialize(); + } + + /** + * Return the stringified attribute + * + * @return string + */ + public function toString(){ + return $this->__toString(); + } +} \ No newline at end of file diff --git a/htdocs/includes/webklex/php-imap/src/Attachment.php b/htdocs/includes/webklex/php-imap/src/Attachment.php new file mode 100755 index 00000000000..29c3d44268a --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/Attachment.php @@ -0,0 +1,344 @@ + null, + 'type' => null, + 'part_number' => 0, + 'content_type' => null, + 'id' => null, + 'name' => null, + 'disposition' => null, + 'img_src' => null, + 'size' => null, + ]; + + /** + * Default mask + * + * @var string $mask + */ + protected $mask = AttachmentMask::class; + + /** + * Attachment constructor. + * @param Message $oMessage + * @param Part $part + */ + public function __construct(Message $oMessage, Part $part) { + $this->config = ClientManager::get('options'); + + $this->oMessage = $oMessage; + $this->part = $part; + $this->part_number = $part->part_number; + + $default_mask = $this->oMessage->getClient()->getDefaultAttachmentMask(); + if($default_mask != null) { + $this->mask = $default_mask; + } + + $this->findType(); + $this->fetch(); + } + + /** + * Call dynamic attribute setter and getter methods + * @param string $method + * @param array $arguments + * + * @return mixed + * @throws MethodNotFoundException + */ + public function __call($method, $arguments) { + if(strtolower(substr($method, 0, 3)) === 'get') { + $name = Str::snake(substr($method, 3)); + + if(isset($this->attributes[$name])) { + return $this->attributes[$name]; + } + + return null; + }elseif (strtolower(substr($method, 0, 3)) === 'set') { + $name = Str::snake(substr($method, 3)); + + $this->attributes[$name] = array_pop($arguments); + + return $this->attributes[$name]; + } + + throw new MethodNotFoundException("Method ".self::class.'::'.$method.'() is not supported'); + } + + /** + * Magic setter + * @param $name + * @param $value + * + * @return mixed + */ + public function __set($name, $value) { + $this->attributes[$name] = $value; + + return $this->attributes[$name]; + } + + /** + * magic getter + * @param $name + * + * @return mixed|null + */ + public function __get($name) { + if(isset($this->attributes[$name])) { + return $this->attributes[$name]; + } + + return null; + } + + /** + * Determine the structure type + */ + protected function findType() { + switch ($this->part->type) { + case IMAP::ATTACHMENT_TYPE_MESSAGE: + $this->type = 'message'; + break; + case IMAP::ATTACHMENT_TYPE_APPLICATION: + $this->type = 'application'; + break; + case IMAP::ATTACHMENT_TYPE_AUDIO: + $this->type = 'audio'; + break; + case IMAP::ATTACHMENT_TYPE_IMAGE: + $this->type = 'image'; + break; + case IMAP::ATTACHMENT_TYPE_VIDEO: + $this->type = 'video'; + break; + case IMAP::ATTACHMENT_TYPE_MODEL: + $this->type = 'model'; + break; + case IMAP::ATTACHMENT_TYPE_TEXT: + $this->type = 'text'; + break; + case IMAP::ATTACHMENT_TYPE_MULTIPART: + $this->type = 'multipart'; + break; + default: + $this->type = 'other'; + break; + } + } + + /** + * Fetch the given attachment + */ + protected function fetch() { + + $content = $this->part->content; + + $this->content_type = $this->part->content_type; + $this->content = $this->oMessage->decodeString($content, $this->part->encoding); + + if (($id = $this->part->id) !== null) { + $this->id = str_replace(['<', '>'], '', $id); + } + + $this->size = $this->part->bytes; + $this->disposition = $this->part->disposition; + + if (($filename = $this->part->filename) !== null) { + $this->setName($filename); + } elseif (($name = $this->part->name) !== null) { + $this->setName($name); + }else { + $this->setName("undefined"); + } + + if (IMAP::ATTACHMENT_TYPE_MESSAGE == $this->part->type) { + if ($this->part->ifdescription) { + $this->setName($this->part->description); + } else { + $this->setName($this->part->subtype); + } + } + } + + /** + * Save the attachment content to your filesystem + * @param string $path + * @param string|null $filename + * + * @return boolean + */ + public function save($path, $filename = null) { + $filename = $filename ? $filename : $this->getName(); + + return file_put_contents($path.$filename, $this->getContent()) !== false; + } + + /** + * Set the attachment name and try to decode it + * @param $name + */ + public function setName($name) { + $decoder = $this->config['decoder']['attachment']; + if ($name !== null) { + if($decoder === 'utf-8' && extension_loaded('imap')) { + $this->name = \imap_utf8($name); + }else{ + $this->name = mb_decode_mimeheader($name); + } + } + } + + /** + * Get the attachment mime type + * + * @return string|null + */ + public function getMimeType(){ + return (new \finfo())->buffer($this->getContent(), FILEINFO_MIME_TYPE); + } + + /** + * Try to guess the attachment file extension + * + * @return string|null + */ + public function getExtension(){ + $deprecated_guesser = "\Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser"; + if (class_exists($deprecated_guesser) !== false){ + return $deprecated_guesser::getInstance()->guess($this->getMimeType()); + } + $guesser = "\Symfony\Component\Mime\MimeTypes"; + $extensions = $guesser::getDefault()->getExtensions($this->getMimeType()); + return isset($extensions[0]) ? $extensions[0] : null; + } + + /** + * Get all attributes + * + * @return array + */ + public function getAttributes(){ + return $this->attributes; + } + + /** + * @return Message + */ + public function getMessage(){ + return $this->oMessage; + } + + /** + * Set the default mask + * @param $mask + * + * @return $this + */ + public function setMask($mask){ + if(class_exists($mask)){ + $this->mask = $mask; + } + + return $this; + } + + /** + * Get the used default mask + * + * @return string + */ + public function getMask(){ + return $this->mask; + } + + /** + * Get a masked instance by providing a mask name + * @param string|null $mask + * + * @return mixed + * @throws MaskNotFoundException + */ + public function mask($mask = null){ + $mask = $mask !== null ? $mask : $this->mask; + if(class_exists($mask)){ + return new $mask($this); + } + + throw new MaskNotFoundException("Unknown mask provided: ".$mask); + } +} \ No newline at end of file diff --git a/htdocs/includes/webklex/php-imap/src/Attribute.php b/htdocs/includes/webklex/php-imap/src/Attribute.php new file mode 100644 index 00000000000..06dc6a7903d --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/Attribute.php @@ -0,0 +1,274 @@ +setName($name); + $this->add($value); + } + + + /** + * Return the stringified attribute + * + * @return string + */ + public function __toString() { + return implode(", ", $this->values); + } + + /** + * Return the stringified attribute + * + * @return string + */ + public function toString(){ + return $this->__toString(); + } + + /** + * Return the serialized attribute + * + * @return array + */ + public function __serialize(){ + return $this->values; + } + + /** + * Convert instance to array + * + * @return array + */ + public function toArray(){ + return $this->__serialize(); + } + + /** + * Convert first value to a date object + * + * @return Carbon|null + */ + public function toDate(){ + $date = $this->first(); + if ($date instanceof Carbon) return $date; + + return Carbon::parse($date); + } + + /** + * Determine if a value exists at an offset. + * + * @param mixed $key + * @return bool + */ + public function offsetExists($key) { + return array_key_exists($key, $this->values); + } + + /** + * Get a value at a given offset. + * + * @param mixed $key + * @return mixed + */ + public function offsetGet($key) { + return $this->values[$key]; + } + + /** + * Set the value at a given offset. + * + * @param mixed $key + * @param mixed $value + * @return void + */ + public function offsetSet($key, $value) { + if (is_null($key)) { + $this->values[] = $value; + } else { + $this->values[$key] = $value; + } + } + + /** + * Unset the value at a given offset. + * + * @param string $key + * @return void + */ + public function offsetUnset($key) { + unset($this->values[$key]); + } + + /** + * Add one or more values to the attribute + * @param array|mixed $value + * @param boolean $strict + * + * @return Attribute + */ + public function add($value, $strict = false) { + if (is_array($value)) { + return $this->merge($value, $strict); + }elseif ($value !== null) { + $this->attach($value, $strict); + } + + return $this; + } + + /** + * Merge a given array of values with the current values array + * @param array $values + * @param boolean $strict + * + * @return Attribute + */ + public function merge($values, $strict = false) { + if (is_array($values)) { + foreach ($values as $value) { + $this->attach($value, $strict); + } + } + + return $this; + } + + /** + * Check if the attribute contains the given value + * @param mixed $value + * + * @return bool + */ + public function contains($value) { + foreach ($this->values as $v) { + if ($v === $value) { + return true; + } + } + return false; + } + + /** + * Attach a given value to the current value array + * @param $value + * @param bool $strict + */ + public function attach($value, $strict = false) { + if ($strict === true) { + if ($this->contains($value) === false) { + $this->values[] = $value; + } + }else{ + $this->values[] = $value; + } + } + + /** + * Set the attribute name + * @param $name + * + * @return Attribute + */ + public function setName($name){ + $this->name = $name; + + return $this; + } + + /** + * Get the attribute name + * + * @return string + */ + public function getName(){ + return $this->name; + } + + /** + * Get all values + * + * @return array + */ + public function get(){ + return $this->values; + } + + /** + * Alias method for self::get() + * + * @return array + */ + public function all(){ + return $this->get(); + } + + /** + * Get the first value if possible + * + * @return mixed|null + */ + public function first(){ + if ($this->offsetExists(0)) { + return $this->values[0]; + } + return null; + } + + /** + * Get the last value if possible + * + * @return mixed|null + */ + public function last(){ + if (($cnt = $this->count()) > 0) { + return $this->values[$cnt - 1]; + } + return null; + } + + /** + * Get the number of values + * + * @return int + */ + public function count(){ + return count($this->values); + } +} \ No newline at end of file diff --git a/htdocs/includes/webklex/php-imap/src/Client.php b/htdocs/includes/webklex/php-imap/src/Client.php new file mode 100755 index 00000000000..1ac56467b70 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/Client.php @@ -0,0 +1,669 @@ + null, + 'request_fulluri' => false, + 'username' => null, + 'password' => null, + ]; + + /** + * Connection timeout + * @var int $timeout + */ + public $timeout; + + /** + * Account username/ + * + * @var mixed + */ + public $username; + + /** + * Account password. + * + * @var string + */ + public $password; + + /** + * Account authentication method. + * + * @var string + */ + public $authentication; + + /** + * Active folder path. + * + * @var string + */ + protected $active_folder = null; + + /** + * Default message mask + * + * @var string $default_message_mask + */ + protected $default_message_mask = MessageMask::class; + + /** + * Default attachment mask + * + * @var string $default_attachment_mask + */ + protected $default_attachment_mask = AttachmentMask::class; + + /** + * Used default account values + * + * @var array $default_account_config + */ + protected $default_account_config = [ + 'host' => 'localhost', + 'port' => 993, + 'protocol' => 'imap', + 'encryption' => 'ssl', + 'validate_cert' => true, + 'username' => '', + 'password' => '', + 'authentication' => null, + 'proxy' => [ + 'socket' => null, + 'request_fulluri' => false, + 'username' => null, + 'password' => null, + ], + "timeout" => 30 + ]; + + /** + * Client constructor. + * @param array $config + * + * @throws MaskNotFoundException + */ + public function __construct($config = []) { + $this->setConfig($config); + $this->setMaskFromConfig($config); + $this->setEventsFromConfig($config); + } + + /** + * Client destructor + */ + public function __destruct() { + $this->disconnect(); + } + + /** + * Set the Client configuration + * @param array $config + * + * @return self + */ + public function setConfig(array $config) { + $default_account = ClientManager::get('default'); + $default_config = ClientManager::get("accounts.$default_account"); + + foreach ($this->default_account_config as $key => $value) { + $this->setAccountConfig($key, $config, $default_config); + } + + return $this; + } + + /** + * Set a specific account config + * @param string $key + * @param array $config + * @param array $default_config + */ + private function setAccountConfig($key, $config, $default_config){ + $value = $this->default_account_config[$key]; + if(isset($config[$key])) { + $value = $config[$key]; + }elseif(isset($default_config[$key])) { + $value = $default_config[$key]; + } + $this->$key = $value; + } + + /** + * Look for a possible events in any available config + * @param $config + */ + protected function setEventsFromConfig($config) { + $this->events = ClientManager::get("events"); + if(isset($config['events'])){ + foreach($config['events'] as $section => $events) { + $this->events[$section] = array_merge($this->events[$section], $events); + } + } + } + + /** + * Look for a possible mask in any available config + * @param $config + * + * @throws MaskNotFoundException + */ + protected function setMaskFromConfig($config) { + $default_config = ClientManager::get("masks"); + + if(isset($config['masks'])){ + if(isset($config['masks']['message'])) { + if(class_exists($config['masks']['message'])) { + $this->default_message_mask = $config['masks']['message']; + }else{ + throw new MaskNotFoundException("Unknown mask provided: ".$config['masks']['message']); + } + }else{ + if(class_exists($default_config['message'])) { + $this->default_message_mask = $default_config['message']; + }else{ + throw new MaskNotFoundException("Unknown mask provided: ".$default_config['message']); + } + } + if(isset($config['masks']['attachment'])) { + if(class_exists($config['masks']['attachment'])) { + $this->default_attachment_mask = $config['masks']['attachment']; + }else{ + throw new MaskNotFoundException("Unknown mask provided: ".$config['masks']['attachment']); + } + }else{ + if(class_exists($default_config['attachment'])) { + $this->default_attachment_mask = $default_config['attachment']; + }else{ + throw new MaskNotFoundException("Unknown mask provided: ".$default_config['attachment']); + } + } + }else{ + if(class_exists($default_config['message'])) { + $this->default_message_mask = $default_config['message']; + }else{ + throw new MaskNotFoundException("Unknown mask provided: ".$default_config['message']); + } + + if(class_exists($default_config['attachment'])) { + $this->default_attachment_mask = $default_config['attachment']; + }else{ + throw new MaskNotFoundException("Unknown mask provided: ".$default_config['attachment']); + } + } + + } + + /** + * Get the current imap resource + * + * @return bool|Protocol|ProtocolInterface + * @throws ConnectionFailedException + */ + public function getConnection() { + $this->checkConnection(); + return $this->connection; + } + + /** + * Determine if connection was established. + * + * @return bool + */ + public function isConnected() { + return $this->connection ? $this->connection->connected() : false; + } + + /** + * Determine if connection was established and connect if not. + * + * @throws ConnectionFailedException + */ + public function checkConnection() { + if (!$this->isConnected()) { + $this->connect(); + } + } + + /** + * Force a reconnect + * + * @throws ConnectionFailedException + */ + public function reconnect() { + if ($this->isConnected()) { + $this->disconnect(); + } + $this->connect(); + } + + /** + * Connect to server. + * + * @return $this + * @throws ConnectionFailedException + */ + public function connect() { + $this->disconnect(); + $protocol = strtolower($this->protocol); + + if (in_array($protocol, ['imap', 'imap4', 'imap4rev1'])) { + $this->connection = new ImapProtocol($this->validate_cert, $this->encryption); + $this->connection->setConnectionTimeout($this->timeout); + $this->connection->setProxy($this->proxy); + }else{ + if (extension_loaded('imap') === false) { + throw new ConnectionFailedException("connection setup failed", 0, new ProtocolNotSupportedException($protocol." is an unsupported protocol")); + } + $this->connection = new LegacyProtocol($this->validate_cert, $this->encryption); + if (strpos($protocol, "legacy-") === 0) { + $protocol = substr($protocol, 7); + } + $this->connection->setProtocol($protocol); + } + + try { + $this->connection->connect($this->host, $this->port); + } catch (ErrorException $e) { + throw new ConnectionFailedException("connection setup failed", 0, $e); + } catch (Exceptions\RuntimeException $e) { + throw new ConnectionFailedException("connection setup failed", 0, $e); + } + $this->authenticate(); + + return $this; + } + + /** + * Authenticate the current session + * + * @throws ConnectionFailedException + */ + protected function authenticate() { + try { + if ($this->authentication == "oauth") { + if (!$this->connection->authenticate($this->username, $this->password)) { + throw new AuthFailedException(); + } + } elseif (!$this->connection->login($this->username, $this->password)) { + throw new AuthFailedException(); + } + } catch (AuthFailedException $e) { + throw new ConnectionFailedException("connection setup failed", 0, $e); + } + } + + /** + * Disconnect from server. + * + * @return $this + */ + public function disconnect() { + if ($this->isConnected() && $this->connection !== false) { + $this->connection->logout(); + } + $this->active_folder = null; + + return $this; + } + + /** + * Get a folder instance by a folder name + * @param string $folder_name + * @param string|bool|null $delimiter + * + * @return mixed + * @throws ConnectionFailedException + * @throws FolderFetchingException + * @throws Exceptions\RuntimeException + */ + public function getFolder($folder_name, $delimiter = null) { + if ($delimiter !== false && $delimiter !== null) { + return $this->getFolderByPath($folder_name); + } + + // Set delimiter to false to force selection via getFolderByName (maybe useful for uncommon folder names) + $delimiter = is_null($delimiter) ? ClientManager::get('options.delimiter', "/") : $delimiter; + if (strpos($folder_name, (string)$delimiter) !== false) { + return $this->getFolderByPath($folder_name); + } + + return $this->getFolderByName($folder_name); + } + + /** + * Get a folder instance by a folder name + * @param $folder_name + * + * @return mixed + * @throws ConnectionFailedException + * @throws FolderFetchingException + * @throws Exceptions\RuntimeException + */ + public function getFolderByName($folder_name) { + return $this->getFolders(false)->where("name", $folder_name)->first(); + } + + /** + * Get a folder instance by a folder path + * @param $folder_path + * + * @return mixed + * @throws ConnectionFailedException + * @throws FolderFetchingException + * @throws Exceptions\RuntimeException + */ + public function getFolderByPath($folder_path) { + return $this->getFolders(false)->where("path", $folder_path)->first(); + } + + /** + * Get folders list. + * If hierarchical order is set to true, it will make a tree of folders, otherwise it will return flat array. + * + * @param boolean $hierarchical + * @param string|null $parent_folder + * + * @return FolderCollection + * @throws ConnectionFailedException + * @throws FolderFetchingException + * @throws Exceptions\RuntimeException + */ + public function getFolders($hierarchical = true, $parent_folder = null) { + $this->checkConnection(); + $folders = FolderCollection::make([]); + + $pattern = $parent_folder.($hierarchical ? '%' : '*'); + $items = $this->connection->folders('', $pattern); + + if(is_array($items)){ + foreach ($items as $folder_name => $item) { + $folder = new Folder($this, $folder_name, $item["delimiter"], $item["flags"]); + + if ($hierarchical && $folder->hasChildren()) { + $pattern = $folder->full_name.$folder->delimiter.'%'; + + $children = $this->getFolders(true, $pattern); + $folder->setChildren($children); + } + + $folders->push($folder); + } + + return $folders; + }else{ + throw new FolderFetchingException("failed to fetch any folders"); + } + } + + /** + * Open a given folder. + * @param string $folder_path + * @param boolean $force_select + * + * @return mixed + * @throws ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + public function openFolder($folder_path, $force_select = false) { + if ($this->active_folder == $folder_path && $this->isConnected() && $force_select === false) { + return true; + } + $this->checkConnection(); + $this->active_folder = $folder_path; + return $this->connection->selectFolder($folder_path); + } + + /** + * Create a new Folder + * @param string $folder + * @param boolean $expunge + * + * @return bool + * @throws ConnectionFailedException + * @throws FolderFetchingException + * @throws Exceptions\EventNotFoundException + * @throws Exceptions\RuntimeException + */ + public function createFolder($folder, $expunge = true) { + $this->checkConnection(); + $status = $this->connection->createFolder($folder); + + if($expunge) $this->expunge(); + + $folder = $this->getFolder($folder); + if($status && $folder) { + $event = $this->getEvent("folder", "new"); + $event::dispatch($folder); + } + + return $folder; + } + + /** + * Check a given folder + * @param $folder + * + * @return false|object + * @throws ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + public function checkFolder($folder) { + $this->checkConnection(); + return $this->connection->examineFolder($folder); + } + + /** + * Get the current active folder + * + * @return string + */ + public function getFolderPath(){ + return $this->active_folder; + } + + /** + * Retrieve the quota level settings, and usage statics per mailbox + * + * @return array + * @throws ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + public function getQuota() { + $this->checkConnection(); + return $this->connection->getQuota($this->username); + } + + /** + * Retrieve the quota settings per user + * @param string $quota_root + * + * @return array + * @throws ConnectionFailedException + */ + public function getQuotaRoot($quota_root = 'INBOX') { + $this->checkConnection(); + return $this->connection->getQuotaRoot($quota_root); + } + + /** + * Delete all messages marked for deletion + * + * @return bool + * @throws ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + public function expunge() { + $this->checkConnection(); + return $this->connection->expunge(); + } + + /** + * Set the connection timeout + * @param integer $timeout + * + * @return Protocol + * @throws ConnectionFailedException + */ + public function setTimeout($timeout) { + $this->checkConnection(); + return $this->connection->setConnectionTimeout($timeout); + } + + /** + * Get the connection timeout + * + * @return int + * @throws ConnectionFailedException + */ + public function getTimeout(){ + $this->checkConnection(); + return $this->connection->getConnectionTimeout(); + } + + /** + * Get the default message mask + * + * @return string + */ + public function getDefaultMessageMask(){ + return $this->default_message_mask; + } + + /** + * Get the default events for a given section + * @param $section + * + * @return array + */ + public function getDefaultEvents($section){ + return $this->events[$section]; + } + + /** + * Set the default message mask + * @param $mask + * + * @return $this + * @throws MaskNotFoundException + */ + public function setDefaultMessageMask($mask) { + if(class_exists($mask)) { + $this->default_message_mask = $mask; + + return $this; + } + + throw new MaskNotFoundException("Unknown mask provided: ".$mask); + } + + /** + * Get the default attachment mask + * + * @return string + */ + public function getDefaultAttachmentMask(){ + return $this->default_attachment_mask; + } + + /** + * Set the default attachment mask + * @param $mask + * + * @return $this + * @throws MaskNotFoundException + */ + public function setDefaultAttachmentMask($mask) { + if(class_exists($mask)) { + $this->default_attachment_mask = $mask; + + return $this; + } + + throw new MaskNotFoundException("Unknown mask provided: ".$mask); + } +} diff --git a/htdocs/includes/webklex/php-imap/src/ClientManager.php b/htdocs/includes/webklex/php-imap/src/ClientManager.php new file mode 100644 index 00000000000..3daf9f83f76 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/ClientManager.php @@ -0,0 +1,262 @@ +setConfig($config); + } + + /** + * Dynamically pass calls to the default account. + * @param string $method + * @param array $parameters + * + * @return mixed + * @throws Exceptions\MaskNotFoundException + */ + public function __call($method, $parameters) { + $callable = [$this->account(), $method]; + + return call_user_func_array($callable, $parameters); + } + + /** + * Safely create a new client instance which is not listed in accounts + * @param array $config + * + * @return Client + * @throws Exceptions\MaskNotFoundException + */ + public function make($config) { + return new Client($config); + } + + /** + * Get a dotted config parameter + * @param string $key + * @param null $default + * + * @return mixed|null + */ + public static function get($key, $default = null) { + $parts = explode('.', $key); + $value = null; + foreach($parts as $part) { + if($value === null) { + if(isset(self::$config[$part])) { + $value = self::$config[$part]; + }else{ + break; + } + }else{ + if(isset($value[$part])) { + $value = $value[$part]; + }else{ + break; + } + } + } + + return $value === null ? $default : $value; + } + + /** + * Resolve a account instance. + * @param string $name + * + * @return Client + * @throws Exceptions\MaskNotFoundException + */ + public function account($name = null) { + $name = $name ?: $this->getDefaultAccount(); + + // If the connection has not been resolved yet we will resolve it now as all + // of the connections are resolved when they are actually needed so we do + // not make any unnecessary connection to the various queue end-points. + if (!isset($this->accounts[$name])) { + $this->accounts[$name] = $this->resolve($name); + } + + return $this->accounts[$name]; + } + + /** + * Resolve a account. + * + * @param string $name + * + * @return Client + * @throws Exceptions\MaskNotFoundException + */ + protected function resolve($name) { + $config = $this->getClientConfig($name); + + return new Client($config); + } + + /** + * Get the account configuration. + * @param string $name + * + * @return array + */ + protected function getClientConfig($name) { + if ($name === null || $name === 'null') { + return ['driver' => 'null']; + } + + return self::$config["accounts"][$name]; + } + + /** + * Get the name of the default account. + * + * @return string + */ + public function getDefaultAccount() { + return self::$config['default']; + } + + /** + * Set the name of the default account. + * @param string $name + * + * @return void + */ + public function setDefaultAccount($name) { + self::$config['default'] = $name; + } + + + /** + * Merge the vendor settings with the local config + * + * The default account identifier will be used as default for any missing account parameters. + * If however the default account is missing a parameter the package default account parameter will be used. + * This can be disabled by setting imap.default in your config file to 'false' + * + * @param array|string $config + * + * @return $this + */ + public function setConfig($config) { + + if(is_array($config) === false) { + $config = require $config; + } + + $config_key = 'imap'; + $path = __DIR__.'/config/'.$config_key.'.php'; + + $vendor_config = require $path; + $config = $this->array_merge_recursive_distinct($vendor_config, $config); + + if(is_array($config)){ + if(isset($config['default'])){ + if(isset($config['accounts']) && $config['default'] != false){ + + $default_config = $vendor_config['accounts']['default']; + if(isset($config['accounts'][$config['default']])){ + $default_config = array_merge($default_config, $config['accounts'][$config['default']]); + } + + if(is_array($config['accounts'])){ + foreach($config['accounts'] as $account_key => $account){ + $config['accounts'][$account_key] = array_merge($default_config, $account); + } + } + } + } + } + + self::$config = $config; + + return $this; + } + + /** + * Marge arrays recursively and distinct + * + * Merges any number of arrays / parameters recursively, replacing + * entries with string keys with values from latter arrays. + * If the entry or the next value to be assigned is an array, then it + * automatically treats both arguments as an array. + * Numeric entries are appended, not replaced, but only if they are + * unique + * + * @param array $array1 Initial array to merge. + * @param array ... Variable list of arrays to recursively merge. + * + * @return array|mixed + * + * @link http://www.php.net/manual/en/function.array-merge-recursive.php#96201 + * @author Mark Roduner + */ + private function array_merge_recursive_distinct() { + + $arrays = func_get_args(); + $base = array_shift($arrays); + + if(!is_array($base)) $base = empty($base) ? array() : array($base); + + foreach($arrays as $append) { + + if(!is_array($append)) $append = array($append); + + foreach($append as $key => $value) { + + if(!array_key_exists($key, $base) and !is_numeric($key)) { + $base[$key] = $append[$key]; + continue; + } + + if(is_array($value) or is_array($base[$key])) { + $base[$key] = $this->array_merge_recursive_distinct($base[$key], $append[$key]); + } else if(is_numeric($key)) { + if(!in_array($value, $base)) $base[] = $value; + } else { + $base[$key] = $value; + } + + } + + } + + return $base; + } +} \ No newline at end of file diff --git a/htdocs/includes/webklex/php-imap/src/Connection/Protocols/ImapProtocol.php b/htdocs/includes/webklex/php-imap/src/Connection/Protocols/ImapProtocol.php new file mode 100644 index 00000000000..99da29d3c3a --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/Connection/Protocols/ImapProtocol.php @@ -0,0 +1,1074 @@ +setCertValidation($cert_validation); + $this->encryption = $encryption; + } + + /** + * Public destructor + */ + public function __destruct() { + $this->logout(); + } + + /** + * Open connection to IMAP server + * @param string $host hostname or IP address of IMAP server + * @param int|null $port of IMAP server, default is 143 and 993 for ssl + * + * @throws ConnectionFailedException + */ + public function connect($host, $port = null) { + $transport = 'tcp'; + $encryption = ""; + + if ($this->encryption) { + $encryption = strtolower($this->encryption); + if ($encryption == "ssl") { + $transport = 'ssl'; + $port = $port === null ? 993 : $port; + } + } + $port = $port === null ? 143 : $port; + try { + $this->stream = $this->createStream($transport, $host, $port, $this->connection_timeout); + if (!$this->assumedNextLine('* OK')) { + throw new ConnectionFailedException('connection refused'); + } + if ($encryption == "tls") { + $this->enableTls(); + } + } catch (Exception $e) { + throw new ConnectionFailedException('connection failed', 0, $e); + } + } + + /** + * Enable tls on the current connection + * + * @throws ConnectionFailedException + * @throws RuntimeException + */ + protected function enableTls(){ + $response = $this->requestAndResponse('STARTTLS'); + $result = $response && stream_socket_enable_crypto($this->stream, true, $this->getCryptoMethod()); + if (!$result) { + throw new ConnectionFailedException('failed to enable TLS'); + } + } + + /** + * Get the next line from stream + * + * @return string next line + * @throws RuntimeException + */ + public function nextLine() { + $line = fgets($this->stream); + + if ($line === false) { + throw new RuntimeException('failed to read - connection closed?'); + } + + return $line; + } + + /** + * Get the next line and check if it starts with a given string + * @param string $start + * + * @return bool + * @throws RuntimeException + */ + protected function assumedNextLine($start) { + $line = $this->nextLine(); + return strpos($line, $start) === 0; + } + + /** + * Get the next line and split the tag + * @param string $tag reference tag + * + * @return string next line + * @throws RuntimeException + */ + protected function nextTaggedLine(&$tag) { + $line = $this->nextLine(); + list($tag, $line) = explode(' ', $line, 2); + + return $line; + } + + /** + * Split a given line in values. A value is literal of any form or a list + * @param string $line + * + * @return array + * @throws RuntimeException + */ + protected function decodeLine($line) { + $tokens = []; + $stack = []; + + // replace any trailing including spaces with a single space + $line = rtrim($line) . ' '; + while (($pos = strpos($line, ' ')) !== false) { + $token = substr($line, 0, $pos); + if (!strlen($token)) { + continue; + } + while ($token[0] == '(') { + array_push($stack, $tokens); + $tokens = []; + $token = substr($token, 1); + } + if ($token[0] == '"') { + if (preg_match('%^\(*"((.|\\\\|\\")*?)" *%', $line, $matches)) { + $tokens[] = $matches[1]; + $line = substr($line, strlen($matches[0])); + continue; + } + } + if ($token[0] == '{') { + $endPos = strpos($token, '}'); + $chars = substr($token, 1, $endPos - 1); + if (is_numeric($chars)) { + $token = ''; + while (strlen($token) < $chars) { + $token .= $this->nextLine(); + } + $line = ''; + if (strlen($token) > $chars) { + $line = substr($token, $chars); + $token = substr($token, 0, $chars); + } else { + $line .= $this->nextLine(); + } + $tokens[] = $token; + $line = trim($line) . ' '; + continue; + } + } + if ($stack && $token[strlen($token) - 1] == ')') { + // closing braces are not separated by spaces, so we need to count them + $braces = strlen($token); + $token = rtrim($token, ')'); + // only count braces if more than one + $braces -= strlen($token) + 1; + // only add if token had more than just closing braces + if (rtrim($token) != '') { + $tokens[] = rtrim($token); + } + $token = $tokens; + $tokens = array_pop($stack); + // special handline if more than one closing brace + while ($braces-- > 0) { + $tokens[] = $token; + $token = $tokens; + $tokens = array_pop($stack); + } + } + $tokens[] = $token; + $line = substr($line, $pos + 1); + } + + // maybe the server forgot to send some closing braces + while ($stack) { + $child = $tokens; + $tokens = array_pop($stack); + $tokens[] = $child; + } + + return $tokens; + } + + /** + * Read abd decode a response "line" + * @param array|string $tokens to decode + * @param string $wantedTag targeted tag + * @param bool $dontParse if true only the unparsed line is returned in $tokens + * + * @return bool + * @throws RuntimeException + */ + public function readLine(&$tokens = [], $wantedTag = '*', $dontParse = false) { + $line = $this->nextTaggedLine($tag); // get next tag + if (!$dontParse) { + $tokens = $this->decodeLine($line); + } else { + $tokens = $line; + } + if ($this->debug) echo "<< ".$line."\n"; + + // if tag is wanted tag we might be at the end of a multiline response + return $tag == $wantedTag; + } + + /** + * Read all lines of response until given tag is found + * @param string $tag request tag + * @param bool $dontParse if true every line is returned unparsed instead of the decoded tokens + * + * @return void|null|bool|array tokens if success, false if error, null if bad request + * @throws RuntimeException + */ + public function readResponse($tag, $dontParse = false) { + $lines = []; + $tokens = null; // define $tokens variable before first use + do { + $readAll = $this->readLine($tokens, $tag, $dontParse); + $lines[] = $tokens; + } while (!$readAll); + + if ($dontParse) { + // First two chars are still needed for the response code + $tokens = [substr($tokens, 0, 2)]; + } + + // last line has response code + if ($tokens[0] == 'OK') { + return $lines ? $lines : true; + } elseif ($tokens[0] == 'NO') { + return false; + } + + return; + } + + /** + * Send a new request + * @param string $command + * @param array $tokens additional parameters to command, use escapeString() to prepare + * @param string $tag provide a tag otherwise an autogenerated is returned + * + * @throws RuntimeException + */ + public function sendRequest($command, $tokens = [], &$tag = null) { + if (!$tag) { + $this->noun++; + $tag = 'TAG' . $this->noun; + } + + $line = $tag . ' ' . $command; + + foreach ($tokens as $token) { + if (is_array($token)) { + if (fwrite($this->stream, $line . ' ' . $token[0] . "\r\n") === false) { + throw new RuntimeException('failed to write - connection closed?'); + } + if (!$this->assumedNextLine('+ ')) { + throw new RuntimeException('failed to send literal string'); + } + $line = $token[1]; + } else { + $line .= ' ' . $token; + } + } + if ($this->debug) echo ">> ".$line."\n"; + + if (fwrite($this->stream, $line . "\r\n") === false) { + throw new RuntimeException('failed to write - connection closed?'); + } + } + + /** + * Send a request and get response at once + * @param string $command + * @param array $tokens parameters as in sendRequest() + * @param bool $dontParse if true unparsed lines are returned instead of tokens + * + * @return void|null|bool|array response as in readResponse() + * @throws RuntimeException + */ + public function requestAndResponse($command, $tokens = [], $dontParse = false) { + $this->sendRequest($command, $tokens, $tag); + + return $this->readResponse($tag, $dontParse); + } + + /** + * Escape one or more literals i.e. for sendRequest + * @param string|array $string the literal/-s + * + * @return string|array escape literals, literals with newline ar returned + * as array('{size}', 'string'); + */ + public function escapeString($string) { + if (func_num_args() < 2) { + if (strpos($string, "\n") !== false) { + return ['{' . strlen($string) . '}', $string]; + } else { + return '"' . str_replace(['\\', '"'], ['\\\\', '\\"'], $string) . '"'; + } + } + $result = []; + foreach (func_get_args() as $string) { + $result[] = $this->escapeString($string); + } + return $result; + } + + /** + * Escape a list with literals or lists + * @param array $list list with literals or lists as PHP array + * + * @return string escaped list for imap + */ + public function escapeList($list) { + $result = []; + foreach ($list as $v) { + if (!is_array($v)) { + $result[] = $v; + continue; + } + $result[] = $this->escapeList($v); + } + return '(' . implode(' ', $result) . ')'; + } + + /** + * Login to a new session. + * @param string $user username + * @param string $password password + * + * @return bool|mixed + * @throws AuthFailedException + */ + public function login($user, $password) { + try { + return $this->requestAndResponse('LOGIN', $this->escapeString($user, $password), true); + } catch (RuntimeException $e) { + throw new AuthFailedException("failed to authenticate", 0, $e); + } + } + + /** + * Authenticate your current IMAP session. + * @param string $user username + * @param string $token access token + * + * @return bool + * @throws AuthFailedException + */ + public function authenticate($user, $token) { + try { + $authenticateParams = ['XOAUTH2', base64_encode("user=$user\1auth=Bearer $token\1\1")]; + $this->sendRequest('AUTHENTICATE', $authenticateParams); + + while (true) { + $response = ""; + $is_plus = $this->readLine($response, '+', true); + if ($is_plus) { + // try to log the challenge somewhere where it can be found + error_log("got an extra server challenge: $response"); + // respond with an empty response. + $this->sendRequest(''); + } else { + if (preg_match('/^NO /i', $response) || + preg_match('/^BAD /i', $response)) { + error_log("got failure response: $response"); + return false; + } else if (preg_match("/^OK /i", $response)) { + return true; + } + } + } + } catch (RuntimeException $e) { + throw new AuthFailedException("failed to authenticate", 0, $e); + } + return false; + } + + /** + * Logout of imap server + * + * @return bool success + */ + public function logout() { + $result = false; + if ($this->stream) { + try { + $result = $this->requestAndResponse('LOGOUT', [], true); + } catch (Exception $e) {} + fclose($this->stream); + $this->stream = null; + } + return $result; + } + + /** + * Check if the current session is connected + * + * @return bool + */ + public function connected(){ + return (boolean) $this->stream; + } + + /** + * Get an array of available capabilities + * + * @return array list of capabilities + * @throws RuntimeException + */ + public function getCapabilities() { + $response = $this->requestAndResponse('CAPABILITY'); + + if (!$response) return []; + + $capabilities = []; + foreach ($response as $line) { + $capabilities = array_merge($capabilities, $line); + } + return $capabilities; + } + + /** + * Examine and select have the same response. + * @param string $command can be 'EXAMINE' or 'SELECT' + * @param string $folder target folder + * + * @return bool|array + * @throws RuntimeException + */ + public function examineOrSelect($command = 'EXAMINE', $folder = 'INBOX') { + $this->sendRequest($command, [$this->escapeString($folder)], $tag); + + $result = []; + $tokens = null; // define $tokens variable before first use + while (!$this->readLine($tokens, $tag)) { + if ($tokens[0] == 'FLAGS') { + array_shift($tokens); + $result['flags'] = $tokens; + continue; + } + switch ($tokens[1]) { + case 'EXISTS': + case 'RECENT': + $result[strtolower($tokens[1])] = $tokens[0]; + break; + case '[UIDVALIDITY': + $result['uidvalidity'] = (int)$tokens[2]; + break; + case '[UIDNEXT': + $result['uidnext'] = (int)$tokens[2]; + break; + default: + // ignore + break; + } + } + + if ($tokens[0] != 'OK') { + return false; + } + return $result; + } + + /** + * Change the current folder + * @param string $folder change to this folder + * + * @return bool|array see examineOrselect() + * @throws RuntimeException + */ + public function selectFolder($folder = 'INBOX') { + return $this->examineOrSelect('SELECT', $folder); + } + + /** + * Examine a given folder + * @param string $folder examine this folder + * + * @return bool|array see examineOrselect() + * @throws RuntimeException + */ + public function examineFolder($folder = 'INBOX') { + return $this->examineOrSelect('EXAMINE', $folder); + } + + /** + * Fetch one or more items of one or more messages + * @param string|array $items items to fetch [RFC822.HEADER, FLAGS, RFC822.TEXT, etc] + * @param int|array $from message for items or start message if $to !== null + * @param int|null $to if null only one message ($from) is fetched, else it's the + * last message, INF means last message available + * @param bool $uid set to true if passing a unique id + * + * @return string|array if only one item of one message is fetched it's returned as string + * if items of one message are fetched it's returned as (name => value) + * if one items of messages are fetched it's returned as (msgno => value) + * if items of messages are fetched it's returned as (msgno => (name => value)) + * @throws RuntimeException + */ + protected function fetch($items, $from, $to = null, $uid = false) { + if (is_array($from)) { + $set = implode(',', $from); + } elseif ($to === null) { + $set = (int)$from; + } elseif ($to === INF) { + $set = (int)$from . ':*'; + } else { + $set = (int)$from . ':' . (int)$to; + } + + $items = (array)$items; + $itemList = $this->escapeList($items); + + $this->sendRequest(($uid ? 'UID ' : '') . 'FETCH', [$set, $itemList], $tag); + + $result = []; + $tokens = null; // define $tokens variable before first use + while (!$this->readLine($tokens, $tag)) { + // ignore other responses + if ($tokens[1] != 'FETCH') { + continue; + } + + // find array key of UID value; try the last elements, or search for it + if ($uid) { + $count = count($tokens[2]); + if ($tokens[2][$count - 2] == 'UID') { + $uidKey = $count - 1; + } else if ($tokens[2][0] == 'UID') { + $uidKey = 1; + } else { + $uidKey = array_search('UID', $tokens[2]) + 1; + } + } + + // ignore other messages + if ($to === null && !is_array($from) && ($uid ? $tokens[2][$uidKey] != $from : $tokens[0] != $from)) { + continue; + } + + // if we only want one item we return that one directly + if (count($items) == 1) { + if ($tokens[2][0] == $items[0]) { + $data = $tokens[2][1]; + } elseif ($uid && $tokens[2][2] == $items[0]) { + $data = $tokens[2][3]; + } else { + // maybe the server send an other field we didn't wanted + $count = count($tokens[2]); + // we start with 2, because 0 was already checked + for ($i = 2; $i < $count; $i += 2) { + if ($tokens[2][$i] != $items[0]) { + continue; + } + $data = $tokens[2][$i + 1]; + break; + } + } + } else { + $data = []; + while (key($tokens[2]) !== null) { + $data[current($tokens[2])] = next($tokens[2]); + next($tokens[2]); + } + } + + // if we want only one message we can ignore everything else and just return + if ($to === null && !is_array($from) && ($uid ? $tokens[2][$uidKey] == $from : $tokens[0] == $from)) { + // we still need to read all lines + while (!$this->readLine($tokens, $tag)) + + return $data; + } + if ($uid) { + $result[$tokens[2][$uidKey]] = $data; + }else{ + $result[$tokens[0]] = $data; + } + } + + if ($to === null && !is_array($from)) { + throw new RuntimeException('the single id was not found in response'); + } + + return $result; + } + + /** + * Fetch message headers + * @param array|int $uids + * @param string $rfc + * @param bool $uid set to true if passing a unique id + * + * @return array + * @throws RuntimeException + */ + public function content($uids, $rfc = "RFC822", $uid = false) { + return $this->fetch(["$rfc.TEXT"], $uids, null, $uid); + } + + /** + * Fetch message headers + * @param array|int $uids + * @param string $rfc + * @param bool $uid set to true if passing a unique id + * + * @return array + * @throws RuntimeException + */ + public function headers($uids, $rfc = "RFC822", $uid = false){ + return $this->fetch(["$rfc.HEADER"], $uids, null, $uid); + } + + /** + * Fetch message flags + * @param array|int $uids + * @param bool $uid set to true if passing a unique id + * + * @return array + * @throws RuntimeException + */ + public function flags($uids, $uid = false){ + return $this->fetch(["FLAGS"], $uids, null, $uid); + } + + /** + * Get uid for a given id + * @param int|null $id message number + * + * @return array|string message number for given message or all messages as array + * @throws MessageNotFoundException + */ + public function getUid($id = null) { + try { + $uids = $this->fetch('UID', 1, INF); + if ($id == null) { + return $uids; + } + + foreach ($uids as $k => $v) { + if ($k == $id) { + return $v; + } + } + } catch (RuntimeException $e) {} + + throw new MessageNotFoundException('unique id not found'); + } + + /** + * Get a message number for a uid + * @param string $id uid + * + * @return int message number + * @throws MessageNotFoundException + */ + public function getMessageNumber($id) { + $ids = $this->getUid(); + foreach ($ids as $k => $v) { + if ($v == $id) { + return $k; + } + } + + throw new MessageNotFoundException('message number not found'); + } + + /** + * Get a list of available folders + * @param string $reference mailbox reference for list + * @param string $folder mailbox name match with wildcards + * + * @return array folders that matched $folder as array(name => array('delimiter' => .., 'flags' => ..)) + * @throws RuntimeException + */ + public function folders($reference = '', $folder = '*') { + $result = []; + $list = $this->requestAndResponse('LIST', $this->escapeString($reference, $folder)); + if (!$list || $list === true) { + return $result; + } + + foreach ($list as $item) { + if (count($item) != 4 || $item[0] != 'LIST') { + continue; + } + $result[$item[3]] = ['delimiter' => $item[2], 'flags' => $item[1]]; + } + + return $result; + } + + /** + * Manage flags + * @param array $flags flags to set, add or remove - see $mode + * @param int $from message for items or start message if $to !== null + * @param int|null $to if null only one message ($from) is fetched, else it's the + * last message, INF means last message available + * @param string|null $mode '+' to add flags, '-' to remove flags, everything else sets the flags as given + * @param bool $silent if false the return values are the new flags for the wanted messages + * @param bool $uid set to true if passing a unique id + * + * @return bool|array new flags if $silent is false, else true or false depending on success + * @throws RuntimeException + */ + public function store(array $flags, $from, $to = null, $mode = null, $silent = true, $uid = false) { + $item = 'FLAGS'; + if ($mode == '+' || $mode == '-') { + $item = $mode . $item; + } + if ($silent) { + $item .= '.SILENT'; + } + + $flags = $this->escapeList($flags); + $set = (int)$from; + if ($to !== null) { + $set .= ':' . ($to == INF ? '*' : (int)$to); + } + + $command = ($uid ? "UID " : "")."STORE"; + $result = $this->requestAndResponse($command, [$set, $item, $flags], $silent); + + if ($silent) { + return (bool)$result; + } + + $tokens = $result; + $result = []; + foreach ($tokens as $token) { + if ($token[1] != 'FETCH' || $token[2][0] != 'FLAGS') { + continue; + } + $result[$token[0]] = $token[2][1]; + } + + return $result; + } + + /** + * Append a new message to given folder + * @param string $folder name of target folder + * @param string $message full message content + * @param array $flags flags for new message + * @param string $date date for new message + * + * @return bool success + * @throws RuntimeException + */ + public function appendMessage($folder, $message, $flags = null, $date = null) { + $tokens = []; + $tokens[] = $this->escapeString($folder); + if ($flags !== null) { + $tokens[] = $this->escapeList($flags); + } + if ($date !== null) { + $tokens[] = $this->escapeString($date); + } + $tokens[] = $this->escapeString($message); + + return $this->requestAndResponse('APPEND', $tokens, true); + } + + /** + * Copy a message set from current folder to an other folder + * @param string $folder destination folder + * @param $from + * @param int|null $to if null only one message ($from) is fetched, else it's the + * last message, INF means last message available + * @param bool $uid set to true if passing a unique id + * + * @return bool success + * @throws RuntimeException + */ + public function copyMessage($folder, $from, $to = null, $uid = false) { + $set = (int)$from; + if ($to !== null) { + $set .= ':' . ($to == INF ? '*' : (int)$to); + } + $command = ($uid ? "UID " : "")."COPY"; + + return $this->requestAndResponse($command, [$set, $this->escapeString($folder)], true); + } + + /** + * Copy multiple messages to the target folder + * + * @param array $messages List of message identifiers + * @param string $folder Destination folder + * @param bool $uid Set to true if you pass message unique identifiers instead of numbers + * @return array|bool Tokens if operation successful, false if an error occurred + * + * @throws RuntimeException + */ + public function copyManyMessages($messages, $folder, $uid = false) { + $command = $uid ? 'UID COPY' : 'COPY'; + + $set = implode(',', $messages); + $tokens = [$set, $this->escapeString($folder)]; + + return $this->requestAndResponse($command, $tokens, true); + } + + /** + * Move a message set from current folder to an other folder + * @param string $folder destination folder + * @param $from + * @param int|null $to if null only one message ($from) is fetched, else it's the + * last message, INF means last message available + * @param bool $uid set to true if passing a unique id + * + * @return bool success + * @throws RuntimeException + */ + public function moveMessage($folder, $from, $to = null, $uid = false) { + $set = (int)$from; + if ($to !== null) { + $set .= ':' . ($to == INF ? '*' : (int)$to); + } + $command = ($uid ? "UID " : "")."MOVE"; + + return $this->requestAndResponse($command, [$set, $this->escapeString($folder)], true); + } + + /** + * Move multiple messages to the target folder + * + * @param array $messages List of message identifiers + * @param string $folder Destination folder + * @param bool $uid Set to true if you pass message unique identifiers instead of numbers + * @return array|bool Tokens if operation successful, false if an error occurred + * + * @throws RuntimeException + */ + public function moveManyMessages($messages, $folder, $uid = false) { + $command = $uid ? 'UID MOVE' : 'MOVE'; + + $set = implode(',', $messages); + $tokens = [$set, $this->escapeString($folder)]; + + return $this->requestAndResponse($command, $tokens, true); + } + + /** + * Create a new folder (and parent folders if needed) + * @param string $folder folder name + * + * @return bool success + * @throws RuntimeException + */ + public function createFolder($folder) { + return $this->requestAndResponse('CREATE', [$this->escapeString($folder)], true); + } + + /** + * Rename an existing folder + * @param string $old old name + * @param string $new new name + * + * @return bool success + * @throws RuntimeException + */ + public function renameFolder($old, $new) { + return $this->requestAndResponse('RENAME', $this->escapeString($old, $new), true); + } + + /** + * Delete a folder + * @param string $folder folder name + * + * @return bool success + * @throws RuntimeException + */ + public function deleteFolder($folder) { + return $this->requestAndResponse('DELETE', [$this->escapeString($folder)], true); + } + + /** + * Subscribe to a folder + * @param string $folder folder name + * + * @return bool success + * @throws RuntimeException + */ + public function subscribeFolder($folder) { + return $this->requestAndResponse('SUBSCRIBE', [$this->escapeString($folder)], true); + } + + /** + * Unsubscribe from a folder + * @param string $folder folder name + * + * @return bool success + * @throws RuntimeException + */ + public function unsubscribeFolder($folder) { + return $this->requestAndResponse('UNSUBSCRIBE', [$this->escapeString($folder)], true); + } + + /** + * Apply session saved changes to the server + * + * @return bool success + * @throws RuntimeException + */ + public function expunge() { + return $this->requestAndResponse('EXPUNGE'); + } + + /** + * Send noop command + * + * @return bool success + * @throws RuntimeException + */ + public function noop() { + return $this->requestAndResponse('NOOP'); + } + + /** + * Retrieve the quota level settings, and usage statics per mailbox + * @param $username + * + * @return array + * @throws RuntimeException + */ + public function getQuota($username) { + return $this->requestAndResponse("GETQUOTA", ['"#user/'.$username.'"']); + } + + /** + * Retrieve the quota settings per user + * @param string $quota_root + * + * @return array + * @throws RuntimeException + */ + public function getQuotaRoot($quota_root = 'INBOX') { + return $this->requestAndResponse("QUOTA", [$quota_root]); + } + + /** + * Send idle command + * + * @throws RuntimeException + */ + public function idle() { + $this->sendRequest("IDLE"); + if (!$this->assumedNextLine('+ ')) { + throw new RuntimeException('idle failed'); + } + } + + /** + * Send done command + * @throws RuntimeException + */ + public function done() { + if (fwrite($this->stream, "DONE\r\n") === false) { + throw new RuntimeException('failed to write - connection closed?'); + } + return true; + } + + /** + * Search for matching messages + * @param array $params + * @param bool $uid set to true if passing a unique id + * + * @return array message ids + * @throws RuntimeException + */ + public function search(array $params, $uid = false) { + $token = $uid == true ? "UID SEARCH" : "SEARCH"; + $response = $this->requestAndResponse($token, $params); + if (!$response) { + return $response; + } + + foreach ($response as $ids) { + if ($ids[0] == 'SEARCH') { + array_shift($ids); + return $ids; + } + } + return []; + } + + /** + * Get a message overview + * @param string $sequence + * @param bool $uid set to true if passing a unique id + * + * @return array + * @throws RuntimeException + * @throws MessageNotFoundException + * @throws InvalidMessageDateException + */ + public function overview($sequence, $uid = false) { + $result = []; + list($from, $to) = explode(":", $sequence); + + $uids = $this->getUid(); + $ids = []; + foreach ($uids as $msgn => $v) { + $id = $uid ? $v : $msgn; + if ( ($to >= $id && $from <= $id) || ($to === "*" && $from <= $id) ){ + $ids[] = $id; + } + } + $headers = $this->headers($ids, "RFC822", $uid); + foreach ($headers as $id => $raw_header) { + $result[$id] = (new Header($raw_header, false))->getAttributes(); + } + return $result; + } + + /** + * Enable the debug mode + */ + public function enableDebug(){ + $this->debug = true; + } + + /** + * Disable the debug mode + */ + public function disableDebug(){ + $this->debug = false; + } +} diff --git a/htdocs/includes/webklex/php-imap/src/Connection/Protocols/LegacyProtocol.php b/htdocs/includes/webklex/php-imap/src/Connection/Protocols/LegacyProtocol.php new file mode 100644 index 00000000000..96cc733f248 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/Connection/Protocols/LegacyProtocol.php @@ -0,0 +1,607 @@ +setCertValidation($cert_validation); + $this->encryption = $encryption; + } + + /** + * Public destructor + */ + public function __destruct() { + $this->logout(); + } + + /** + * Save the information for a nw connection + * @param string $host + * @param null $port + */ + public function connect($host, $port = null) { + if ($this->encryption) { + $encryption = strtolower($this->encryption); + if ($encryption == "ssl") { + $port = $port === null ? 993 : $port; + } + } + $port = $port === null ? 143 : $port; + $this->host = $host; + $this->port = $port; + } + + /** + * Login to a new session. + * @param string $user username + * @param string $password password + * + * @return bool + * @throws AuthFailedException + * @throws RuntimeException + */ + public function login($user, $password) { + try { + $this->stream = \imap_open( + $this->getAddress(), + $user, + $password, + 0, + $attempts = 3, + ClientManager::get('options.open') + ); + } catch (\ErrorException $e) { + $errors = \imap_errors(); + $message = $e->getMessage().'. '.implode("; ", (is_array($errors) ? $errors : array())); + throw new AuthFailedException($message); + } + + if(!$this->stream) { + $errors = \imap_errors(); + $message = implode("; ", (is_array($errors) ? $errors : array())); + throw new AuthFailedException($message); + } + + $errors = \imap_errors(); + if(is_array($errors)) { + $status = $this->examineFolder(); + if($status['exists'] !== 0) { + $message = implode("; ", (is_array($errors) ? $errors : array())); + throw new RuntimeException($message); + } + } + + return $this->stream; + } + + /** + * Authenticate your current session. + * @param string $user username + * @param string $token access token + * + * @return bool|resource + * @throws AuthFailedException|RuntimeException + */ + public function authenticate($user, $token) { + return $this->login($user, $token); + } + + /** + * Get full address of mailbox. + * + * @return string + */ + protected function getAddress() { + $address = "{".$this->host.":".$this->port."/".$this->protocol; + if (!$this->cert_validation) { + $address .= '/novalidate-cert'; + } + if (in_array($this->encryption,['tls', 'notls', 'ssl'])) { + $address .= '/'.$this->encryption; + } elseif ($this->encryption === "starttls") { + $address .= '/tls'; + } + + $address .= '}'; + + return $address; + } + + /** + * Logout of the current session + * + * @return bool success + */ + public function logout() { + if ($this->stream) { + $result = \imap_close($this->stream, IMAP::CL_EXPUNGE); + $this->stream = false; + return $result; + } + return false; + } + + /** + * Check if the current session is connected + * + * @return bool + */ + public function connected(){ + return boolval($this->stream); + } + + /** + * Get an array of available capabilities + * + * @throws MethodNotSupportedException + */ + public function getCapabilities() { + throw new MethodNotSupportedException(); + } + + /** + * Change the current folder + * @param string $folder change to this folder + * + * @return bool|array see examineOrselect() + * @throws RuntimeException + */ + public function selectFolder($folder = 'INBOX') { + \imap_reopen($this->stream, $folder, IMAP::OP_READONLY, 3); + return $this->examineFolder($folder); + } + + /** + * Examine a given folder + * @param string $folder examine this folder + * + * @return bool|array + * @throws RuntimeException + */ + public function examineFolder($folder = 'INBOX') { + if (strpos($folder, ".") === 0) { + throw new RuntimeException("Segmentation fault prevented. Folders starts with an illegal char '.'."); + } + $folder = $this->getAddress().$folder; + $status = \imap_status($this->stream, $folder, IMAP::SA_ALL); + return [ + "flags" => [], + "exists" => $status->messages, + "recent" => $status->recent, + "unseen" => $status->unseen, + "uidnext" => $status->uidnext, + ]; + } + + /** + * Fetch message content + * @param array|int $uids + * @param string $rfc + * @param bool $uid set to true if passing a unique id + * + * @return array + */ + public function content($uids, $rfc = "RFC822", $uid = false) { + $result = []; + $uids = is_array($uids) ? $uids : [$uids]; + foreach ($uids as $id) { + $result[$id] = \imap_fetchbody($this->stream, $id, "", $uid ? IMAP::FT_UID : IMAP::NIL); + } + return $result; + } + + /** + * Fetch message headers + * @param array|int $uids + * @param string $rfc + * @param bool $uid set to true if passing a unique id + * + * @return array + */ + public function headers($uids, $rfc = "RFC822", $uid = false){ + $result = []; + $uids = is_array($uids) ? $uids : [$uids]; + foreach ($uids as $id) { + $result[$id] = \imap_fetchheader($this->stream, $id, $uid ? IMAP::FT_UID : IMAP::NIL); + } + return $result; + } + + /** + * Fetch message flags + * @param array|int $uids + * @param bool $uid set to true if passing a unique id + * + * @return array + */ + public function flags($uids, $uid = false){ + $result = []; + $uids = is_array($uids) ? $uids : [$uids]; + foreach ($uids as $id) { + $raw_flags = \imap_fetch_overview($this->stream, $id, $uid ? IMAP::FT_UID : IMAP::NIL); + $flags = []; + if (is_array($raw_flags) && isset($raw_flags[0])) { + $raw_flags = (array) $raw_flags[0]; + foreach($raw_flags as $flag => $value) { + if ($value === 1 && in_array($flag, ["size", "uid", "msgno", "update"]) === false){ + $flags[] = "\\".ucfirst($flag); + } + } + } + $result[$uid] = $flags; + } + + return $result; + } + + /** + * Get uid for a given id + * @param int|null $id message number + * + * @return array|string message number for given message or all messages as array + */ + public function getUid($id = null) { + if ($id === null) { + $overview = $this->overview("1:*"); + $uids = []; + foreach($overview as $set){ + $uids[$set->msgno] = $set->uid; + } + return $uids; + } + return \imap_uid($this->stream, $id); + } + + /** + * Get a message number for a uid + * @param string $id uid + * + * @return int message number + */ + public function getMessageNumber($id) { + return \imap_msgno($this->stream, $id); + } + + /** + * Get a message overview + * @param string $sequence uid sequence + * @param bool $uid set to true if passing a unique id + * + * @return array + */ + public function overview($sequence, $uid = false) { + return \imap_fetch_overview($this->stream, $sequence,$uid ? IMAP::FT_UID : IMAP::NIL); + } + + /** + * Get a list of available folders + * @param string $reference mailbox reference for list + * @param string $folder mailbox name match with wildcards + * + * @return array folders that matched $folder as array(name => array('delimiter' => .., 'flags' => ..)) + * @throws RuntimeException + */ + public function folders($reference = '', $folder = '*') { + $result = []; + + $items = \imap_getmailboxes($this->stream, $this->getAddress(), $reference.$folder); + if(is_array($items)){ + foreach ($items as $item) { + $name = $this->decodeFolderName($item->name); + $result[$name] = ['delimiter' => $item->delimiter, 'flags' => []]; + } + }else{ + throw new RuntimeException(\imap_last_error()); + } + + return $result; + } + + /** + * Manage flags + * @param array $flags flags to set, add or remove - see $mode + * @param int $from message for items or start message if $to !== null + * @param int|null $to if null only one message ($from) is fetched, else it's the + * last message, INF means last message available + * @param string|null $mode '+' to add flags, '-' to remove flags, everything else sets the flags as given + * @param bool $silent if false the return values are the new flags for the wanted messages + * @param bool $uid set to true if passing a unique id + * + * @return bool|array new flags if $silent is false, else true or false depending on success + */ + public function store(array $flags, $from, $to = null, $mode = null, $silent = true, $uid = false) { + $flag = trim(is_array($flags) ? implode(" ", $flags) : $flags); + + if ($mode == "+"){ + $status = \imap_setflag_full($this->stream, $from, $flag, $uid ? IMAP::FT_UID : IMAP::NIL); + }else{ + $status = \imap_clearflag_full($this->stream, $from, $flag, $uid ? IMAP::FT_UID : IMAP::NIL); + } + + if ($silent === true) { + return $status; + } + + return $this->flags($from); + } + + /** + * Append a new message to given folder + * @param string $folder name of target folder + * @param string $message full message content + * @param array $flags flags for new message + * @param string $date date for new message + * + * @return bool success + */ + public function appendMessage($folder, $message, $flags = null, $date = null) { + if ($date != null) { + if ($date instanceof \Carbon\Carbon){ + $date = $date->format('d-M-Y H:i:s O'); + } + return \imap_append($this->stream, $folder, $message, $flags, $date); + } + + return \imap_append($this->stream, $folder, $message, $flags); + } + + /** + * Copy message set from current folder to other folder + * @param string $folder destination folder + * @param $from + * @param int|null $to if null only one message ($from) is fetched, else it's the + * last message, INF means last message available + * @param bool $uid set to true if passing a unique id + * + * @return bool success + */ + public function copyMessage($folder, $from, $to = null, $uid = false) { + return \imap_mail_copy($this->stream, $from, $folder, $uid ? IMAP::FT_UID : IMAP::NIL); + } + + /** + * Copy multiple messages to the target folder + * + * @param array $messages List of message identifiers + * @param string $folder Destination folder + * @param bool $uid Set to true if you pass message unique identifiers instead of numbers + * @return array|bool Tokens if operation successful, false if an error occurred + */ + public function copyManyMessages($messages, $folder, $uid = false) { + foreach($messages as $msg) { + if ($this->copyMessage($folder, $msg, null, $uid) == false) { + return false; + } + } + + return $messages; + } + + /** + * Move a message set from current folder to an other folder + * @param string $folder destination folder + * @param $from + * @param int|null $to if null only one message ($from) is fetched, else it's the + * last message, INF means last message available + * @param bool $uid set to true if passing a unique id + * + * @return bool success + */ + public function moveMessage($folder, $from, $to = null, $uid = false) { + return \imap_mail_move($this->stream, $from, $folder, $uid ? IMAP::FT_UID : IMAP::NIL); + } + + /** + * Move multiple messages to the target folder + * + * @param array $messages List of message identifiers + * @param string $folder Destination folder + * @param bool $uid Set to true if you pass message unique identifiers instead of numbers + * @return array|bool Tokens if operation successful, false if an error occurred + */ + public function moveManyMessages($messages, $folder, $uid = false) { + foreach($messages as $msg) { + if ($this->moveMessage($folder, $msg, null, $uid) == false) { + return false; + } + } + + return $messages; + } + + /** + * Create a new folder (and parent folders if needed) + * @param string $folder folder name + * + * @return bool success + */ + public function createFolder($folder) { + return \imap_createmailbox($this->stream, $folder); + } + + /** + * Rename an existing folder + * @param string $old old name + * @param string $new new name + * + * @return bool success + */ + public function renameFolder($old, $new) { + return \imap_renamemailbox($this->stream, $old, $new); + } + + /** + * Delete a folder + * @param string $folder folder name + * + * @return bool success + */ + public function deleteFolder($folder) { + return \imap_deletemailbox($this->stream, $folder); + } + + /** + * Subscribe to a folder + * @param string $folder folder name + * + * @throws MethodNotSupportedException + */ + public function subscribeFolder($folder) { + throw new MethodNotSupportedException(); + } + + /** + * Unsubscribe from a folder + * @param string $folder folder name + * + * @throws MethodNotSupportedException + */ + public function unsubscribeFolder($folder) { + throw new MethodNotSupportedException(); + } + + /** + * Apply session saved changes to the server + * + * @return bool success + */ + public function expunge() { + return \imap_expunge($this->stream); + } + + /** + * Send noop command + * + * @throws MethodNotSupportedException + */ + public function noop() { + throw new MethodNotSupportedException(); + } + + /** + * Send idle command + * + * @throws MethodNotSupportedException + */ + public function idle() { + throw new MethodNotSupportedException(); + } + + /** + * Send done command + * + * @throws MethodNotSupportedException + */ + public function done() { + throw new MethodNotSupportedException(); + } + + /** + * Search for matching messages + * + * @param array $params + * @return array message ids + */ + public function search(array $params, $uid = false) { + return \imap_search($this->stream, $params[0], $uid ? IMAP::FT_UID : IMAP::NIL); + } + + /** + * Enable the debug mode + */ + public function enableDebug(){ + $this->debug = true; + } + + /** + * Disable the debug mode + */ + public function disableDebug(){ + $this->debug = false; + } + + /** + * Decode name. + * It converts UTF7-IMAP encoding to UTF-8. + * + * @param $name + * + * @return mixed|string + */ + protected function decodeFolderName($name) { + preg_match('#\{(.*)\}(.*)#', $name, $preg); + return mb_convert_encoding($preg[2], "UTF-8", "UTF7-IMAP"); + } + + /** + * @return string + */ + public function getProtocol() { + return $this->protocol; + } + + /** + * Retrieve the quota level settings, and usage statics per mailbox + * @param $username + * + * @return array + */ + public function getQuota($username) { + return \imap_get_quota($this->stream, 'user.'.$username); + } + + /** + * Retrieve the quota settings per user + * @param string $quota_root + * + * @return array + */ + public function getQuotaRoot($quota_root = 'INBOX') { + return \imap_get_quotaroot($this->stream, $quota_root); + } + + /** + * @param string $protocol + * @return LegacyProtocol + */ + public function setProtocol($protocol) { + if (($pos = strpos($protocol, "legacy")) > 0) { + $protocol = substr($protocol, 0, ($pos + 2) * -1); + } + $this->protocol = $protocol; + return $this; + } +} \ No newline at end of file diff --git a/htdocs/includes/webklex/php-imap/src/Connection/Protocols/Protocol.php b/htdocs/includes/webklex/php-imap/src/Connection/Protocols/Protocol.php new file mode 100644 index 00000000000..ef01d46ec9b --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/Connection/Protocols/Protocol.php @@ -0,0 +1,224 @@ + null, + 'request_fulluri' => false, + 'username' => null, + 'password' => null, + ]; + + /** + * Get an available cryptographic method + * + * @return int + */ + public function getCryptoMethod() { + // Allow the best TLS version(s) we can + $cryptoMethod = STREAM_CRYPTO_METHOD_TLS_CLIENT; + + // PHP 5.6.7 dropped inclusion of TLS 1.1 and 1.2 in STREAM_CRYPTO_METHOD_TLS_CLIENT + // so add them back in manually if we can + if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) { + $cryptoMethod = STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT; + }elseif (defined('STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT')) { + $cryptoMethod = STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT; + } + + return $cryptoMethod; + } + + /** + * Enable SSL certificate validation + * + * @return $this + */ + public function enableCertValidation() { + $this->cert_validation = true; + return $this; + } + + /** + * Disable SSL certificate validation + * @return $this + */ + public function disableCertValidation() { + $this->cert_validation = false; + return $this; + } + + /** + * Set SSL certificate validation + * @var int $cert_validation + * + * @return $this + */ + public function setCertValidation($cert_validation) { + $this->cert_validation = $cert_validation; + return $this; + } + + /** + * Should we validate SSL certificate? + * + * @return bool + */ + public function getCertValidation() { + return $this->cert_validation; + } + + /** + * Set connection proxy settings + * @var array $options + * + * @return $this + */ + public function setProxy($options) { + foreach ($this->proxy as $key => $val) { + if (isset($options[$key])) { + $this->proxy[$key] = $options[$key]; + } + } + + return $this; + } + + /** + * Get the current proxy settings + * + * @return array + */ + public function getProxy() { + return $this->proxy; + } + + /** + * Prepare socket options + * @var string $transport + * + * @return array + */ + private function defaultSocketOptions($transport) { + $options = []; + if ($this->encryption != false) { + $options["ssl"] = [ + 'verify_peer_name' => $this->getCertValidation(), + 'verify_peer' => $this->getCertValidation(), + ]; + } + + if ($this->proxy["socket"] != null) { + $options[$transport]["proxy"] = $this->proxy["socket"]; + $options[$transport]["request_fulluri"] = $this->proxy["request_fulluri"]; + + if ($this->proxy["username"] != null) { + $auth = base64_encode($this->proxy["username"].':'.$this->proxy["password"]); + + $options[$transport]["header"] = [ + "Proxy-Authorization: Basic $auth" + ]; + } + } + + return $options; + } + + /** + * Create a new resource stream + * @param $transport + * @param string $host hostname or IP address of IMAP server + * @param int $port of IMAP server, default is 143 (993 for ssl) + * @param int $timeout timeout in seconds for initiating session + * + * @return resource|boolean The socket created. + * @throws ConnectionFailedException + */ + protected function createStream($transport, $host, $port, $timeout) { + $socket = "$transport://$host:$port"; + $stream = stream_socket_client($socket, $errno, $errstr, $timeout, + STREAM_CLIENT_CONNECT, + stream_context_create($this->defaultSocketOptions($transport)) + ); + stream_set_timeout($stream, $timeout); + + if (!$stream) { + throw new ConnectionFailedException($errstr, $errno); + } + + if (false === stream_set_timeout($stream, $timeout)) { + throw new ConnectionFailedException('Failed to set stream timeout'); + } + + return $stream; + } + + /** + * @return int + */ + public function getConnectionTimeout() { + return $this->connection_timeout; + } + + /** + * @param int $connection_timeout + * @return Protocol + */ + public function setConnectionTimeout($connection_timeout) { + if ($connection_timeout !== null) { + $this->connection_timeout = $connection_timeout; + } + return $this; + } + +} \ No newline at end of file diff --git a/htdocs/includes/webklex/php-imap/src/Connection/Protocols/ProtocolInterface.php b/htdocs/includes/webklex/php-imap/src/Connection/Protocols/ProtocolInterface.php new file mode 100644 index 00000000000..6770d8d4c7b --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/Connection/Protocols/ProtocolInterface.php @@ -0,0 +1,375 @@ + array('delim' => .., 'flags' => ..)) + * @throws RuntimeException + */ + public function folders($reference = '', $folder = '*'); + + /** + * Set message flags + * + * @param array $flags flags to set, add or remove + * @param int $from message for items or start message if $to !== null + * @param int|null $to if null only one message ($from) is fetched, else it's the + * last message, INF means last message available + * @param string|null $mode '+' to add flags, '-' to remove flags, everything else sets the flags as given + * @param bool $silent if false the return values are the new flags for the wanted messages + * @param bool $uid set to true if passing a unique id + * + * @return bool|array new flags if $silent is false, else true or false depending on success + * @throws RuntimeException + */ + public function store(array $flags, $from, $to = null, $mode = null, $silent = true, $uid = false); + + /** + * Append a new message to given folder + * + * @param string $folder name of target folder + * @param string $message full message content + * @param array $flags flags for new message + * @param string $date date for new message + * @return bool success + * @throws RuntimeException + */ + public function appendMessage($folder, $message, $flags = null, $date = null); + + /** + * Copy message set from current folder to other folder + * + * @param string $folder destination folder + * @param $from + * @param int|null $to if null only one message ($from) is fetched, else it's the + * last message, INF means last message available + * @param bool $uid set to true if passing a unique id + * + * @return bool success + * @throws RuntimeException + */ + public function copyMessage($folder, $from, $to = null, $uid = false); + + /** + * Copy multiple messages to the target folder + * + * @param array $messages List of message identifiers + * @param string $folder Destination folder + * @param bool $uid Set to true if you pass message unique identifiers instead of numbers + * @return array|bool Tokens if operation successful, false if an error occurred + * + * @throws RuntimeException + */ + public function copyManyMessages($messages, $folder, $uid = false); + + /** + * Move a message set from current folder to an other folder + * @param string $folder destination folder + * @param $from + * @param int|null $to if null only one message ($from) is fetched, else it's the + * last message, INF means last message available + * @param bool $uid set to true if passing a unique id + * + * @return bool success + */ + public function moveMessage($folder, $from, $to = null, $uid = false); + + /** + * Move multiple messages to the target folder + * + * @param array $messages List of message identifiers + * @param string $folder Destination folder + * @param bool $uid Set to true if you pass message unique identifiers instead of numbers + * @return array|bool Tokens if operation successful, false if an error occurred + * + * @throws RuntimeException + */ + public function moveManyMessages($messages, $folder, $uid = false); + + /** + * Create a new folder + * + * @param string $folder folder name + * @return bool success + * @throws RuntimeException + */ + public function createFolder($folder); + + /** + * Rename an existing folder + * + * @param string $old old name + * @param string $new new name + * @return bool success + * @throws RuntimeException + */ + public function renameFolder($old, $new); + + /** + * Delete a folder + * + * @param string $folder folder name + * @return bool success + * @throws RuntimeException + */ + public function deleteFolder($folder); + + /** + * Subscribe to a folder + * + * @param string $folder folder name + * @return bool success + * @throws RuntimeException + */ + public function subscribeFolder($folder); + + /** + * Unsubscribe from a folder + * @param string $folder folder name + * + * @return bool success + * @throws RuntimeException + */ + public function unsubscribeFolder($folder); + + /** + * Send idle command + * + * @throws RuntimeException + */ + public function idle(); + + /** + * Send done command + * @throws RuntimeException + */ + public function done(); + + /** + * Apply session saved changes to the server + * + * @return bool success + * @throws RuntimeException + */ + public function expunge(); + + /** + * Retrieve the quota level settings, and usage statics per mailbox + * @param $username + * + * @return array + * @throws RuntimeException + */ + public function getQuota($username); + + /** + * Retrieve the quota settings per user + * + * @param string $quota_root + * + * @return array + * @throws ConnectionFailedException + */ + public function getQuotaRoot($quota_root = 'INBOX'); + + /** + * Send noop command + * + * @return bool success + * @throws RuntimeException + */ + public function noop(); + + /** + * Do a search request + * + * @param array $params + * @param bool $uid set to true if passing a unique id + * + * @return array message ids + * @throws RuntimeException + */ + public function search(array $params, $uid = false); + + /** + * Get a message overview + * @param string $sequence uid sequence + * @param bool $uid set to true if passing a unique id + * + * @return array + * @throws RuntimeException + * @throws MessageNotFoundException + * @throws InvalidMessageDateException + */ + public function overview($sequence, $uid = false); + + /** + * Enable the debug mode + */ + public function enableDebug(); + + /** + * Disable the debug mode + */ + public function disableDebug(); +} \ No newline at end of file diff --git a/htdocs/includes/webklex/php-imap/src/EncodingAliases.php b/htdocs/includes/webklex/php-imap/src/EncodingAliases.php new file mode 100644 index 00000000000..1eb16c131bb --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/EncodingAliases.php @@ -0,0 +1,482 @@ + "us-ascii", + "us-ascii" => "us-ascii", + "ansi_x3.4-1968" => "us-ascii", + "646" => "us-ascii", + "iso-8859-1" => "ISO-8859-1", + "iso-8859-2" => "ISO-8859-2", + "iso-8859-3" => "ISO-8859-3", + "iso-8859-4" => "ISO-8859-4", + "iso-8859-5" => "ISO-8859-5", + "iso-8859-6" => "ISO-8859-6", + "iso-8859-6-i" => "ISO-8859-6-I", + "iso-8859-6-e" => "ISO-8859-6-E", + "iso-8859-7" => "ISO-8859-7", + "iso-8859-8" => "ISO-8859-8", + "iso-8859-8-i" => "ISO-8859-8-I", + "iso-8859-8-e" => "ISO-8859-8-E", + "iso-8859-9" => "ISO-8859-9", + "iso-8859-10" => "ISO-8859-10", + "iso-8859-11" => "ISO-8859-11", + "iso-8859-13" => "ISO-8859-13", + "iso-8859-14" => "ISO-8859-14", + "iso-8859-15" => "ISO-8859-15", + "iso-8859-16" => "ISO-8859-16", + "iso-ir-111" => "ISO-IR-111", + "iso-2022-cn" => "ISO-2022-CN", + "iso-2022-cn-ext" => "ISO-2022-CN", + "iso-2022-kr" => "ISO-2022-KR", + "iso-2022-jp" => "ISO-2022-JP", + "utf-16be" => "UTF-16BE", + "utf-16le" => "UTF-16LE", + "utf-16" => "UTF-16", + "windows-1250" => "windows-1250", + "windows-1251" => "windows-1251", + "windows-1252" => "windows-1252", + "windows-1253" => "windows-1253", + "windows-1254" => "windows-1254", + "windows-1255" => "windows-1255", + "windows-1256" => "windows-1256", + "windows-1257" => "windows-1257", + "windows-1258" => "windows-1258", + "ibm866" => "IBM866", + "ibm850" => "IBM850", + "ibm852" => "IBM852", + "ibm855" => "IBM855", + "ibm857" => "IBM857", + "ibm862" => "IBM862", + "ibm864" => "IBM864", + "utf-8" => "UTF-8", + "utf-7" => "UTF-7", + "shift_jis" => "Shift_JIS", + "big5" => "Big5", + "euc-jp" => "EUC-JP", + "euc-kr" => "EUC-KR", + "gb2312" => "GB2312", + "gb18030" => "gb18030", + "viscii" => "VISCII", + "koi8-r" => "KOI8-R", + "koi8_r" => "KOI8-R", + "cskoi8r" => "KOI8-R", + "koi" => "KOI8-R", + "koi8" => "KOI8-R", + "koi8-u" => "KOI8-U", + "tis-620" => "TIS-620", + "t.61-8bit" => "T.61-8bit", + "hz-gb-2312" => "HZ-GB-2312", + "big5-hkscs" => "Big5-HKSCS", + "gbk" => "gbk", + "cns11643" => "x-euc-tw", + // + // Aliases for ISO-8859-1 + // + "latin1" => "ISO-8859-1", + "iso_8859-1" => "ISO-8859-1", + "iso8859-1" => "ISO-8859-1", + "iso8859-2" => "ISO-8859-2", + "iso8859-3" => "ISO-8859-3", + "iso8859-4" => "ISO-8859-4", + "iso8859-5" => "ISO-8859-5", + "iso8859-6" => "ISO-8859-6", + "iso8859-7" => "ISO-8859-7", + "iso8859-8" => "ISO-8859-8", + "iso8859-9" => "ISO-8859-9", + "iso8859-10" => "ISO-8859-10", + "iso8859-11" => "ISO-8859-11", + "iso8859-13" => "ISO-8859-13", + "iso8859-14" => "ISO-8859-14", + "iso8859-15" => "ISO-8859-15", + "iso_8859-1:1987" => "ISO-8859-1", + "iso-ir-100" => "ISO-8859-1", + "l1" => "ISO-8859-1", + "ibm819" => "ISO-8859-1", + "cp819" => "ISO-8859-1", + "csisolatin1" => "ISO-8859-1", + // + // Aliases for ISO-8859-2 + // + "latin2" => "ISO-8859-2", + "iso_8859-2" => "ISO-8859-2", + "iso_8859-2:1987" => "ISO-8859-2", + "iso-ir-101" => "ISO-8859-2", + "l2" => "ISO-8859-2", + "csisolatin2" => "ISO-8859-2", + // + // Aliases for ISO-8859-3 + // + "latin3" => "ISO-8859-3", + "iso_8859-3" => "ISO-8859-3", + "iso_8859-3:1988" => "ISO-8859-3", + "iso-ir-109" => "ISO-8859-3", + "l3" => "ISO-8859-3", + "csisolatin3" => "ISO-8859-3", + // + // Aliases for ISO-8859-4 + // + "latin4" => "ISO-8859-4", + "iso_8859-4" => "ISO-8859-4", + "iso_8859-4:1988" => "ISO-8859-4", + "iso-ir-110" => "ISO-8859-4", + "l4" => "ISO-8859-4", + "csisolatin4" => "ISO-8859-4", + // + // Aliases for ISO-8859-5 + // + "cyrillic" => "ISO-8859-5", + "iso_8859-5" => "ISO-8859-5", + "iso_8859-5:1988" => "ISO-8859-5", + "iso-ir-144" => "ISO-8859-5", + "csisolatincyrillic" => "ISO-8859-5", + // + // Aliases for ISO-8859-6 + // + "arabic" => "ISO-8859-6", + "iso_8859-6" => "ISO-8859-6", + "iso_8859-6:1987" => "ISO-8859-6", + "iso-ir-127" => "ISO-8859-6", + "ecma-114" => "ISO-8859-6", + "asmo-708" => "ISO-8859-6", + "csisolatinarabic" => "ISO-8859-6", + // + // Aliases for ISO-8859-6-I + // + "csiso88596i" => "ISO-8859-6-I", + // + // Aliases for ISO-8859-6-E", + // + "csiso88596e" => "ISO-8859-6-E", + // + // Aliases for ISO-8859-7", + // + "greek" => "ISO-8859-7", + "greek8" => "ISO-8859-7", + "sun_eu_greek" => "ISO-8859-7", + "iso_8859-7" => "ISO-8859-7", + "iso_8859-7:1987" => "ISO-8859-7", + "iso-ir-126" => "ISO-8859-7", + "elot_928" => "ISO-8859-7", + "ecma-118" => "ISO-8859-7", + "csisolatingreek" => "ISO-8859-7", + // + // Aliases for ISO-8859-8", + // + "hebrew" => "ISO-8859-8", + "iso_8859-8" => "ISO-8859-8", + "visual" => "ISO-8859-8", + "iso_8859-8:1988" => "ISO-8859-8", + "iso-ir-138" => "ISO-8859-8", + "csisolatinhebrew" => "ISO-8859-8", + // + // Aliases for ISO-8859-8-I", + // + "csiso88598i" => "ISO-8859-8-I", + "iso-8859-8i" => "ISO-8859-8-I", + "logical" => "ISO-8859-8-I", + // + // Aliases for ISO-8859-8-E", + // + "csiso88598e" => "ISO-8859-8-E", + // + // Aliases for ISO-8859-9", + // + "latin5" => "ISO-8859-9", + "iso_8859-9" => "ISO-8859-9", + "iso_8859-9:1989" => "ISO-8859-9", + "iso-ir-148" => "ISO-8859-9", + "l5" => "ISO-8859-9", + "csisolatin5" => "ISO-8859-9", + // + // Aliases for UTF-8", + // + "unicode-1-1-utf-8" => "UTF-8", + // nl_langinfo(CODESET) in HP/UX returns 'utf8' under UTF-8 locales", + "utf8" => "UTF-8", + // + // Aliases for Shift_JIS", + // + "x-sjis" => "Shift_JIS", + "shift-jis" => "Shift_JIS", + "ms_kanji" => "Shift_JIS", + "csshiftjis" => "Shift_JIS", + "windows-31j" => "Shift_JIS", + "cp932" => "Shift_JIS", + "sjis" => "Shift_JIS", + // + // Aliases for EUC_JP", + // + "cseucpkdfmtjapanese" => "EUC-JP", + "x-euc-jp" => "EUC-JP", + // + // Aliases for ISO-2022-JP", + // + "csiso2022jp" => "ISO-2022-JP", + // The following are really not aliases ISO-2022-JP, but sharing the same decoder", + "iso-2022-jp-2" => "ISO-2022-JP", + "csiso2022jp2" => "ISO-2022-JP", + // + // Aliases for Big5", + // + "csbig5" => "Big5", + "cn-big5" => "Big5", + // x-x-big5 is not really a alias for Big5, add it only for MS FrontPage", + "x-x-big5" => "Big5", + // Sun Solaris", + "zh_tw-big5" => "Big5", + // + // Aliases for EUC-KR", + // + "cseuckr" => "EUC-KR", + "ks_c_5601-1987" => "EUC-KR", + "iso-ir-149" => "EUC-KR", + "ks_c_5601-1989" => "EUC-KR", + "ksc_5601" => "EUC-KR", + "ksc5601" => "EUC-KR", + "korean" => "EUC-KR", + "csksc56011987" => "EUC-KR", + "5601" => "EUC-KR", + "windows-949" => "EUC-KR", + // + // Aliases for GB2312", + // + // The following are really not aliases GB2312, add them only for MS FrontPage", + "gb_2312-80" => "GB2312", + "iso-ir-58" => "GB2312", + "chinese" => "GB2312", + "csiso58gb231280" => "GB2312", + "csgb2312" => "GB2312", + "zh_cn.euc" => "GB2312", + // Sun Solaris", + "gb_2312" => "GB2312", + // + // Aliases for windows-125x ", + // + "x-cp1250" => "windows-1250", + "x-cp1251" => "windows-1251", + "x-cp1252" => "windows-1252", + "x-cp1253" => "windows-1253", + "x-cp1254" => "windows-1254", + "x-cp1255" => "windows-1255", + "x-cp1256" => "windows-1256", + "x-cp1257" => "windows-1257", + "x-cp1258" => "windows-1258", + // + // Aliases for windows-874 ", + // + "windows-874" => "windows-874", + "ibm874" => "windows-874", + "dos-874" => "windows-874", + // + // Aliases for macintosh", + // + "macintosh" => "macintosh", + "x-mac-roman" => "macintosh", + "mac" => "macintosh", + "csmacintosh" => "macintosh", + // + // Aliases for IBM866", + // + "cp866" => "IBM866", + "cp-866" => "IBM866", + "866" => "IBM866", + "csibm866" => "IBM866", + // + // Aliases for IBM850", + // + "cp850" => "IBM850", + "850" => "IBM850", + "csibm850" => "IBM850", + // + // Aliases for IBM852", + // + "cp852" => "IBM852", + "852" => "IBM852", + "csibm852" => "IBM852", + // + // Aliases for IBM855", + // + "cp855" => "IBM855", + "855" => "IBM855", + "csibm855" => "IBM855", + // + // Aliases for IBM857", + // + "cp857" => "IBM857", + "857" => "IBM857", + "csibm857" => "IBM857", + // + // Aliases for IBM862", + // + "cp862" => "IBM862", + "862" => "IBM862", + "csibm862" => "IBM862", + // + // Aliases for IBM864", + // + "cp864" => "IBM864", + "864" => "IBM864", + "csibm864" => "IBM864", + "ibm-864" => "IBM864", + // + // Aliases for T.61-8bit", + // + "t.61" => "T.61-8bit", + "iso-ir-103" => "T.61-8bit", + "csiso103t618bit" => "T.61-8bit", + // + // Aliases for UTF-7", + // + "x-unicode-2-0-utf-7" => "UTF-7", + "unicode-2-0-utf-7" => "UTF-7", + "unicode-1-1-utf-7" => "UTF-7", + "csunicode11utf7" => "UTF-7", + // + // Aliases for ISO-10646-UCS-2", + // + "csunicode" => "UTF-16BE", + "csunicode11" => "UTF-16BE", + "iso-10646-ucs-basic" => "UTF-16BE", + "csunicodeascii" => "UTF-16BE", + "iso-10646-unicode-latin1" => "UTF-16BE", + "csunicodelatin1" => "UTF-16BE", + "iso-10646" => "UTF-16BE", + "iso-10646-j-1" => "UTF-16BE", + // + // Aliases for ISO-8859-10", + // + "latin6" => "ISO-8859-10", + "iso-ir-157" => "ISO-8859-10", + "l6" => "ISO-8859-10", + // Currently .properties cannot handle : in key", + //iso_8859-10:1992" => "ISO-8859-10", + "csisolatin6" => "ISO-8859-10", + // + // Aliases for ISO-8859-15", + // + "iso_8859-15" => "ISO-8859-15", + "csisolatin9" => "ISO-8859-15", + "l9" => "ISO-8859-15", + // + // Aliases for ISO-IR-111", + // + "ecma-cyrillic" => "ISO-IR-111", + "csiso111ecmacyrillic" => "ISO-IR-111", + // + // Aliases for ISO-2022-KR", + // + "csiso2022kr" => "ISO-2022-KR", + // + // Aliases for VISCII", + // + "csviscii" => "VISCII", + // + // Aliases for x-euc-tw", + // + "zh_tw-euc" => "x-euc-tw", + // + // Following names appears in unix nl_langinfo(CODESET)", + // They can be compiled as platform specific if necessary", + // DONT put things here if it does not look generic enough (like hp15CN)", + // + "iso88591" => "ISO-8859-1", + "iso88592" => "ISO-8859-2", + "iso88593" => "ISO-8859-3", + "iso88594" => "ISO-8859-4", + "iso88595" => "ISO-8859-5", + "iso88596" => "ISO-8859-6", + "iso88597" => "ISO-8859-7", + "iso88598" => "ISO-8859-8", + "iso88599" => "ISO-8859-9", + "iso885910" => "ISO-8859-10", + "iso885911" => "ISO-8859-11", + "iso885912" => "ISO-8859-12", + "iso885913" => "ISO-8859-13", + "iso885914" => "ISO-8859-14", + "iso885915" => "ISO-8859-15", + "cp1250" => "windows-1250", + "cp1251" => "windows-1251", + "cp1252" => "windows-1252", + "cp1253" => "windows-1253", + "cp1254" => "windows-1254", + "cp1255" => "windows-1255", + "cp1256" => "windows-1256", + "cp1257" => "windows-1257", + "cp1258" => "windows-1258", + "x-gbk" => "gbk", + "windows-936" => "gbk", + "ansi-1251" => "windows-1251", + ]; + + /** + * Returns proper encoding mapping, if exsists. If it doesn't, return unchanged $encoding + * @param string $encoding + * @param string|null $fallback + * + * @return string + */ + public static function get($encoding, $fallback = null) { + if (isset(self::$aliases[strtolower($encoding)])) { + return self::$aliases[strtolower($encoding)]; + } + return $fallback !== null ? $fallback : $encoding; + } + +} diff --git a/htdocs/includes/webklex/php-imap/src/Events/Event.php b/htdocs/includes/webklex/php-imap/src/Events/Event.php new file mode 100644 index 00000000000..921f28b25ed --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/Events/Event.php @@ -0,0 +1,28 @@ +message = $arguments[0]; + $this->flag = $arguments[1]; + } +} diff --git a/htdocs/includes/webklex/php-imap/src/Events/FolderDeletedEvent.php b/htdocs/includes/webklex/php-imap/src/Events/FolderDeletedEvent.php new file mode 100644 index 00000000000..89b5083f975 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/Events/FolderDeletedEvent.php @@ -0,0 +1,22 @@ +old_folder = $folders[0]; + $this->new_folder = $folders[1]; + } +} diff --git a/htdocs/includes/webklex/php-imap/src/Events/FolderNewEvent.php b/htdocs/includes/webklex/php-imap/src/Events/FolderNewEvent.php new file mode 100644 index 00000000000..d16bbbd67b6 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/Events/FolderNewEvent.php @@ -0,0 +1,35 @@ +folder = $folders[0]; + } +} diff --git a/htdocs/includes/webklex/php-imap/src/Events/MessageCopiedEvent.php b/htdocs/includes/webklex/php-imap/src/Events/MessageCopiedEvent.php new file mode 100644 index 00000000000..a6a3a447f50 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/Events/MessageCopiedEvent.php @@ -0,0 +1,22 @@ +old_message = $messages[0]; + $this->new_message = $messages[1]; + } +} diff --git a/htdocs/includes/webklex/php-imap/src/Events/MessageNewEvent.php b/htdocs/includes/webklex/php-imap/src/Events/MessageNewEvent.php new file mode 100644 index 00000000000..1487e28d6bd --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/Events/MessageNewEvent.php @@ -0,0 +1,35 @@ +message = $messages[0]; + } +} diff --git a/htdocs/includes/webklex/php-imap/src/Events/MessageRestoredEvent.php b/htdocs/includes/webklex/php-imap/src/Events/MessageRestoredEvent.php new file mode 100644 index 00000000000..25b6520a740 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/Events/MessageRestoredEvent.php @@ -0,0 +1,22 @@ +client = $client; + + $this->events["message"] = $client->getDefaultEvents("message"); + $this->events["folder"] = $client->getDefaultEvents("folder"); + + $this->setDelimiter($delimiter); + $this->path = $folder_name; + $this->full_name = $this->decodeName($folder_name); + $this->name = $this->getSimpleName($this->delimiter, $this->full_name); + + $this->parseAttributes($attributes); + } + + /** + * Get a new search query instance + * @param string $charset + * + * @return WhereQuery + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + public function query($charset = 'UTF-8'){ + $this->getClient()->checkConnection(); + $this->getClient()->openFolder($this->path); + + return new WhereQuery($this->getClient(), $charset); + } + + /** + * @inheritdoc self::query($charset = 'UTF-8') + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + public function search($charset = 'UTF-8'){ + return $this->query($charset); + } + + /** + * @inheritdoc self::query($charset = 'UTF-8') + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + public function messages($charset = 'UTF-8'){ + return $this->query($charset); + } + + /** + * Determine if folder has children. + * + * @return bool + */ + public function hasChildren() { + return $this->has_children; + } + + /** + * Set children. + * @param FolderCollection|array $children + * + * @return self + */ + public function setChildren($children = []) { + $this->children = $children; + + return $this; + } + + /** + * Decode name. + * It converts UTF7-IMAP encoding to UTF-8. + * @param $name + * + * @return mixed|string + */ + protected function decodeName($name) { + return mb_convert_encoding($name, "UTF-8", "UTF7-IMAP"); + } + + /** + * Get simple name (without parent folders). + * @param $delimiter + * @param $full_name + * + * @return mixed + */ + protected function getSimpleName($delimiter, $full_name) { + $arr = explode($delimiter, $full_name); + + return end($arr); + } + + /** + * Parse attributes and set it to object properties. + * @param $attributes + */ + protected function parseAttributes($attributes) { + $this->no_inferiors = in_array('\NoInferiors', $attributes) ? true : false; + $this->no_select = in_array('\NoSelect', $attributes) ? true : false; + $this->marked = in_array('\Marked', $attributes) ? true : false; + $this->referral = in_array('\Referral', $attributes) ? true : false; + $this->has_children = in_array('\HasChildren', $attributes) ? true : false; + } + + /** + * Move or rename the current folder + * @param string $new_name + * @param boolean $expunge + * + * @return bool + * @throws ConnectionFailedException + * @throws Exceptions\EventNotFoundException + * @throws Exceptions\FolderFetchingException + * @throws Exceptions\RuntimeException + */ + public function move($new_name, $expunge = true) { + $this->client->checkConnection(); + $status = $this->client->getConnection()->renameFolder($this->full_name, $new_name); + if($expunge) $this->client->expunge(); + + $folder = $this->client->getFolder($new_name); + $event = $this->getEvent("folder", "moved"); + $event::dispatch($this, $folder); + + return $status; + } + + /** + * Get a message overview + * @param string|null $sequence uid sequence + * + * @return array + * @throws ConnectionFailedException + * @throws Exceptions\InvalidMessageDateException + * @throws Exceptions\MessageNotFoundException + * @throws Exceptions\RuntimeException + */ + public function overview($sequence = null){ + $this->client->openFolder($this->path); + $sequence = $sequence === null ? "1:*" : $sequence; + $uid = ClientManager::get('options.sequence', IMAP::ST_MSGN) == IMAP::ST_UID; + return $this->client->getConnection()->overview($sequence, $uid); + } + + /** + * Append a string message to the current mailbox + * @param string $message + * @param string $options + * @param string $internal_date + * + * @return bool + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + public function appendMessage($message, $options = null, $internal_date = null) { + /** + * Check if $internal_date is parsed. If it is null it should not be set. Otherwise the message can't be stored. + * If this parameter is set, it will set the INTERNALDATE on the appended message. The parameter should be a + * date string that conforms to the rfc2060 specifications for a date_time value or be a Carbon object. + */ + + if ($internal_date != null) { + if ($internal_date instanceof Carbon){ + $internal_date = $internal_date->format('d-M-Y H:i:s O'); + } + } + + return $this->client->getConnection()->appendMessage($this->full_name, $message, $options, $internal_date); + } + + /** + * Rename the current folder + * @param string $new_name + * @param boolean $expunge + * + * @return bool + * @throws ConnectionFailedException + * @throws Exceptions\EventNotFoundException + * @throws Exceptions\FolderFetchingException + * @throws Exceptions\RuntimeException + */ + public function rename($new_name, $expunge = true) { + return $this->move($new_name, $expunge); + } + + /** + * Delete the current folder + * @param boolean $expunge + * + * @return bool + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\RuntimeException + * @throws Exceptions\EventNotFoundException + */ + public function delete($expunge = true) { + $status = $this->client->getConnection()->deleteFolder($this->path); + if($expunge) $this->client->expunge(); + + $event = $this->getEvent("folder", "deleted"); + $event::dispatch($this); + + return $status; + } + + /** + * Subscribe the current folder + * + * @return bool + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + public function subscribe() { + $this->client->openFolder($this->path); + return $this->client->getConnection()->subscribeFolder($this->path); + } + + /** + * Unsubscribe the current folder + * + * @return bool + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + public function unsubscribe() { + $this->client->openFolder($this->path); + return $this->client->getConnection()->unsubscribeFolder($this->path); + } + + /** + * Idle the current connection + * @param callable $callback + * @param integer $timeout max 1740 seconds - recommended by rfc2177 §3 + * @param boolean $auto_reconnect try to reconnect on connection close + * + * @throws ConnectionFailedException + * @throws Exceptions\InvalidMessageDateException + * @throws Exceptions\MessageContentFetchingException + * @throws Exceptions\MessageHeaderFetchingException + * @throws Exceptions\RuntimeException + * @throws Exceptions\EventNotFoundException + * @throws Exceptions\MessageFlagException + * @throws Exceptions\MessageNotFoundException + */ + public function idle(callable $callback, $timeout = 1200, $auto_reconnect = false) { + $this->client->getConnection()->setConnectionTimeout($timeout); + + $this->client->reconnect(); + $this->client->openFolder($this->path, true); + $connection = $this->client->getConnection(); + + $sequence = ClientManager::get('options.sequence', IMAP::ST_MSGN); + $connection->idle(); + + while (true) { + try { + $line = $connection->nextLine(); + if (($pos = strpos($line, "EXISTS")) !== false) { + $msgn = (int) substr($line, 2, $pos -2); + $connection->done(); + + $this->client->openFolder($this->path, true); + $message = $this->query()->getMessageByMsgn($msgn); + $message->setSequence($sequence); + $callback($message); + + $event = $this->getEvent("message", "new"); + $event::dispatch($message); + + $connection->idle(); + } + }catch (Exceptions\RuntimeException $e) { + if(strpos($e->getMessage(), "connection closed") === false) { + throw $e; + } + if ($auto_reconnect === true) { + $this->client->reconnect(); + $this->client->openFolder($this->path, true); + + $connection = $this->client->getConnection(); + $connection->idle(); + } + } + } + } + + /** + * Get folder status information + * + * @return array|bool + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + public function getStatus() { + return $this->examine(); + } + + /** + * Examine the current folder + * + * @return array + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + public function examine() { + return $this->client->getConnection()->examineFolder($this->path); + } + + /** + * Get the current Client instance + * + * @return Client + */ + public function getClient() { + return $this->client; + } + + /** + * Set the delimiter + * @param $delimiter + */ + public function setDelimiter($delimiter){ + if(in_array($delimiter, [null, '', ' ', false]) === true) { + $delimiter = ClientManager::get('options.delimiter', '/'); + } + + $this->delimiter = $delimiter; + } +} diff --git a/htdocs/includes/webklex/php-imap/src/Header.php b/htdocs/includes/webklex/php-imap/src/Header.php new file mode 100644 index 00000000000..9fecd69fa3c --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/Header.php @@ -0,0 +1,753 @@ +raw = $raw_header; + $this->config = ClientManager::get('options'); + $this->attributize = $attributize; + $this->parse(); + } + + /** + * Call dynamic attribute setter and getter methods + * @param string $method + * @param array $arguments + * + * @return Attribute|mixed + * @throws MethodNotFoundException + */ + public function __call($method, $arguments) { + if(strtolower(substr($method, 0, 3)) === 'get') { + $name = preg_replace('/(.)(?=[A-Z])/u', '$1_', substr(strtolower($method), 3)); + + if(in_array($name, array_keys($this->attributes))) { + return $this->attributes[$name]; + } + + } + + throw new MethodNotFoundException("Method ".self::class.'::'.$method.'() is not supported'); + } + + /** + * Magic getter + * @param $name + * + * @return Attribute|null + */ + public function __get($name) { + return $this->get($name); + } + + /** + * Get a specific header attribute + * @param $name + * + * @return Attribute|mixed + */ + public function get($name) { + if(isset($this->attributes[$name])) { + return $this->attributes[$name]; + } + + return null; + } + + /** + * Set a specific attribute + * @param string $name + * @param array|mixed $value + * @param boolean $strict + * + * @return Attribute + */ + public function set($name, $value, $strict = false) { + if(isset($this->attributes[$name]) && $strict === false) { + if ($this->attributize) { + $this->attributes[$name]->add($value, true); + }else{ + if(isset($this->attributes[$name])) { + if (is_array($this->attributes[$name]) == false) { + $this->attributes[$name] = [$this->attributes[$name], $value]; + }else{ + $this->attributes[$name][] = $value; + } + }else{ + $this->attributes[$name] = $value; + } + } + }elseif($this->attributize == false){ + $this->attributes[$name] = $value; + }else{ + $this->attributes[$name] = new Attribute($name, $value); + } + + return $this->attributes[$name]; + } + + /** + * Perform a regex match all on the raw header and return the first result + * @param $pattern + * + * @return mixed|null + */ + public function find($pattern) { + if (preg_match_all($pattern, $this->raw, $matches)) { + if (isset($matches[1])) { + if(count($matches[1]) > 0) { + return $matches[1][0]; + } + } + } + return null; + } + + /** + * Try to find a boundary if possible + * + * @return string|null + */ + public function getBoundary(){ + $boundary = $this->find("/boundary\=(.*)/i"); + + if ($boundary === null) { + return null; + } + + return $this->clearBoundaryString($boundary); + } + + /** + * Remove all unwanted chars from a given boundary + * @param string $str + * + * @return string + */ + private function clearBoundaryString($str) { + return str_replace(['"', '\r', '\n', "\n", "\r", ";", "\s"], "", $str); + } + + /** + * Parse the raw headers + * + * @throws InvalidMessageDateException + */ + protected function parse(){ + $header = $this->rfc822_parse_headers($this->raw); + + $this->extractAddresses($header); + + if (property_exists($header, 'subject')) { + $this->set("subject", $this->decode($header->subject)); + } + if (property_exists($header, 'references')) { + $this->set("references", $this->decode($header->references)); + } + if (property_exists($header, 'message_id')) { + $this->set("message_id", str_replace(['<', '>'], '', $header->message_id)); + } + + $this->parseDate($header); + foreach ($header as $key => $value) { + $key = trim(rtrim(strtolower($key))); + if(!isset($this->attributes[$key])){ + $this->set($key, $value); + } + } + + $this->extractHeaderExtensions(); + $this->findPriority(); + } + + /** + * Parse mail headers from a string + * @link https://php.net/manual/en/function.imap-rfc822-parse-headers.php + * @param $raw_headers + * + * @return object + */ + public function rfc822_parse_headers($raw_headers){ + $headers = []; + $imap_headers = []; + if (extension_loaded('imap') && $this->config["rfc822"]) { + $raw_imap_headers = (array) \imap_rfc822_parse_headers($this->raw); + foreach($raw_imap_headers as $key => $values) { + $key = str_replace("-", "_", $key); + $imap_headers[$key] = $values; + } + } + $lines = explode("\r\n", str_replace("\r\n\t", ' ', $raw_headers)); + $prev_header = null; + foreach($lines as $line) { + if (substr($line, 0, 1) === "\n") { + $line = substr($line, 1); + } + + if (substr($line, 0, 1) === "\t") { + $line = substr($line, 1); + $line = trim(rtrim($line)); + if ($prev_header !== null) { + $headers[$prev_header][] = $line; + } + }elseif (substr($line, 0, 1) === " ") { + $line = substr($line, 1); + $line = trim(rtrim($line)); + if ($prev_header !== null) { + if (!isset($headers[$prev_header])) { + $headers[$prev_header] = ""; + } + if (is_array($headers[$prev_header])) { + $headers[$prev_header][] = $line; + }else{ + $headers[$prev_header] .= $line; + } + } + }else{ + if (($pos = strpos($line, ":")) > 0) { + $key = trim(rtrim(strtolower(substr($line, 0, $pos)))); + $key = str_replace("-", "_", $key); + + $value = trim(rtrim(substr($line, $pos + 1))); + if (isset($headers[$key])) { + $headers[$key][] = $value; + }else{ + $headers[$key] = [$value]; + } + $prev_header = $key; + } + } + } + + foreach($headers as $key => $values) { + if (isset($imap_headers[$key])) continue; + $value = null; + switch($key){ + case 'from': + case 'to': + case 'cc': + case 'bcc': + case 'reply_to': + case 'sender': + $value = $this->decodeAddresses($values); + $headers[$key."address"] = implode(", ", $values); + break; + case 'subject': + $value = implode(" ", $values); + break; + default: + if (is_array($values)) { + foreach($values as $k => $v) { + if ($v == "") { + unset($values[$k]); + } + } + $available_values = count($values); + if ($available_values === 1) { + $value = array_pop($values); + } elseif ($available_values === 2) { + $value = implode(" ", $values); + } elseif ($available_values > 2) { + $value = array_values($values); + } else { + $value = ""; + } + } + break; + } + $headers[$key] = $value; + } + + return (object) array_merge($headers, $imap_headers); + } + + /** + * Decode MIME header elements + * @link https://php.net/manual/en/function.imap-mime-header-decode.php + * @param string $text The MIME text + * + * @return array The decoded elements are returned in an array of objects, where each + * object has two properties, charset and text. + */ + public function mime_header_decode($text){ + if (extension_loaded('imap')) { + return \imap_mime_header_decode($text); + } + $charset = $this->getEncoding($text); + return [(object)[ + "charset" => $charset, + "text" => $this->convertEncoding($text, $charset) + ]]; + } + + /** + * Check if a given pair of strings has ben decoded + * @param $encoded + * @param $decoded + * + * @return bool + */ + private function notDecoded($encoded, $decoded) { + return 0 === strpos($decoded, '=?') + && strlen($decoded) - 2 === strpos($decoded, '?=') + && false !== strpos($encoded, $decoded); + } + + /** + * Convert the encoding + * @param $str + * @param string $from + * @param string $to + * + * @return mixed|string + */ + public function convertEncoding($str, $from = "ISO-8859-2", $to = "UTF-8") { + + $from = EncodingAliases::get($from, $this->fallback_encoding); + $to = EncodingAliases::get($to, $this->fallback_encoding); + + if ($from === $to) { + return $str; + } + + // We don't need to do convertEncoding() if charset is ASCII (us-ascii): + // ASCII is a subset of UTF-8, so all ASCII files are already UTF-8 encoded + // https://stackoverflow.com/a/11303410 + // + // us-ascii is the same as ASCII: + // ASCII is the traditional name for the encoding system; the Internet Assigned Numbers Authority (IANA) + // prefers the updated name US-ASCII, which clarifies that this system was developed in the US and + // based on the typographical symbols predominantly in use there. + // https://en.wikipedia.org/wiki/ASCII + // + // convertEncoding() function basically means convertToUtf8(), so when we convert ASCII string into UTF-8 it gets broken. + if (strtolower($from) == 'us-ascii' && $to == 'UTF-8') { + return $str; + } + + try { + if (function_exists('iconv') && $from != 'UTF-7' && $to != 'UTF-7') { + return iconv($from, $to, $str); + } else { + if (!$from) { + return mb_convert_encoding($str, $to); + } + return mb_convert_encoding($str, $to, $from); + } + } catch (\Exception $e) { + if (strstr($from, '-')) { + $from = str_replace('-', '', $from); + return $this->convertEncoding($str, $from, $to); + } else { + return $str; + } + } + } + + /** + * Get the encoding of a given abject + * @param object|string $structure + * + * @return string + */ + public function getEncoding($structure) { + if (property_exists($structure, 'parameters')) { + foreach ($structure->parameters as $parameter) { + if (strtolower($parameter->attribute) == "charset") { + return EncodingAliases::get($parameter->value, $this->fallback_encoding); + } + } + }elseif (property_exists($structure, 'charset')) { + return EncodingAliases::get($structure->charset, $this->fallback_encoding); + }elseif (is_string($structure) === true){ + return mb_detect_encoding($structure); + } + + return $this->fallback_encoding; + } + + /** + * Test if a given value is utf-8 encoded + * @param $value + * + * @return bool + */ + private function is_uft8($value) { + return strpos(strtolower($value), '=?utf-8?') === 0; + } + + /** + * Try to decode a specific header + * @param mixed $value + * + * @return mixed + */ + private function decode($value) { + if (is_array($value)) { + return $this->decodeArray($value); + } + $original_value = $value; + $decoder = $this->config['decoder']['message']; + + if ($value !== null) { + $is_utf8_base = $this->is_uft8($value); + + if($decoder === 'utf-8' && extension_loaded('imap')) { + $value = \imap_utf8($value); + $is_utf8_base = $this->is_uft8($value); + if ($is_utf8_base) { + $value = mb_decode_mimeheader($value); + } + if ($this->notDecoded($original_value, $value)) { + $decoded_value = $this->mime_header_decode($value); + if (count($decoded_value) > 0) { + if(property_exists($decoded_value[0], "text")) { + $value = $decoded_value[0]->text; + } + } + } + }elseif($decoder === 'iconv' && $is_utf8_base) { + $value = iconv_mime_decode($value); + }elseif($is_utf8_base){ + $value = mb_decode_mimeheader($value); + } + + if ($this->is_uft8($value)) { + $value = mb_decode_mimeheader($value); + } + + if ($this->notDecoded($original_value, $value)) { + $value = $this->convertEncoding($original_value, $this->getEncoding($original_value)); + } + } + + return $value; + } + + /** + * Decode a given array + * @param array $values + * + * @return array + */ + private function decodeArray($values) { + foreach($values as $key => $value) { + $values[$key] = $this->decode($value); + } + return $values; + } + + /** + * Try to extract the priority from a given raw header string + */ + private function findPriority() { + if(($priority = $this->get("x_priority")) === null) return; + switch((int)"$priority"){ + case IMAP::MESSAGE_PRIORITY_HIGHEST; + $priority = IMAP::MESSAGE_PRIORITY_HIGHEST; + break; + case IMAP::MESSAGE_PRIORITY_HIGH; + $priority = IMAP::MESSAGE_PRIORITY_HIGH; + break; + case IMAP::MESSAGE_PRIORITY_NORMAL; + $priority = IMAP::MESSAGE_PRIORITY_NORMAL; + break; + case IMAP::MESSAGE_PRIORITY_LOW; + $priority = IMAP::MESSAGE_PRIORITY_LOW; + break; + case IMAP::MESSAGE_PRIORITY_LOWEST; + $priority = IMAP::MESSAGE_PRIORITY_LOWEST; + break; + default: + $priority = IMAP::MESSAGE_PRIORITY_UNKNOWN; + break; + } + + $this->set("priority", $priority); + } + + /** + * Extract a given part as address array from a given header + * @param $values + * + * @return array + */ + private function decodeAddresses($values) { + $addresses = []; + + if (extension_loaded('mailparse') && $this->config["rfc822"]) { + foreach ($values as $address) { + foreach (\mailparse_rfc822_parse_addresses($address) as $parsed_address) { + if (isset($parsed_address['address'])) { + $mail_address = explode('@', $parsed_address['address']); + if (count($mail_address) == 2) { + $addresses[] = (object)[ + "personal" => isset($parsed_address['display']) ? $parsed_address['display'] : '', + "mailbox" => $mail_address[0], + "host" => $mail_address[1], + ]; + } + } + } + } + + return $addresses; + } + + foreach($values as $address) { + foreach (preg_split('/, (?=(?:[^"]*"[^"]*")*[^"]*$)/', $address) as $split_address) { + $split_address = trim(rtrim($split_address)); + + if (strpos($split_address, ",") == strlen($split_address) - 1) { + $split_address = substr($split_address, 0, -1); + } + if (preg_match( + '/^(?:(?P.+)\s)?(?(name)<|[^\s]+?)(?(name)>|>?)$/', + $split_address, + $matches + )) { + $name = trim(rtrim($matches["name"])); + $email = trim(rtrim($matches["email"])); + list($mailbox, $host) = array_pad(explode("@", $email), 2, null); + $addresses[] = (object)[ + "personal" => $name, + "mailbox" => $mailbox, + "host" => $host, + ]; + } + } + } + + return $addresses; + } + + /** + * Extract a given part as address array from a given header + * @param object $header + */ + private function extractAddresses($header) { + foreach(['from', 'to', 'cc', 'bcc', 'reply_to', 'sender'] as $key){ + if (property_exists($header, $key)) { + $this->set($key, $this->parseAddresses($header->$key)); + } + } + } + + /** + * Parse Addresses + * @param $list + * + * @return array + */ + private function parseAddresses($list) { + $addresses = []; + + if (is_array($list) === false) { + return $addresses; + } + + foreach ($list as $item) { + $address = (object) $item; + + if (!property_exists($address, 'mailbox')) { + $address->mailbox = false; + } + if (!property_exists($address, 'host')) { + $address->host = false; + } + if (!property_exists($address, 'personal')) { + $address->personal = false; + } else { + $personalParts = $this->mime_header_decode($address->personal); + + if(is_array($personalParts)) { + $address->personal = ''; + foreach ($personalParts as $p) { + $address->personal .= $this->convertEncoding($p->text, $this->getEncoding($p)); + } + } + + if (strpos($address->personal, "'") === 0) { + $address->personal = str_replace("'", "", $address->personal); + } + } + + $address->mail = ($address->mailbox && $address->host) ? $address->mailbox.'@'.$address->host : false; + $address->full = ($address->personal) ? $address->personal.' <'.$address->mail.'>' : $address->mail; + + $addresses[] = new Address($address); + } + + return $addresses; + } + + /** + * Search and extract potential header extensions + */ + private function extractHeaderExtensions(){ + foreach ($this->attributes as $key => $value) { + if (is_array($value)) { + $value = implode(", ", $value); + }else{ + $value = (string)$value; + } + // Only parse strings and don't parse any attributes like the user-agent + if (in_array($key, ["user_agent"]) === false) { + if (($pos = strpos($value, ";")) !== false){ + $original = substr($value, 0, $pos); + $this->set($key, trim(rtrim($original)), true); + + // Get all potential extensions + $extensions = explode(";", substr($value, $pos + 1)); + foreach($extensions as $extension) { + if (($pos = strpos($extension, "=")) !== false){ + $key = substr($extension, 0, $pos); + $key = trim(rtrim(strtolower($key))); + + if (isset($this->attributes[$key]) === false) { + $value = substr($extension, $pos + 1); + $value = str_replace('"', "", $value); + $value = trim(rtrim($value)); + + $this->set($key, $value); + } + } + } + } + } + } + } + + /** + * Exception handling for invalid dates + * + * Currently known invalid formats: + * ^ Datetime ^ Problem ^ Cause + * | Mon, 20 Nov 2017 20:31:31 +0800 (GMT+8:00) | Double timezone specification | A Windows feature + * | Thu, 8 Nov 2018 08:54:58 -0200 (-02) | + * | | and invalid timezone (max 6 char) | + * | 04 Jan 2018 10:12:47 UT | Missing letter "C" | Unknown + * | Thu, 31 May 2018 18:15:00 +0800 (added by) | Non-standard details added by the | Unknown + * | | mail server | + * | Sat, 31 Aug 2013 20:08:23 +0580 | Invalid timezone | PHPMailer bug https://sourceforge.net/p/phpmailer/mailman/message/6132703/ + * + * Please report any new invalid timestamps to [#45](https://github.com/Webklex/php-imap/issues) + * + * @param object $header + * + * @throws InvalidMessageDateException + */ + private function parseDate($header) { + + if (property_exists($header, 'date')) { + $parsed_date = null; + $date = $header->date; + + if(preg_match('/\+0580/', $date)) { + $date = str_replace('+0580', '+0530', $date); + } + + $date = trim(rtrim($date)); + try { + $parsed_date = Carbon::parse($date); + } catch (\Exception $e) { + switch (true) { + case preg_match('/([0-9]{1,2}\ [A-Z]{2,3}\ [0-9]{4}\ [0-9]{1,2}\:[0-9]{1,2}\:[0-9]{1,2}\ UT)+$/i', $date) > 0: + case preg_match('/([A-Z]{2,3}\,\ [0-9]{1,2}\ [A-Z]{2,3}\ [0-9]{4}\ [0-9]{1,2}\:[0-9]{1,2}\:[0-9]{1,2}\ UT)+$/i', $date) > 0: + $date .= 'C'; + break; + case preg_match('/([A-Z]{2,3}\,\ [0-9]{1,2}\ [A-Z]{2,3}\ [0-9]{4}\ [0-9]{1,2}\:[0-9]{1,2}\:[0-9]{1,2}\ \+[0-9]{2,4}\ \(\+[0-9]{1,2}\))+$/i', $date) > 0: + case preg_match('/([A-Z]{2,3}[\,|\ \,]\ [0-9]{1,2}\ [A-Z]{2,3}\ [0-9]{4}\ [0-9]{1,2}\:[0-9]{1,2}\:[0-9]{1,2}.*)+$/i', $date) > 0: + case preg_match('/([A-Z]{2,3}\,\ [0-9]{1,2}\ [A-Z]{2,3}\ [0-9]{4}\ [0-9]{1,2}\:[0-9]{1,2}\:[0-9]{1,2}\ [\-|\+][0-9]{4}\ \(.*)\)+$/i', $date) > 0: + case preg_match('/([A-Z]{2,3}\, \ [0-9]{1,2}\ [A-Z]{2,3}\ [0-9]{4}\ [0-9]{1,2}\:[0-9]{1,2}\:[0-9]{1,2}\ [\-|\+][0-9]{4}\ \(.*)\)+$/i', $date) > 0: + case preg_match('/([0-9]{1,2}\ [A-Z]{2,3}\ [0-9]{2,4}\ [0-9]{2}\:[0-9]{2}\:[0-9]{2}\ [A-Z]{2}\ \-[0-9]{2}\:[0-9]{2}\ \([A-Z]{2,3}\ \-[0-9]{2}:[0-9]{2}\))+$/i', $date) > 0: + $array = explode('(', $date); + $array = array_reverse($array); + $date = trim(array_pop($array)); + break; + } + try{ + $parsed_date = Carbon::parse($date); + } catch (\Exception $_e) { + throw new InvalidMessageDateException("Invalid message date. ID:".$this->get("message_id"), 1100, $e); + } + } + + $this->set("date", $parsed_date); + } + } + + /** + * Get all available attributes + * + * @return array + */ + public function getAttributes() { + return $this->attributes; + } + +} diff --git a/htdocs/includes/webklex/php-imap/src/IMAP.php b/htdocs/includes/webklex/php-imap/src/IMAP.php new file mode 100644 index 00000000000..41ae8248b61 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/IMAP.php @@ -0,0 +1,375 @@ +imap_close + * @link http://php.net/manual/en/imap.constants.php + */ + const CL_EXPUNGE = 32768; + + /** + * The parameter is a UID + * @link http://php.net/manual/en/imap.constants.php + */ + const FT_UID = 1; + + /** + * Do not set the \Seen flag if not already set + * @link http://php.net/manual/en/imap.constants.php + */ + const FT_PEEK = 2; + const FT_NOT = 4; + + /** + * The return string is in internal format, will not canonicalize to CRLF. + * @link http://php.net/manual/en/imap.constants.php + */ + const FT_INTERNAL = 8; + const FT_PREFETCHTEXT = 32; + + /** + * The sequence argument contains UIDs instead of sequence numbers + * @link http://php.net/manual/en/imap.constants.php + */ + const ST_UID = 1; + const ST_SILENT = 2; + const ST_MSGN = 3; + const ST_SET = 4; + + /** + * the sequence numbers contain UIDS + * @link http://php.net/manual/en/imap.constants.php + */ + const CP_UID = 1; + + /** + * Delete the messages from the current mailbox after copying + * with imap_mail_copy + * @link http://php.net/manual/en/imap.constants.php + */ + const CP_MOVE = 2; + + /** + * Return UIDs instead of sequence numbers + * @link http://php.net/manual/en/imap.constants.php + */ + const SE_UID = 1; + const SE_FREE = 2; + + /** + * Don't prefetch searched messages + * @link http://php.net/manual/en/imap.constants.php + */ + const SE_NOPREFETCH = 4; + const SO_FREE = 8; + const SO_NOSERVER = 16; + const SA_MESSAGES = 1; + const SA_RECENT = 2; + const SA_UNSEEN = 4; + const SA_UIDNEXT = 8; + const SA_UIDVALIDITY = 16; + const SA_ALL = 31; + + /** + * This mailbox has no "children" (there are no + * mailboxes below this one). + * @link http://php.net/manual/en/imap.constants.php + */ + const LATT_NOINFERIORS = 1; + + /** + * This is only a container, not a mailbox - you + * cannot open it. + * @link http://php.net/manual/en/imap.constants.php + */ + const LATT_NOSELECT = 2; + + /** + * This mailbox is marked. Only used by UW-IMAPD. + * @link http://php.net/manual/en/imap.constants.php + */ + const LATT_MARKED = 4; + + /** + * This mailbox is not marked. Only used by + * UW-IMAPD. + * @link http://php.net/manual/en/imap.constants.php + */ + const LATT_UNMARKED = 8; + const LATT_REFERRAL = 16; + const LATT_HASCHILDREN = 32; + const LATT_HASNOCHILDREN = 64; + + /** + * Sort criteria for imap_sort: + * message Date + * @link http://php.net/manual/en/imap.constants.php + */ + const SORTDATE = 0; + + /** + * Sort criteria for imap_sort: + * arrival date + * @link http://php.net/manual/en/imap.constants.php + */ + const SORTARRIVAL = 1; + + /** + * Sort criteria for imap_sort: + * mailbox in first From address + * @link http://php.net/manual/en/imap.constants.php + */ + const SORTFROM = 2; + + /** + * Sort criteria for imap_sort: + * message subject + * @link http://php.net/manual/en/imap.constants.php + */ + const SORTSUBJECT = 3; + + /** + * Sort criteria for imap_sort: + * mailbox in first To address + * @link http://php.net/manual/en/imap.constants.php + */ + const SORTTO = 4; + + /** + * Sort criteria for imap_sort: + * mailbox in first cc address + * @link http://php.net/manual/en/imap.constants.php + */ + const SORTCC = 5; + + /** + * Sort criteria for imap_sort: + * size of message in octets + * @link http://php.net/manual/en/imap.constants.php + */ + const SORTSIZE = 6; + const TYPETEXT = 0; + const TYPEMULTIPART = 1; + const TYPEMESSAGE = 2; + const TYPEAPPLICATION = 3; + const TYPEAUDIO = 4; + const TYPEIMAGE = 5; + const TYPEVIDEO = 6; + const TYPEMODEL = 7; + const TYPEOTHER = 8; + const ENC7BIT = 0; + const ENC8BIT = 1; + const ENCBINARY = 2; + const ENCBASE64 = 3; + const ENCQUOTEDPRINTABLE = 4; + const ENCOTHER = 5; + + /** + * Garbage collector, clear message cache elements. + * @link http://php.net/manual/en/imap.constants.php + */ + const IMAP_GC_ELT = 1; + + /** + * Garbage collector, clear envelopes and bodies. + * @link http://php.net/manual/en/imap.constants.php + */ + const IMAP_GC_ENV = 2; + + /** + * Garbage collector, clear texts. + * @link http://php.net/manual/en/imap.constants.php + */ + const IMAP_GC_TEXTS = 4; + +} \ No newline at end of file diff --git a/htdocs/includes/webklex/php-imap/src/Message.php b/htdocs/includes/webklex/php-imap/src/Message.php new file mode 100755 index 00000000000..90ed1a89141 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/Message.php @@ -0,0 +1,1419 @@ +boot(); + + $default_mask = $client->getDefaultMessageMask(); + if($default_mask != null) { + $this->mask = $default_mask; + } + $this->events["message"] = $client->getDefaultEvents("message"); + $this->events["flag"] = $client->getDefaultEvents("flag"); + + $this->folder_path = $client->getFolderPath(); + + $this->setSequence($sequence); + $this->setFetchOption($fetch_options); + $this->setFetchBodyOption($fetch_body); + $this->setFetchFlagsOption($fetch_flags); + + $this->client = $client; + $this->client->openFolder($this->folder_path); + + $this->setSequenceId($uid, $msglist); + + if ($this->fetch_options == IMAP::FT_PEEK) { + $this->parseFlags(); + } + + $this->parseHeader(); + + if ($this->getFetchBodyOption() === true) { + $this->parseBody(); + } + + if ($this->getFetchFlagsOption() === true && $this->fetch_options !== IMAP::FT_PEEK) { + $this->parseFlags(); + } + } + + /** + * Create a new instance without fetching the message header and providing them raw instead + * @param int $uid + * @param int|null $msglist + * @param Client $client + * @param string $raw_header + * @param string $raw_body + * @param array $raw_flags + * @param null $fetch_options + * @param null $sequence + * + * @return Message + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\EventNotFoundException + * @throws InvalidMessageDateException + * @throws MessageContentFetchingException + * @throws ReflectionException + * @throws MessageFlagException + * @throws Exceptions\RuntimeException + * @throws Exceptions\MessageNotFoundException + */ + public static function make($uid, $msglist, Client $client, $raw_header, $raw_body, $raw_flags, $fetch_options = null, $sequence = null){ + $reflection = new ReflectionClass(self::class); + /** @var self $instance */ + $instance = $reflection->newInstanceWithoutConstructor(); + $instance->boot(); + + $default_mask = $client->getDefaultMessageMask(); + if($default_mask != null) { + $instance->setMask($default_mask); + } + $instance->setEvents([ + "message" => $client->getDefaultEvents("message"), + "flag" => $client->getDefaultEvents("flag"), + ]); + $instance->setFolderPath($client->getFolderPath()); + $instance->setSequence($sequence); + $instance->setFetchOption($fetch_options); + + $instance->setClient($client); + $instance->setSequenceId($uid, $msglist); + + $instance->parseRawHeader($raw_header); + $instance->parseRawFlags($raw_flags); + $instance->parseRawBody($raw_body); + $instance->peek(); + + return $instance; + } + + /** + * Boot a new instance + */ + public function boot(){ + $this->attributes = []; + + $this->config = ClientManager::get('options'); + $this->available_flags = ClientManager::get('flags'); + + $this->attachments = AttachmentCollection::make([]); + $this->flags = FlagCollection::make([]); + } + + /** + * Call dynamic attribute setter and getter methods + * @param string $method + * @param array $arguments + * + * @return mixed + * @throws MethodNotFoundException + */ + public function __call($method, $arguments) { + if(strtolower(substr($method, 0, 3)) === 'get') { + $name = Str::snake(substr($method, 3)); + return $this->get($name); + }elseif (strtolower(substr($method, 0, 3)) === 'set') { + $name = Str::snake(substr($method, 3)); + + if(in_array($name, array_keys($this->attributes))) { + return $this->__set($name, array_pop($arguments)); + } + + } + + throw new MethodNotFoundException("Method ".self::class.'::'.$method.'() is not supported'); + } + + /** + * Magic setter + * @param $name + * @param $value + * + * @return mixed + */ + public function __set($name, $value) { + $this->attributes[$name] = $value; + + return $this->attributes[$name]; + } + + /** + * Magic getter + * @param $name + * + * @return Attribute|mixed|null + */ + public function __get($name) { + return $this->get($name); + } + + /** + * Get an available message or message header attribute + * @param $name + * + * @return Attribute|mixed|null + */ + public function get($name) { + if(isset($this->attributes[$name])) { + return $this->attributes[$name]; + } + + return $this->header->get($name); + } + + /** + * Check if the Message has a text body + * + * @return bool + */ + public function hasTextBody() { + return isset($this->bodies['text']); + } + + /** + * Get the Message text body + * + * @return mixed + */ + public function getTextBody() { + if (!isset($this->bodies['text'])) { + return null; + } + + return $this->bodies['text']; + } + + /** + * Check if the Message has a html body + * + * @return bool + */ + public function hasHTMLBody() { + return isset($this->bodies['html']); + } + + /** + * Get the Message html body + * + * @return string|null + */ + public function getHTMLBody() { + if (!isset($this->bodies['html'])) { + return null; + } + + return $this->bodies['html']; + } + + /** + * Parse all defined headers + * + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\RuntimeException + * @throws InvalidMessageDateException + * @throws MessageHeaderFetchingException + */ + private function parseHeader() { + $sequence_id = $this->getSequenceId(); + $headers = $this->client->getConnection()->headers([$sequence_id], "RFC822", $this->sequence === IMAP::ST_UID); + if (!isset($headers[$sequence_id])) { + throw new MessageHeaderFetchingException("no headers found", 0); + } + + $this->parseRawHeader($headers[$sequence_id]); + } + + /** + * @param string $raw_header + * + * @throws InvalidMessageDateException + */ + public function parseRawHeader($raw_header){ + $this->header = new Header($raw_header); + } + + /** + * Parse additional raw flags + * @param array $raw_flags + */ + public function parseRawFlags($raw_flags) { + $this->flags = FlagCollection::make([]); + + foreach($raw_flags as $flag) { + if (strpos($flag, "\\") === 0){ + $flag = substr($flag, 1); + } + $flag_key = strtolower($flag); + if ($this->available_flags === null || in_array($flag_key, $this->available_flags)) { + $this->flags->put($flag_key, $flag); + } + } + } + + /** + * Parse additional flags + * + * @return void + * @throws Exceptions\ConnectionFailedException + * @throws MessageFlagException + * @throws Exceptions\RuntimeException + */ + private function parseFlags() { + $this->client->openFolder($this->folder_path); + $this->flags = FlagCollection::make([]); + + $sequence_id = $this->getSequenceId(); + try { + $flags = $this->client->getConnection()->flags([$sequence_id], $this->sequence === IMAP::ST_UID); + } catch (Exceptions\RuntimeException $e) { + throw new MessageFlagException("flag could not be fetched", 0, $e); + } + + if (isset($flags[$sequence_id])) { + $this->parseRawFlags($flags[$sequence_id]); + } + } + + /** + * Parse the Message body + * + * @return $this + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\MessageContentFetchingException + * @throws InvalidMessageDateException + * @throws Exceptions\EventNotFoundException + * @throws MessageFlagException + * @throws Exceptions\RuntimeException + */ + public function parseBody() { + $this->client->openFolder($this->folder_path); + + $sequence_id = $this->getSequenceId(); + try { + $contents = $this->client->getConnection()->content([$sequence_id], "RFC822", $this->sequence === IMAP::ST_UID); + } catch (Exceptions\RuntimeException $e) { + throw new MessageContentFetchingException("failed to fetch content", 0); + } + if (!isset($contents[$sequence_id])) { + throw new MessageContentFetchingException("no content found", 0); + } + $content = $contents[$sequence_id]; + + $body = $this->parseRawBody($content); + $this->peek(); + + return $body; + } + + /** + * Handle auto "Seen" flag handling + * + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\EventNotFoundException + * @throws MessageFlagException + * @throws Exceptions\RuntimeException + */ + public function peek(){ + if ($this->fetch_options == IMAP::FT_PEEK) { + if ($this->getFlags()->get("seen") == null) { + $this->unsetFlag("Seen"); + } + }elseif ($this->getFlags()->get("seen") != null) { + $this->setFlag("Seen"); + } + } + + /** + * Parse a given message body + * @param string $raw_body + * + * @return $this + * @throws Exceptions\ConnectionFailedException + * @throws InvalidMessageDateException + * @throws MessageContentFetchingException + * @throws Exceptions\RuntimeException + */ + public function parseRawBody($raw_body) { + $this->structure = new Structure($raw_body, $this->header); + $this->fetchStructure($this->structure); + + return $this; + } + + /** + * Fetch the Message structure + * @param Structure $structure + * + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + private function fetchStructure($structure) { + $this->client->openFolder($this->folder_path); + + foreach ($structure->parts as $part) { + $this->fetchPart($part); + } + } + + /** + * Fetch a given part + * @param Part $part + */ + private function fetchPart(Part $part) { + if ($part->isAttachment()) { + $this->fetchAttachment($part); + }else{ + $encoding = $this->getEncoding($part); + + $content = $this->decodeString($part->content, $part->encoding); + + // We don't need to do convertEncoding() if charset is ASCII (us-ascii): + // ASCII is a subset of UTF-8, so all ASCII files are already UTF-8 encoded + // https://stackoverflow.com/a/11303410 + // + // us-ascii is the same as ASCII: + // ASCII is the traditional name for the encoding system; the Internet Assigned Numbers Authority (IANA) + // prefers the updated name US-ASCII, which clarifies that this system was developed in the US and + // based on the typographical symbols predominantly in use there. + // https://en.wikipedia.org/wiki/ASCII + // + // convertEncoding() function basically means convertToUtf8(), so when we convert ASCII string into UTF-8 it gets broken. + if ($encoding != 'us-ascii') { + $content = $this->convertEncoding($content, $encoding); + } + + $subtype = strtolower($part->subtype); + $subtype = $subtype == "plain" || $subtype == "" ? "text" : $subtype; + + if (isset($this->bodies[$subtype])) { + $this->bodies[$subtype] .= "\n".$content; + }else{ + $this->bodies[$subtype] = $content; + } + } + } + + /** + * Fetch the Message attachment + * @param Part $part + */ + protected function fetchAttachment($part) { + $oAttachment = new Attachment($this, $part); + + if ($oAttachment->getName() !== null && $oAttachment->getSize() > 0) { + if ($oAttachment->getId() !== null) { + $this->attachments->put($oAttachment->getId(), $oAttachment); + } else { + $this->attachments->push($oAttachment); + } + } + } + + /** + * Fail proof setter for $fetch_option + * @param $option + * + * @return $this + */ + public function setFetchOption($option) { + if (is_long($option) === true) { + $this->fetch_options = $option; + } elseif (is_null($option) === true) { + $config = ClientManager::get('options.fetch', IMAP::FT_UID); + $this->fetch_options = is_long($config) ? $config : 1; + } + + return $this; + } + + /** + * Set the sequence type + * @param int $sequence + * + * @return $this + */ + public function setSequence($sequence) { + if (is_long($sequence)) { + $this->sequence = $sequence; + } elseif (is_null($sequence)) { + $config = ClientManager::get('options.sequence', IMAP::ST_MSGN); + $this->sequence = is_long($config) ? $config : IMAP::ST_MSGN; + } + + return $this; + } + + /** + * Fail proof setter for $fetch_body + * @param $option + * + * @return $this + */ + public function setFetchBodyOption($option) { + if (is_bool($option)) { + $this->fetch_body = $option; + } elseif (is_null($option)) { + $config = ClientManager::get('options.fetch_body', true); + $this->fetch_body = is_bool($config) ? $config : true; + } + + return $this; + } + + /** + * Fail proof setter for $fetch_flags + * @param $option + * + * @return $this + */ + public function setFetchFlagsOption($option) { + if (is_bool($option)) { + $this->fetch_flags = $option; + } elseif (is_null($option)) { + $config = ClientManager::get('options.fetch_flags', true); + $this->fetch_flags = is_bool($config) ? $config : true; + } + + return $this; + } + + /** + * Decode a given string + * @param $string + * @param $encoding + * + * @return string + */ + public function decodeString($string, $encoding) { + switch ($encoding) { + case IMAP::MESSAGE_ENC_BINARY: + if (extension_loaded('imap')) { + return base64_decode(\imap_binary($string)); + } + return base64_decode($string); + case IMAP::MESSAGE_ENC_BASE64: + return base64_decode($string); + case IMAP::MESSAGE_ENC_QUOTED_PRINTABLE: + return quoted_printable_decode($string); + case IMAP::MESSAGE_ENC_8BIT: + case IMAP::MESSAGE_ENC_7BIT: + case IMAP::MESSAGE_ENC_OTHER: + default: + return $string; + } + } + + /** + * Convert the encoding + * @param $str + * @param string $from + * @param string $to + * + * @return mixed|string + */ + public function convertEncoding($str, $from = "ISO-8859-2", $to = "UTF-8") { + + $from = EncodingAliases::get($from); + $to = EncodingAliases::get($to); + + if ($from === $to) { + return $str; + } + + // We don't need to do convertEncoding() if charset is ASCII (us-ascii): + // ASCII is a subset of UTF-8, so all ASCII files are already UTF-8 encoded + // https://stackoverflow.com/a/11303410 + // + // us-ascii is the same as ASCII: + // ASCII is the traditional name for the encoding system; the Internet Assigned Numbers Authority (IANA) + // prefers the updated name US-ASCII, which clarifies that this system was developed in the US and + // based on the typographical symbols predominantly in use there. + // https://en.wikipedia.org/wiki/ASCII + // + // convertEncoding() function basically means convertToUtf8(), so when we convert ASCII string into UTF-8 it gets broken. + if (strtolower($from) == 'us-ascii' && $to == 'UTF-8') { + return $str; + } + + if (function_exists('iconv') && $from != 'UTF-7' && $to != 'UTF-7') { + return @iconv($from, $to.'//IGNORE', $str); + } else { + if (!$from) { + return mb_convert_encoding($str, $to); + } + return mb_convert_encoding($str, $to, $from); + } + } + + /** + * Get the encoding of a given abject + * @param object|string $structure + * + * @return string + */ + public function getEncoding($structure) { + if (property_exists($structure, 'parameters')) { + foreach ($structure->parameters as $parameter) { + if (strtolower($parameter->attribute) == "charset") { + return EncodingAliases::get($parameter->value); + } + } + }elseif (property_exists($structure, 'charset')){ + return EncodingAliases::get($structure->charset); + }elseif (is_string($structure) === true){ + return mb_detect_encoding($structure); + } + + return 'UTF-8'; + } + + /** + * Get the messages folder + * + * @return mixed + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\FolderFetchingException + * @throws Exceptions\RuntimeException + */ + public function getFolder(){ + return $this->client->getFolderByPath($this->folder_path); + } + + /** + * Create a message thread based on the current message + * @param Folder|null $sent_folder + * @param MessageCollection|null $thread + * @param Folder|null $folder + * + * @return MessageCollection|null + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\FolderFetchingException + * @throws Exceptions\GetMessagesFailedException + * @throws Exceptions\RuntimeException + */ + public function thread($sent_folder = null, &$thread = null, $folder = null){ + $thread = $thread ? $thread : MessageCollection::make([]); + $folder = $folder ? $folder : $this->getFolder(); + $sent_folder = $sent_folder ? $sent_folder : $this->client->getFolderByPath(ClientManager::get("options.common_folders.sent", "INBOX/Sent")); + + /** @var Message $message */ + foreach($thread as $message) { + if ($message->message_id->first() == $this->message_id->first()) { + return $thread; + } + } + $thread->push($this); + + $this->fetchThreadByInReplyTo($thread, $this->message_id, $folder, $folder, $sent_folder); + $this->fetchThreadByInReplyTo($thread, $this->message_id, $sent_folder, $folder, $sent_folder); + + if (is_array($this->in_reply_to)) { + foreach($this->in_reply_to as $in_reply_to) { + $this->fetchThreadByMessageId($thread, $in_reply_to, $folder, $folder, $sent_folder); + $this->fetchThreadByMessageId($thread, $in_reply_to, $sent_folder, $folder, $sent_folder); + } + } + + return $thread; + } + + /** + * Fetch a partial thread by message id + * @param MessageCollection $thread + * @param string $in_reply_to + * @param Folder $primary_folder + * @param Folder $secondary_folder + * @param Folder $sent_folder + * + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\GetMessagesFailedException + * @throws Exceptions\RuntimeException + */ + protected function fetchThreadByInReplyTo(&$thread, $in_reply_to, $primary_folder, $secondary_folder, $sent_folder){ + $primary_folder->query()->inReplyTo($in_reply_to) + ->setFetchBody($this->getFetchBodyOption()) + ->leaveUnread()->get()->each(function($message) use(&$thread, $secondary_folder, $sent_folder){ + /** @var Message $message */ + $message->thread($sent_folder, $thread, $secondary_folder); + }); + } + + /** + * Fetch a partial thread by message id + * @param MessageCollection $thread + * @param string $message_id + * @param Folder $primary_folder + * @param Folder $secondary_folder + * @param Folder $sent_folder + * + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\GetMessagesFailedException + * @throws Exceptions\RuntimeException + */ + protected function fetchThreadByMessageId(&$thread, $message_id, $primary_folder, $secondary_folder, $sent_folder){ + $primary_folder->query()->messageId($message_id) + ->setFetchBody($this->getFetchBodyOption()) + ->leaveUnread()->get()->each(function($message) use(&$thread, $secondary_folder, $sent_folder){ + /** @var Message $message */ + $message->thread($sent_folder, $thread, $secondary_folder); + }); + } + + /** + * Copy the current Messages to a mailbox + * @param string $folder_path + * @param boolean $expunge + * + * @return null|Message + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\FolderFetchingException + * @throws Exceptions\RuntimeException + * @throws InvalidMessageDateException + * @throws MessageContentFetchingException + * @throws MessageHeaderFetchingException + * @throws Exceptions\EventNotFoundException + * @throws MessageFlagException + * @throws Exceptions\MessageNotFoundException + */ + public function copy($folder_path, $expunge = false) { + $this->client->openFolder($folder_path); + $status = $this->client->getConnection()->examineFolder($folder_path); + + if (isset($status["uidnext"])) { + $next_uid = $status["uidnext"]; + + /** @var Folder $folder */ + $folder = $this->client->getFolderByPath($folder_path); + + $this->client->openFolder($this->folder_path); + if ($this->client->getConnection()->copyMessage($folder->path, $this->getSequenceId(), null, $this->sequence === IMAP::ST_UID) == true) { + return $this->fetchNewMail($folder, $next_uid, "copied", $expunge); + } + } + + return null; + } + + /** + * Move the current Messages to a mailbox + * @param string $folder_path + * @param boolean $expunge + * + * @return Message|null + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\FolderFetchingException + * @throws Exceptions\RuntimeException + * @throws InvalidMessageDateException + * @throws MessageContentFetchingException + * @throws MessageHeaderFetchingException + * @throws Exceptions\EventNotFoundException + * @throws MessageFlagException + * @throws Exceptions\MessageNotFoundException + */ + public function move($folder_path, $expunge = false) { + $this->client->openFolder($folder_path); + $status = $this->client->getConnection()->examineFolder($folder_path); + + if (isset($status["uidnext"])) { + $next_uid = $status["uidnext"]; + + /** @var Folder $folder */ + $folder = $this->client->getFolderByPath($folder_path); + + $this->client->openFolder($this->folder_path); + if ($this->client->getConnection()->moveMessage($folder->path, $this->getSequenceId(), null, $this->sequence === IMAP::ST_UID) == true) { + return $this->fetchNewMail($folder, $next_uid, "moved", $expunge); + } + } + + return null; + } + + /** + * Fetch a new message and fire a given event + * @param Folder $folder + * @param int $next_uid + * @param string $event + * @param boolean $expunge + * + * @return mixed + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\EventNotFoundException + * @throws Exceptions\MessageNotFoundException + * @throws Exceptions\RuntimeException + * @throws InvalidMessageDateException + * @throws MessageContentFetchingException + * @throws MessageFlagException + * @throws MessageHeaderFetchingException + */ + protected function fetchNewMail($folder, $next_uid, $event, $expunge){ + if($expunge) $this->client->expunge(); + + $this->client->openFolder($folder->path); + + if ($this->sequence === IMAP::ST_UID) { + $sequence_id = $next_uid; + }else{ + $sequence_id = $this->client->getConnection()->getMessageNumber($next_uid); + } + + $message = $folder->query()->getMessage($sequence_id, null, $this->sequence); + $event = $this->getEvent("message", $event); + $event::dispatch($this, $message); + + return $message; + } + + /** + * Delete the current Message + * @param bool $expunge + * + * @return bool + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\EventNotFoundException + * @throws MessageFlagException + * @throws Exceptions\RuntimeException + */ + public function delete($expunge = true) { + $status = $this->setFlag("Deleted"); + if($expunge) $this->client->expunge(); + + $event = $this->getEvent("message", "deleted"); + $event::dispatch($this); + + return $status; + } + + /** + * Restore a deleted Message + * @param boolean $expunge + * + * @return bool + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\EventNotFoundException + * @throws MessageFlagException + * @throws Exceptions\RuntimeException + */ + public function restore($expunge = true) { + $status = $this->unsetFlag("Deleted"); + if($expunge) $this->client->expunge(); + + $event = $this->getEvent("message", "restored"); + $event::dispatch($this); + + return $status; + } + + /** + * Set a given flag + * @param string|array $flag + * + * @return bool + * @throws Exceptions\ConnectionFailedException + * @throws MessageFlagException + * @throws Exceptions\EventNotFoundException + * @throws Exceptions\RuntimeException + */ + public function setFlag($flag) { + $this->client->openFolder($this->folder_path); + $flag = "\\".trim(is_array($flag) ? implode(" \\", $flag) : $flag); + $sequence_id = $this->getSequenceId(); + try { + $status = $this->client->getConnection()->store([$flag], $sequence_id, $sequence_id, "+", true, $this->sequence === IMAP::ST_UID); + } catch (Exceptions\RuntimeException $e) { + throw new MessageFlagException("flag could not be set", 0, $e); + } + $this->parseFlags(); + + $event = $this->getEvent("flag", "new"); + $event::dispatch($this, $flag); + + return $status; + } + + /** + * Unset a given flag + * @param string|array $flag + * + * @return bool + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\EventNotFoundException + * @throws MessageFlagException + * @throws Exceptions\RuntimeException + */ + public function unsetFlag($flag) { + $this->client->openFolder($this->folder_path); + + $flag = "\\".trim(is_array($flag) ? implode(" \\", $flag) : $flag); + $sequence_id = $this->getSequenceId(); + try { + $status = $this->client->getConnection()->store([$flag], $sequence_id, $sequence_id, "-", true, $this->sequence === IMAP::ST_UID); + } catch (Exceptions\RuntimeException $e) { + throw new MessageFlagException("flag could not be removed", 0, $e); + } + $this->parseFlags(); + + $event = $this->getEvent("flag", "deleted"); + $event::dispatch($this, $flag); + + return $status; + } + + /** + * Set a given flag + * @param string|array $flag + * + * @return bool + * @throws Exceptions\ConnectionFailedException + * @throws MessageFlagException + * @throws Exceptions\EventNotFoundException + * @throws Exceptions\RuntimeException + */ + public function addFlag($flag) { + return $this->setFlag($flag); + } + + /** + * Unset a given flag + * @param string|array $flag + * + * @return bool + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\EventNotFoundException + * @throws MessageFlagException + * @throws Exceptions\RuntimeException + */ + public function removeFlag($flag) { + return $this->unsetFlag($flag); + } + + /** + * Get all message attachments. + * + * @return AttachmentCollection + */ + public function getAttachments() { + return $this->attachments; + } + + /** + * Get all message attachments. + * + * @return AttachmentCollection + */ + public function attachments(){ + return $this->getAttachments(); + } + + /** + * Checks if there are any attachments present + * + * @return boolean + */ + public function hasAttachments() { + return $this->attachments->isEmpty() === false; + } + + /** + * Get the raw body + * + * @return string + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\RuntimeException + */ + public function getRawBody() { + if ($this->raw_body === null) { + $this->client->openFolder($this->folder_path); + + $this->raw_body = $this->structure->raw; + } + + return $this->raw_body; + } + + /** + * Get the message header + * + * @return Header + */ + public function getHeader() { + return $this->header; + } + + /** + * Get the current client + * + * @return Client + */ + public function getClient() { + return $this->client; + } + + /** + * Get the used fetch option + * + * @return integer + */ + public function getFetchOptions() { + return $this->fetch_options; + } + + /** + * Get the used fetch body option + * + * @return boolean + */ + public function getFetchBodyOption() { + return $this->fetch_body; + } + + /** + * Get the used fetch flags option + * + * @return boolean + */ + public function getFetchFlagsOption() { + return $this->fetch_flags; + } + + /** + * Get all available bodies + * + * @return array + */ + public function getBodies() { + return $this->bodies; + } + + /** + * Get all set flags + * + * @return FlagCollection + */ + public function getFlags() { + return $this->flags; + } + + /** + * Get all set flags + * + * @return FlagCollection + */ + public function flags(){ + return $this->getFlags(); + } + + /** + * Get the fetched structure + * + * @return Structure|null + */ + public function getStructure(){ + return $this->structure; + } + + /** + * Check if a message matches an other by comparing basic attributes + * + * @param null|Message $message + * @return boolean + */ + public function is(Message $message = null) { + if (is_null($message)) { + return false; + } + + return $this->uid == $message->uid + && $this->message_id->first() == $message->message_id->first() + && $this->subject->first() == $message->subject->first() + && $this->date->toDate()->eq($message->date); + } + + /** + * Get all message attributes + * + * @return array + */ + public function getAttributes(){ + return array_merge($this->attributes, $this->header->getAttributes()); + } + + /** + * Set the message mask + * @param $mask + * + * @return $this + */ + public function setMask($mask){ + if(class_exists($mask)){ + $this->mask = $mask; + } + + return $this; + } + + /** + * Get the used message mask + * + * @return string + */ + public function getMask(){ + return $this->mask; + } + + /** + * Get a masked instance by providing a mask name + * @param string|null $mask + * + * @return mixed + * @throws MaskNotFoundException + */ + public function mask($mask = null){ + $mask = $mask !== null ? $mask : $this->mask; + if(class_exists($mask)){ + return new $mask($this); + } + + throw new MaskNotFoundException("Unknown mask provided: ".$mask); + } + + /** + * Get the message path aka folder path + * + * @return string + */ + public function getFolderPath(){ + return $this->folder_path; + } + + /** + * Set the message path aka folder path + * @param $folder_path + * + * @return $this + */ + public function setFolderPath($folder_path){ + $this->folder_path = $folder_path; + + return $this; + } + + /** + * Set the config + * @param $config + * + * @return $this + */ + public function setConfig($config){ + $this->config = $config; + + return $this; + } + + /** + * Set the available flags + * @param $available_flags + * + * @return $this + */ + public function setAvailableFlags($available_flags){ + $this->available_flags = $available_flags; + + return $this; + } + + /** + * Set the attachment collection + * @param $attachments + * + * @return $this + */ + public function setAttachments($attachments){ + $this->attachments = $attachments; + + return $this; + } + + /** + * Set the flag collection + * @param $flags + * + * @return $this + */ + public function setFlags($flags){ + $this->flags = $flags; + + return $this; + } + + /** + * Set the client + * @param $client + * + * @return $this + * @throws Exceptions\RuntimeException + * @throws Exceptions\ConnectionFailedException + */ + public function setClient($client){ + $this->client = $client; + $this->client->openFolder($this->folder_path); + + return $this; + } + + /** + * Set the message number + * @param int $uid + * + * @return $this + * @throws Exceptions\MessageNotFoundException + * @throws Exceptions\ConnectionFailedException + */ + public function setUid($uid){ + $this->uid = $uid; + $this->msgn = $this->client->getConnection()->getMessageNumber($this->uid); + $this->msglist = null; + + return $this; + } + + /** + * Set the message number + * @param $msgn + * @param int|null $msglist + * + * @return $this + * @throws Exceptions\MessageNotFoundException + * @throws Exceptions\ConnectionFailedException + */ + public function setMsgn($msgn, $msglist = null){ + $this->msgn = $msgn; + $this->msglist = $msglist; + $this->uid = $this->client->getConnection()->getUid($this->msgn); + + return $this; + } + + /** + * Get the current sequence type + * + * @return int + */ + public function getSequence(){ + return $this->sequence; + } + + /** + * Set the sequence type + * + * @return int + */ + public function getSequenceId(){ + return $this->sequence === IMAP::ST_UID ? $this->uid : $this->msgn; + } + + /** + * Set the sequence id + * @param $uid + * @param int|null $msglist + * + * @throws Exceptions\ConnectionFailedException + * @throws Exceptions\MessageNotFoundException + */ + public function setSequenceId($uid, $msglist = null){ + if ($this->getSequence() === IMAP::ST_UID) { + $this->setUid($uid); + $this->setMsglist($msglist); + }else{ + $this->setMsgn($uid, $msglist); + } + } +} diff --git a/htdocs/includes/webklex/php-imap/src/Part.php b/htdocs/includes/webklex/php-imap/src/Part.php new file mode 100644 index 00000000000..a6a6748886f --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/Part.php @@ -0,0 +1,312 @@ +raw = $raw_part; + $this->header = $header; + $this->part_number = $part_number; + $this->parse(); + } + + /** + * Parse the raw parts + * + * @throws InvalidMessageDateException + */ + protected function parse(){ + if ($this->header === null) { + $body = $this->findHeaders(); + }else{ + $body = $this->raw; + } + + $this->parseDisposition(); + $this->parseDescription(); + $this->parseEncoding(); + + $this->charset = $this->header->get("charset"); + $this->name = $this->header->get("name"); + $this->filename = $this->header->get("filename"); + + if(!empty($this->header->get("id"))) { + $this->id = $this->header->get("id"); + } else if(!empty($this->header->get("x_attachment_id"))){ + $this->id = $this->header->get("x_attachment_id"); + } else if(!empty($this->header->get("content_id"))){ + $this->id = strtr($this->header->get("content_id"), [ + '<' => '', + '>' => '' + ]); + } + + $content_types = $this->header->get("content_type"); + if(!empty($content_types)){ + $this->subtype = $this->parseSubtype($content_types); + $content_type = $content_types; + if (is_array($content_types)) { + $content_type = $content_types[0]; + } + $parts = explode(';', $content_type); + $this->content_type = trim($parts[0]); + } + + + $this->content = trim(rtrim($body)); + $this->bytes = strlen($this->content); + } + + /** + * Find all available headers and return the left over body segment + * + * @return string + * @throws InvalidMessageDateException + */ + private function findHeaders(){ + $body = $this->raw; + while (($pos = strpos($body, "\r\n")) > 0) { + $body = substr($body, $pos + 2); + } + $headers = substr($this->raw, 0, strlen($body) * -1); + $body = substr($body, 0, -2); + + $this->header = new Header($headers); + + return (string) $body; + } + + /** + * Try to parse the subtype if any is present + * @param $content_type + * + * @return string + */ + private function parseSubtype($content_type){ + if (is_array($content_type)) { + foreach ($content_type as $part){ + if ((strpos($part, "/")) !== false){ + return $this->parseSubtype($part); + } + } + return null; + } + if (($pos = strpos($content_type, "/")) !== false){ + return substr($content_type, $pos + 1); + } + return null; + } + + /** + * Try to parse the disposition if any is present + */ + private function parseDisposition(){ + $content_disposition = $this->header->get("content_disposition"); + if($content_disposition !== null) { + $this->ifdisposition = true; + $this->disposition = (is_array($content_disposition)) ? implode(' ', $content_disposition) : $content_disposition; + } + } + + /** + * Try to parse the description if any is present + */ + private function parseDescription(){ + $content_description = $this->header->get("content_description"); + if($content_description !== null) { + $this->ifdescription = true; + $this->description = $content_description; + } + } + + /** + * Try to parse the encoding if any is present + */ + private function parseEncoding(){ + $encoding = $this->header->get("content_transfer_encoding"); + if($encoding !== null) { + switch (strtolower($encoding)) { + case "quoted-printable": + $this->encoding = IMAP::MESSAGE_ENC_QUOTED_PRINTABLE; + break; + case "base64": + $this->encoding = IMAP::MESSAGE_ENC_BASE64; + break; + case "7bit": + $this->encoding = IMAP::MESSAGE_ENC_7BIT; + break; + case "8bit": + $this->encoding = IMAP::MESSAGE_ENC_8BIT; + break; + case "binary": + $this->encoding = IMAP::MESSAGE_ENC_BINARY; + break; + default: + $this->encoding = IMAP::MESSAGE_ENC_OTHER; + break; + + } + } + } + + /** + * Check if the current part represents an attachment + * + * @return bool + */ + public function isAttachment(){ + $valid_disposition = in_array(strtolower($this->disposition), ClientManager::get('options.dispositions')); + + if ($this->type == IMAP::MESSAGE_TYPE_TEXT && ($this->ifdisposition == 0 || (empty($this->disposition))) && !$valid_disposition) { + if (($this->subtype == null || in_array((strtolower($this->subtype)), ["plain", "html"])) && $this->filename == null && $this->name == null) { + return false; + } + } + return true; + } + +} diff --git a/htdocs/includes/webklex/php-imap/src/Query/Query.php b/htdocs/includes/webklex/php-imap/src/Query/Query.php new file mode 100644 index 00000000000..b1806755f4d --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/Query/Query.php @@ -0,0 +1,842 @@ +setClient($client); + + $this->sequence = ClientManager::get('options.sequence', IMAP::ST_MSGN); + if (ClientManager::get('options.fetch') === IMAP::FT_PEEK) $this->leaveUnread(); + + if (ClientManager::get('options.fetch_order') === 'desc') { + $this->fetch_order = 'desc'; + } else { + $this->fetch_order = 'asc'; + } + + $this->date_format = ClientManager::get('date_format', 'd M y'); + $this->soft_fail = ClientManager::get('options.soft_fail', false); + + $this->charset = $charset; + $this->query = new Collection(); + $this->boot(); + } + + /** + * Instance boot method for additional functionality + */ + protected function boot() { + } + + /** + * Parse a given value + * @param mixed $value + * + * @return string + */ + protected function parse_value($value) { + switch (true) { + case $value instanceof Carbon: + $value = $value->format($this->date_format); + break; + } + + return (string)$value; + } + + /** + * Check if a given date is a valid carbon object and if not try to convert it + * @param string|Carbon $date + * + * @return Carbon + * @throws MessageSearchValidationException + */ + protected function parse_date($date) { + if ($date instanceof Carbon) return $date; + + try { + $date = Carbon::parse($date); + } catch (Exception $e) { + throw new MessageSearchValidationException(); + } + + return $date; + } + + /** + * Get the raw IMAP search query + * + * @return string + */ + public function generate_query() { + $query = ''; + $this->query->each(function($statement) use (&$query) { + if (count($statement) == 1) { + $query .= $statement[0]; + } else { + if ($statement[1] === null) { + $query .= $statement[0]; + } else { + $query .= $statement[0] . ' "' . $statement[1] . '"'; + } + } + $query .= ' '; + + }); + + $this->raw_query = trim($query); + + return $this->raw_query; + } + + /** + * Perform an imap search request + * + * @return Collection + * @throws GetMessagesFailedException + */ + protected function search() { + $this->generate_query(); + + try { + $available_messages = $this->client->getConnection()->search([$this->getRawQuery()], $this->sequence == IMAP::ST_UID); + return $available_messages !== false ? new Collection($available_messages) : new Collection(); + } catch (RuntimeException $e) { + throw new GetMessagesFailedException("failed to fetch messages", 0, $e); + } catch (ConnectionFailedException $e) { + throw new GetMessagesFailedException("failed to fetch messages", 0, $e); + } + } + + /** + * Count all available messages matching the current search criteria + * + * @return int + * @throws GetMessagesFailedException + */ + public function count() { + return $this->search()->count(); + } + + /** + * Fetch a given id collection + * @param Collection $available_messages + * + * @return array + * @throws ConnectionFailedException + * @throws RuntimeException + */ + protected function fetch($available_messages) { + if ($this->fetch_order === 'desc') { + $available_messages = $available_messages->reverse(); + } + + $uids = $available_messages->forPage($this->page, $this->limit)->toArray(); + $flags = $this->client->getConnection()->flags($uids, $this->sequence == IMAP::ST_UID); + $headers = $this->client->getConnection()->headers($uids, "RFC822", $this->sequence == IMAP::ST_UID); + + $contents = []; + if ($this->getFetchBody()) { + $contents = $this->client->getConnection()->content($uids, "RFC822", $this->sequence == IMAP::ST_UID); + } + + return [ + "uids" => $uids, + "flags" => $flags, + "headers" => $headers, + "contents" => $contents, + ]; + } + + /** + * Make a new message from given raw components + * @param integer $uid + * @param integer $msglist + * @param string $header + * @param string $content + * @param array $flags + * + * @return Message|null + * @throws ConnectionFailedException + * @throws EventNotFoundException + * @throws GetMessagesFailedException + * @throws ReflectionException + */ + protected function make($uid, $msglist, $header, $content, $flags){ + try { + return Message::make($uid, $msglist, $this->getClient(), $header, $content, $flags, $this->getFetchOptions(), $this->sequence); + }catch (MessageNotFoundException $e) { + $this->setError($uid, $e); + }catch (RuntimeException $e) { + $this->setError($uid, $e); + }catch (MessageFlagException $e) { + $this->setError($uid, $e); + }catch (InvalidMessageDateException $e) { + $this->setError($uid, $e); + }catch (MessageContentFetchingException $e) { + $this->setError($uid, $e); + } + + $this->handleException($uid); + + return null; + } + + /** + * Get the message key for a given message + * @param string $message_key + * @param integer $msglist + * @param Message $message + * + * @return string + */ + protected function getMessageKey($message_key, $msglist, $message){ + switch ($message_key) { + case 'number': + $key = $message->getMessageNo(); + break; + case 'list': + $key = $msglist; + break; + case 'uid': + $key = $message->getUid(); + break; + default: + $key = $message->getMessageId(); + break; + } + return (string)$key; + } + + /** + * Populate a given id collection and receive a fully fetched message collection + * @param Collection $available_messages + * + * @return MessageCollection + * @throws ConnectionFailedException + * @throws EventNotFoundException + * @throws GetMessagesFailedException + * @throws ReflectionException + * @throws RuntimeException + */ + protected function populate($available_messages) { + $messages = MessageCollection::make([]); + + $messages->total($available_messages->count()); + + $message_key = ClientManager::get('options.message_key'); + + $raw_messages = $this->fetch($available_messages); + + $msglist = 0; + foreach ($raw_messages["headers"] as $uid => $header) { + $content = isset($raw_messages["contents"][$uid]) ? $raw_messages["contents"][$uid] : ""; + $flag = isset($raw_messages["flags"][$uid]) ? $raw_messages["flags"][$uid] : []; + + $message = $this->make($uid, $msglist, $header, $content, $flag); + if ($message !== null) { + $key = $this->getMessageKey($message_key, $msglist, $message); + $messages->put("$key", $message); + } + $msglist++; + } + + return $messages; + } + + /** + * Fetch the current query and return all found messages + * + * @return MessageCollection + * @throws GetMessagesFailedException + */ + public function get() { + $available_messages = $this->search(); + + try { + if ($available_messages->count() > 0) { + return $this->populate($available_messages); + } + return MessageCollection::make([]); + } catch (Exception $e) { + throw new GetMessagesFailedException($e->getMessage(), 0, $e); + } + } + + /** + * Fetch the current query as chunked requests + * @param callable $callback + * @param int $chunk_size + * @param int $start_chunk + * + * @throws ConnectionFailedException + * @throws EventNotFoundException + * @throws GetMessagesFailedException + * @throws ReflectionException + * @throws RuntimeException + */ + public function chunked($callback, $chunk_size = 10, $start_chunk = 1) { + $available_messages = $this->search(); + if (($available_messages_count = $available_messages->count()) > 0) { + $old_limit = $this->limit; + $old_page = $this->page; + + $this->limit = $chunk_size; + $this->page = $start_chunk; + do { + $messages = $this->populate($available_messages); + $callback($messages, $this->page); + $this->page++; + } while ($this->limit * $this->page <= $available_messages_count); + $this->limit = $old_limit; + $this->page = $old_page; + } + } + + /** + * Paginate the current query + * @param int $per_page Results you which to receive per page + * @param int|null $page The current page you are on (e.g. 0, 1, 2, ...) use `null` to enable auto mode + * @param string $page_name The page name / uri parameter used for the generated links and the auto mode + * + * @return LengthAwarePaginator + * @throws GetMessagesFailedException + */ + public function paginate($per_page = 5, $page = null, $page_name = 'imap_page') { + if ( + $page === null + && isset($_GET[$page_name]) + && $_GET[$page_name] > 0 + ) { + $this->page = intval($_GET[$page_name]); + } elseif ($page > 0) { + $this->page = $page; + } + + $this->limit = $per_page; + + return $this->get()->paginate($per_page, $this->page, $page_name, true); + } + + /** + * Get a new Message instance + * @param int $uid + * @param int|null $msglist + * @param int|null $sequence + * + * @return Message + * @throws ConnectionFailedException + * @throws RuntimeException + * @throws InvalidMessageDateException + * @throws MessageContentFetchingException + * @throws MessageHeaderFetchingException + * @throws EventNotFoundException + * @throws MessageFlagException + * @throws MessageNotFoundException + */ + public function getMessage($uid, $msglist = null, $sequence = null) { + return new Message($uid, $msglist, $this->getClient(), $this->getFetchOptions(), $this->getFetchBody(), $this->getFetchFlags(), $sequence ? $sequence : $this->sequence); + } + + /** + * Get a message by its message number + * @param $msgn + * @param int|null $msglist + * + * @return Message + * @throws ConnectionFailedException + * @throws InvalidMessageDateException + * @throws MessageContentFetchingException + * @throws MessageHeaderFetchingException + * @throws RuntimeException + * @throws EventNotFoundException + * @throws MessageFlagException + * @throws MessageNotFoundException + */ + public function getMessageByMsgn($msgn, $msglist = null) { + return $this->getMessage($msgn, $msglist, IMAP::ST_MSGN); + } + + /** + * Get a message by its uid + * @param $uid + * + * @return Message + * @throws ConnectionFailedException + * @throws InvalidMessageDateException + * @throws MessageContentFetchingException + * @throws MessageHeaderFetchingException + * @throws RuntimeException + * @throws EventNotFoundException + * @throws MessageFlagException + * @throws MessageNotFoundException + */ + public function getMessageByUid($uid) { + return $this->getMessage($uid, null, IMAP::ST_UID); + } + + /** + * Don't mark messages as read when fetching + * + * @return $this + */ + public function leaveUnread() { + $this->setFetchOptions(IMAP::FT_PEEK); + + return $this; + } + + /** + * Mark all messages as read when fetching + * + * @return $this + */ + public function markAsRead() { + $this->setFetchOptions(IMAP::FT_UID); + + return $this; + } + + /** + * Set the sequence type + * @param int $sequence + * + * @return $this + */ + public function setSequence($sequence) { + $this->sequence = $sequence != IMAP::ST_MSGN ? IMAP::ST_UID : $sequence; + + return $this; + } + + /** + * @return Client + * @throws ConnectionFailedException + */ + public function getClient() { + $this->client->checkConnection(); + return $this->client; + } + + /** + * Set the limit and page for the current query + * @param int $limit + * @param int $page + * + * @return $this + */ + public function limit($limit, $page = 1) { + if ($page >= 1) $this->page = $page; + $this->limit = $limit; + + return $this; + } + + /** + * @return Collection + */ + public function getQuery() { + return $this->query; + } + + /** + * @param array $query + * @return Query + */ + public function setQuery($query) { + $this->query = new Collection($query); + return $this; + } + + /** + * @return string + */ + public function getRawQuery() { + return $this->raw_query; + } + + /** + * @param string $raw_query + * @return Query + */ + public function setRawQuery($raw_query) { + $this->raw_query = $raw_query; + return $this; + } + + /** + * @return string + */ + public function getCharset() { + return $this->charset; + } + + /** + * @param string $charset + * @return Query + */ + public function setCharset($charset) { + $this->charset = $charset; + return $this; + } + + /** + * @param Client $client + * @return Query + */ + public function setClient(Client $client) { + $this->client = $client; + return $this; + } + + /** + * @return int + */ + public function getLimit() { + return $this->limit; + } + + /** + * @param int $limit + * @return Query + */ + public function setLimit($limit) { + $this->limit = $limit <= 0 ? null : $limit; + return $this; + } + + /** + * @return int + */ + public function getPage() { + return $this->page; + } + + /** + * @param int $page + * @return Query + */ + public function setPage($page) { + $this->page = $page; + return $this; + } + + /** + * @param boolean $fetch_options + * @return Query + */ + public function setFetchOptions($fetch_options) { + $this->fetch_options = $fetch_options; + return $this; + } + + /** + * @param boolean $fetch_options + * @return Query + */ + public function fetchOptions($fetch_options) { + return $this->setFetchOptions($fetch_options); + } + + /** + * @return int + */ + public function getFetchOptions() { + return $this->fetch_options; + } + + /** + * @return boolean + */ + public function getFetchBody() { + return $this->fetch_body; + } + + /** + * @param boolean $fetch_body + * @return Query + */ + public function setFetchBody($fetch_body) { + $this->fetch_body = $fetch_body; + return $this; + } + + /** + * @param boolean $fetch_body + * @return Query + */ + public function fetchBody($fetch_body) { + return $this->setFetchBody($fetch_body); + } + + /** + * @return int + */ + public function getFetchFlags() { + return $this->fetch_flags; + } + + /** + * @param int $fetch_flags + * @return Query + */ + public function setFetchFlags($fetch_flags) { + $this->fetch_flags = $fetch_flags; + return $this; + } + + /** + * @param string $fetch_order + * @return Query + */ + public function setFetchOrder($fetch_order) { + $fetch_order = strtolower($fetch_order); + + if (in_array($fetch_order, ['asc', 'desc'])) { + $this->fetch_order = $fetch_order; + } + + return $this; + } + + /** + * @param string $fetch_order + * @return Query + */ + public function fetchOrder($fetch_order) { + return $this->setFetchOrder($fetch_order); + } + + /** + * @return string + */ + public function getFetchOrder() { + return $this->fetch_order; + } + + /** + * @return Query + */ + public function setFetchOrderAsc() { + return $this->setFetchOrder('asc'); + } + + /** + * @return Query + */ + public function fetchOrderAsc() { + return $this->setFetchOrderAsc(); + } + + /** + * @return Query + */ + public function setFetchOrderDesc() { + return $this->setFetchOrder('desc'); + } + + /** + * @return Query + */ + public function fetchOrderDesc() { + return $this->setFetchOrderDesc(); + } + + /** + * @var boolean $state + * + * @return Query + */ + public function softFail($state = true) { + return $this->setSoftFail($state); + } + + /** + * @var boolean $state + * + * @return Query + */ + public function setSoftFail($state = true) { + $this->soft_fail = $state; + + return $this; + } + + /** + * @return boolean + */ + public function getSoftFail() { + return $this->soft_fail; + } + + /** + * Handle the exception for a given uid + * @param integer $uid + * + * @throws GetMessagesFailedException + */ + protected function handleException($uid) { + if ($this->soft_fail === false && $this->hasError($uid)) { + $error = $this->getError($uid); + throw new GetMessagesFailedException($error->getMessage(), 0, $error); + } + } + + /** + * Add a new error to the error holder + * @param integer $uid + * @param Exception $error + */ + protected function setError($uid, $error) { + $this->errors[$uid] = $error; + } + + /** + * Check if there are any errors / exceptions present + * @var integer|null $uid + * + * @return boolean + */ + public function hasErrors($uid = null){ + if ($uid !== null) { + return $this->hasError($uid); + } + return count($this->errors) > 0; + } + + /** + * Check if there is an error / exception present + * @var integer $uid + * + * @return boolean + */ + public function hasError($uid){ + return isset($this->errors[$uid]); + } + + /** + * Get all available errors / exceptions + * + * @return array + */ + public function errors(){ + return $this->getErrors(); + } + + /** + * Get all available errors / exceptions + * + * @return array + */ + public function getErrors(){ + return $this->errors; + } + + /** + * Get a specific error / exception + * @var integer $uid + * + * @return Exception|null + */ + public function error($uid){ + return $this->getError($uid); + } + + /** + * Get a specific error / exception + * @var integer $uid + * + * @return Exception|null + */ + public function getError($uid){ + if ($this->hasError($uid)) { + return $this->errors[$uid]; + } + return null; + } +} diff --git a/htdocs/includes/webklex/php-imap/src/Query/WhereQuery.php b/htdocs/includes/webklex/php-imap/src/Query/WhereQuery.php new file mode 100755 index 00000000000..4d23be866e7 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/Query/WhereQuery.php @@ -0,0 +1,551 @@ +whereNot(); + $name = substr($name, 3); + } + + if (strpos(strtolower($name), "where") === false) { + $method = 'where' . ucfirst($name); + } else { + $method = lcfirst($name); + } + + if (method_exists($this, $method) === true) { + return call_user_func_array([$that, $method], $arguments); + } + + throw new MethodNotFoundException("Method " . self::class . '::' . $method . '() is not supported'); + } + + /** + * Validate a given criteria + * @param $criteria + * + * @return string + * @throws InvalidWhereQueryCriteriaException + */ + protected function validate_criteria($criteria) { + $criteria = strtoupper($criteria); + if (substr($criteria, 0, 7) === "CUSTOM ") { + return substr($criteria, 7); + } + if (in_array($criteria, $this->available_criteria) === false) { + throw new InvalidWhereQueryCriteriaException(); + } + + return $criteria; + } + + + /** + * Register search parameters + * @param mixed $criteria + * @param null $value + * + * @return $this + * @throws InvalidWhereQueryCriteriaException + * + * Examples: + * $query->from("someone@email.tld")->seen(); + * $query->whereFrom("someone@email.tld")->whereSeen(); + * $query->where([["FROM" => "someone@email.tld"], ["SEEN"]]); + * $query->where(["FROM" => "someone@email.tld"])->where(["SEEN"]); + * $query->where(["FROM" => "someone@email.tld", "SEEN"]); + * $query->where("FROM", "someone@email.tld")->where("SEEN"); + */ + public function where($criteria, $value = null): WhereQuery { + if (is_array($criteria)) { + foreach ($criteria as $key => $value) { + if (is_numeric($key)) { + $this->where($value); + }else{ + $this->where($key, $value); + } + } + } else { + $this->push_search_criteria($criteria, $value); + } + + return $this; + } + + /** + * Push a given search criteria and value pair to the search query + * @param $criteria string + * @param $value mixed + * + * @throws InvalidWhereQueryCriteriaException + */ + protected function push_search_criteria(string $criteria, $value){ + $criteria = $this->validate_criteria($criteria); + $value = $this->parse_value($value); + + if ($value === null || $value === '') { + $this->query->push([$criteria]); + } else { + $this->query->push([$criteria, $value]); + } + } + + /** + * @param Closure $closure + * + * @return $this + */ + public function orWhere(Closure $closure = null) { + $this->query->push(['OR']); + if ($closure !== null) $closure($this); + + return $this; + } + + /** + * @param Closure $closure + * + * @return $this + */ + public function andWhere(Closure $closure = null) { + $this->query->push(['AND']); + if ($closure !== null) $closure($this); + + return $this; + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereAll() { + return $this->where('ALL'); + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereAnswered() { + return $this->where('ANSWERED'); + } + + /** + * @param string $value + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereBcc($value) { + return $this->where('BCC', $value); + } + + /** + * @param mixed $value + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + * @throws MessageSearchValidationException + */ + public function whereBefore($value) { + $date = $this->parse_date($value); + return $this->where('BEFORE', $date); + } + + /** + * @param string $value + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereBody($value) { + return $this->where('BODY', $value); + } + + /** + * @param string $value + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereCc($value) { + return $this->where('CC', $value); + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereDeleted() { + return $this->where('DELETED'); + } + + /** + * @param string $value + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereFlagged($value) { + return $this->where('FLAGGED', $value); + } + + /** + * @param string $value + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereFrom($value) { + return $this->where('FROM', $value); + } + + /** + * @param string $value + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereKeyword($value) { + return $this->where('KEYWORD', $value); + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereNew() { + return $this->where('NEW'); + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereNot() { + return $this->where('NOT'); + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereOld() { + return $this->where('OLD'); + } + + /** + * @param mixed $value + * + * @return WhereQuery + * @throws MessageSearchValidationException + * @throws InvalidWhereQueryCriteriaException + */ + public function whereOn($value) { + $date = $this->parse_date($value); + return $this->where('ON', $date); + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereRecent() { + return $this->where('RECENT'); + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereSeen() { + return $this->where('SEEN'); + } + + /** + * @param mixed $value + * + * @return WhereQuery + * @throws MessageSearchValidationException + * @throws InvalidWhereQueryCriteriaException + */ + public function whereSince($value) { + $date = $this->parse_date($value); + return $this->where('SINCE', $date); + } + + /** + * @param string $value + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereSubject($value) { + return $this->where('SUBJECT', $value); + } + + /** + * @param string $value + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereText($value) { + return $this->where('TEXT', $value); + } + + /** + * @param string $value + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereTo($value) { + return $this->where('TO', $value); + } + + /** + * @param string $value + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereUnkeyword($value) { + return $this->where('UNKEYWORD', $value); + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereUnanswered() { + return $this->where('UNANSWERED'); + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereUndeleted() { + return $this->where('UNDELETED'); + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereUnflagged() { + return $this->where('UNFLAGGED'); + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereUnseen() { + return $this->where('UNSEEN'); + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereNoXSpam() { + return $this->where("CUSTOM X-Spam-Flag NO"); + } + + /** + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereIsXSpam() { + return $this->where("CUSTOM X-Spam-Flag YES"); + } + + /** + * Search for a specific header value + * @param $header + * @param $value + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereHeader($header, $value) { + return $this->where("CUSTOM HEADER $header $value"); + } + + /** + * Search for a specific message id + * @param $messageId + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereMessageId($messageId) { + return $this->whereHeader("Message-ID", $messageId); + } + + /** + * Search for a specific message id + * @param $messageId + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereInReplyTo($messageId) { + return $this->whereHeader("In-Reply-To", $messageId); + } + + /** + * @param $country_code + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereLanguage($country_code) { + return $this->where("Content-Language $country_code"); + } + + /** + * Get message be it UID. + * + * @param int|string $uid + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereUid($uid) + { + return $this->where('UID', $uid); + } + + /** + * Get messages by their UIDs. + * + * @param array $uids + * + * @return WhereQuery + * @throws InvalidWhereQueryCriteriaException + */ + public function whereUidIn($uids) + { + $uids = implode(',', $uids); + return $this->where('UID', $uids); + } + + /** + * Apply the callback if the given "value" is truthy. + * copied from @url https://github.com/laravel/framework/blob/8.x/src/Illuminate/Support/Traits/Conditionable.php + * + * @param mixed $value + * @param callable $callback + * @param callable|null $default + + * @return $this|mixed + */ + public function when($value, $callback, $default = null) { + if ($value) { + return $callback($this, $value) ?: $this; + } elseif ($default) { + return $default($this, $value) ?: $this; + } + + return $this; + } + + /** + * Apply the callback if the given "value" is falsy. + * copied from @url https://github.com/laravel/framework/blob/8.x/src/Illuminate/Support/Traits/Conditionable.php + * + * @param mixed $value + * @param callable $callback + * @param callable|null $default + + * @return $this|mixed + */ + public function unless($value, $callback, $default = null) { + if (! $value) { + return $callback($this, $value) ?: $this; + } elseif ($default) { + return $default($this, $value) ?: $this; + } + + return $this; + } +} \ No newline at end of file diff --git a/htdocs/includes/webklex/php-imap/src/Structure.php b/htdocs/includes/webklex/php-imap/src/Structure.php new file mode 100644 index 00000000000..a6e65b934a0 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/Structure.php @@ -0,0 +1,174 @@ +raw = $raw_structure; + $this->header = $header; + $this->config = ClientManager::get('options'); + $this->parse(); + } + + /** + * Parse the given raw structure + * + * @throws MessageContentFetchingException + * @throws InvalidMessageDateException + */ + protected function parse(){ + $this->findContentType(); + $this->parts = $this->find_parts(); + } + + /** + * Determine the message content type + */ + public function findContentType(){ + $content_type = $this->header->get("content_type"); + $content_type = (is_array($content_type)) ? implode(' ', $content_type) : $content_type; + if(stripos($content_type, 'multipart') === 0) { + $this->type = IMAP::MESSAGE_TYPE_MULTIPART; + }else{ + $this->type = IMAP::MESSAGE_TYPE_TEXT; + } + } + + /** + * Find all available headers and return the left over body segment + * @var string $context + * @var integer $part_number + * + * @return Part[] + * @throws InvalidMessageDateException + */ + private function parsePart($context, $part_number = 0){ + $body = $context; + while (($pos = strpos($body, "\r\n")) > 0) { + $body = substr($body, $pos + 2); + } + $headers = substr($context, 0, strlen($body) * -1); + $body = substr($body, 0, -2); + + $headers = new Header($headers); + if (($boundary = $headers->getBoundary()) !== null) { + return $this->detectParts($boundary, $body, $part_number); + } + return [new Part($body, $headers, $part_number)]; + } + + /** + * @param string $boundary + * @param string $context + * @param int $part_number + * + * @return array + * @throws InvalidMessageDateException + */ + private function detectParts($boundary, $context, $part_number = 0){ + $base_parts = explode( $boundary, $context); + $final_parts = []; + foreach($base_parts as $ctx) { + $ctx = substr($ctx, 2); + if ($ctx !== "--" && $ctx != "") { + $parts = $this->parsePart($ctx, $part_number); + foreach ($parts as $part) { + $final_parts[] = $part; + $part_number = $part->part_number; + } + $part_number++; + } + } + return $final_parts; + } + + /** + * Find all available parts + * + * @return array + * @throws MessageContentFetchingException + * @throws InvalidMessageDateException + */ + public function find_parts(){ + if($this->type === IMAP::MESSAGE_TYPE_MULTIPART) { + if (($boundary = $this->header->getBoundary()) === null) { + throw new MessageContentFetchingException("no content found", 0); + } + + return $this->detectParts($boundary, $this->raw); + } + + return [new Part($this->raw, $this->header)]; + } + + /** + * Try to find a boundary if possible + * + * @return string|null + * @Depricated since version 2.4.4 + */ + public function getBoundary(){ + return $this->header->getBoundary(); + } +} diff --git a/htdocs/includes/webklex/php-imap/src/Support/AttachmentCollection.php b/htdocs/includes/webklex/php-imap/src/Support/AttachmentCollection.php new file mode 100644 index 00000000000..8b3f9c32213 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/Support/AttachmentCollection.php @@ -0,0 +1,22 @@ +parent->content); + } + + /** + * Get an base64 image src string + * + * @return string|null + */ + public function getImageSrc() { + return 'data:'.$this->parent->content_type.';base64,'.$this->getContentBase64Encoded(); + } +} \ No newline at end of file diff --git a/htdocs/includes/webklex/php-imap/src/Support/Masks/Mask.php b/htdocs/includes/webklex/php-imap/src/Support/Masks/Mask.php new file mode 100755 index 00000000000..7483bd5e5b2 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/Support/Masks/Mask.php @@ -0,0 +1,137 @@ +parent = $parent; + + if(method_exists($this->parent, 'getAttributes')){ + $this->attributes = array_merge($this->attributes, $this->parent->getAttributes()); + } + + $this->boot(); + } + + /** + * Boot method made to be used by any custom mask + */ + protected function boot(){} + + /** + * Call dynamic attribute setter and getter methods and inherit the parent calls + * @param string $method + * @param array $arguments + * + * @return mixed + * @throws MethodNotFoundException + */ + public function __call($method, $arguments) { + if(strtolower(substr($method, 0, 3)) === 'get') { + $name = Str::snake(substr($method, 3)); + + if(isset($this->attributes[$name])) { + return $this->attributes[$name]; + } + + }elseif (strtolower(substr($method, 0, 3)) === 'set') { + $name = Str::snake(substr($method, 3)); + + if(isset($this->attributes[$name])) { + $this->attributes[$name] = array_pop($arguments); + + return $this->attributes[$name]; + } + + } + + if(method_exists($this->parent, $method) === true){ + return call_user_func_array([$this->parent, $method], $arguments); + } + + throw new MethodNotFoundException("Method ".self::class.'::'.$method.'() is not supported'); + } + + /** + * Magic setter + * @param $name + * @param $value + * + * @return mixed + */ + public function __set($name, $value) { + $this->attributes[$name] = $value; + + return $this->attributes[$name]; + } + + /** + * Magic getter + * @param $name + * + * @return mixed|null + */ + public function __get($name) { + if(isset($this->attributes[$name])) { + return $this->attributes[$name]; + } + + return null; + } + + /** + * Get the parent instance + * + * @return mixed + */ + public function getParent(){ + return $this->parent; + } + + /** + * Get all available attributes + * + * @return array + */ + public function getAttributes(){ + return $this->attributes; + } + +} \ No newline at end of file diff --git a/htdocs/includes/webklex/php-imap/src/Support/Masks/MessageMask.php b/htdocs/includes/webklex/php-imap/src/Support/Masks/MessageMask.php new file mode 100644 index 00000000000..d072e8b6456 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/Support/Masks/MessageMask.php @@ -0,0 +1,86 @@ +parent->getBodies(); + if (!isset($bodies['html'])) { + return null; + } + + if(is_object($bodies['html']) && property_exists($bodies['html'], 'content')) { + return $bodies['html']->content; + } + return $bodies['html']; + } + + /** + * Get the Message html body filtered by an optional callback + * @param callable|bool $callback + * + * @return string|null + */ + public function getCustomHTMLBody($callback = false) { + $body = $this->getHtmlBody(); + if($body === null) return null; + + if ($callback !== false) { + $aAttachment = $this->parent->getAttachments(); + $aAttachment->each(function($oAttachment) use(&$body, $callback) { + /** @var Attachment $oAttachment */ + if(is_callable($callback)) { + $body = $callback($body, $oAttachment); + }elseif(is_string($callback)) { + call_user_func($callback, [$body, $oAttachment]); + } + }); + } + + return $body; + } + + /** + * Get the Message html body with embedded base64 images + * the resulting $body. + * + * @return string|null + */ + public function getHTMLBodyWithEmbeddedBase64Images() { + return $this->getCustomHTMLBody(function($body, $oAttachment){ + /** @var Attachment $oAttachment */ + if ($oAttachment->id) { + $body = str_replace('cid:'.$oAttachment->id, 'data:'.$oAttachment->getContentType().';base64, '.base64_encode($oAttachment->getContent()), $body); + } + + return $body; + }); + } +} \ No newline at end of file diff --git a/htdocs/includes/webklex/php-imap/src/Support/MessageCollection.php b/htdocs/includes/webklex/php-imap/src/Support/MessageCollection.php new file mode 100644 index 00000000000..6d1249fae52 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/Support/MessageCollection.php @@ -0,0 +1,22 @@ +total ? $this->total : $this->count(); + + $results = !$prepaginated && $total ? $this->forPage($page, $per_page) : $this->all(); + + return $this->paginator($results, $total, $per_page, $page, [ + 'path' => Paginator::resolveCurrentPath(), + 'pageName' => $page_name, + ]); + } + + /** + * Create a new length-aware paginator instance. + * @param array $items + * @param int $total + * @param int $per_page + * @param int|null $current_page + * @param array $options + * + * @return LengthAwarePaginator + */ + protected function paginator($items, $total, $per_page, $current_page, array $options) { + return new LengthAwarePaginator($items, $total, $per_page, $current_page, $options); + } + + /** + * Get and set the total amount + * @param null $total + * + * @return int|null + */ + public function total($total = null) { + if($total === null) { + return $this->total; + } + + return $this->total = $total; + } +} diff --git a/htdocs/includes/webklex/php-imap/src/Traits/HasEvents.php b/htdocs/includes/webklex/php-imap/src/Traits/HasEvents.php new file mode 100644 index 00000000000..bc7ae68eb42 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/Traits/HasEvents.php @@ -0,0 +1,77 @@ +events[$section])) { + $this->events[$section][$event] = $class; + } + } + + /** + * Set all events + * @param $events + */ + public function setEvents($events) { + $this->events = $events; + } + + /** + * Get a specific event callback + * @param $section + * @param $event + * + * @return Event + * @throws EventNotFoundException + */ + public function getEvent($section, $event) { + if (isset($this->events[$section])) { + return $this->events[$section][$event]; + } + throw new EventNotFoundException(); + } + + /** + * Get all events + * + * @return array + */ + public function getEvents(){ + return $this->events; + } + +} \ No newline at end of file diff --git a/htdocs/includes/webklex/php-imap/src/config/imap.php b/htdocs/includes/webklex/php-imap/src/config/imap.php new file mode 100644 index 00000000000..1b605ee0465 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/src/config/imap.php @@ -0,0 +1,216 @@ + 'd-M-Y', + + /* + |-------------------------------------------------------------------------- + | Default account + |-------------------------------------------------------------------------- + | + | The default account identifier. It will be used as default for any missing account parameters. + | If however the default account is missing a parameter the package default will be used. + | Set to 'false' [boolean] to disable this functionality. + | + */ + 'default' => 'default', + + /* + |-------------------------------------------------------------------------- + | Available accounts + |-------------------------------------------------------------------------- + | + | Please list all IMAP accounts which you are planning to use within the + | array below. + | + */ + 'accounts' => [ + + 'default' => [// account identifier + 'host' => 'localhost', + 'port' => 993, + 'protocol' => 'imap', //might also use imap, [pop3 or nntp (untested)] + 'encryption' => 'ssl', // Supported: false, 'ssl', 'tls' + 'validate_cert' => true, + 'username' => 'root@example.com', + 'password' => '', + 'authentication' => null, + 'proxy' => [ + 'socket' => null, + 'request_fulluri' => false, + 'username' => null, + 'password' => null, + ], + "timeout" => 30 + ], + + /* + 'gmail' => [ // account identifier + 'host' => 'imap.gmail.com', + 'port' => 993, + 'encryption' => 'ssl', + 'validate_cert' => true, + 'username' => 'example@gmail.com', + 'password' => 'PASSWORD', + 'authentication' => 'oauth', + ], + + 'another' => [ // account identifier + 'host' => '', + 'port' => 993, + 'encryption' => false, + 'validate_cert' => true, + 'username' => '', + 'password' => '', + 'authentication' => null, + ] + */ + ], + + /* + |-------------------------------------------------------------------------- + | Available IMAP options + |-------------------------------------------------------------------------- + | + | Available php imap config parameters are listed below + | -Delimiter (optional): + | This option is only used when calling $oClient-> + | You can use any supported char such as ".", "/", (...) + | -Fetch option: + | IMAP::FT_UID - Message marked as read by fetching the body message + | IMAP::FT_PEEK - Fetch the message without setting the "seen" flag + | -Fetch sequence id: + | IMAP::ST_UID - Fetch message components using the message uid + | IMAP::ST_MSGN - Fetch message components using the message number + | -Body download option + | Default TRUE + | -Flag download option + | Default TRUE + | -Soft fail + | Default FALSE - Set to TRUE if you want to ignore certain exception while fetching bulk messages + | -RFC822 + | Default TRUE - Set to FALSE to prevent the usage of \imap_rfc822_parse_headers(). + | See https://github.com/Webklex/php-imap/issues/115 for more information. + | -Message key identifier option + | You can choose between the following: + | 'id' - Use the MessageID as array key (default, might cause hickups with yahoo mail) + | 'number' - Use the message number as array key (isn't always unique and can cause some interesting behavior) + | 'list' - Use the message list number as array key (incrementing integer (does not always start at 0 or 1) + | 'uid' - Use the message uid as array key (isn't always unique and can cause some interesting behavior) + | -Fetch order + | 'asc' - Order all messages ascending (probably results in oldest first) + | 'desc' - Order all messages descending (probably results in newest first) + | -Disposition types potentially considered an attachment + | Default ['attachment', 'inline'] + | -Common folders + | Default folder locations and paths assumed if none is provided + | -Open IMAP options: + | DISABLE_AUTHENTICATOR - Disable authentication properties. + | Use 'GSSAPI' if you encounter the following + | error: "Kerberos error: No credentials cache + | file found (try running kinit) (...)" + | or ['GSSAPI','PLAIN'] if you are using outlook mail + | -Decoder options (currently only the message subject and attachment name decoder can be set) + | 'utf-8' - Uses imap_utf8($string) to decode a string + | 'mimeheader' - Uses mb_decode_mimeheader($string) to decode a string + | + */ + 'options' => [ + 'delimiter' => '/', + 'fetch' => \Webklex\PHPIMAP\IMAP::FT_PEEK, + 'sequence' => \Webklex\PHPIMAP\IMAP::ST_MSGN, + 'fetch_body' => true, + 'fetch_flags' => true, + 'soft_fail' => false, + 'rfc822' => true, + 'message_key' => 'list', + 'fetch_order' => 'asc', + 'dispositions' => ['attachment', 'inline'], + 'common_folders' => [ + "root" => "INBOX", + "junk" => "INBOX/Junk", + "draft" => "INBOX/Drafts", + "sent" => "INBOX/Sent", + "trash" => "INBOX/Trash", + ], + 'decoder' => [ + 'message' => 'utf-8', // mimeheader + 'attachment' => 'utf-8' // mimeheader + ], + 'open' => [ + // 'DISABLE_AUTHENTICATOR' => 'GSSAPI' + ] + ], + + /* + |-------------------------------------------------------------------------- + | Available flags + |-------------------------------------------------------------------------- + | + | List all available / supported flags. Set to null to accept all given flags. + */ + 'flags' => ['recent', 'flagged', 'answered', 'deleted', 'seen', 'draft'], + + /* + |-------------------------------------------------------------------------- + | Available events + |-------------------------------------------------------------------------- + | + */ + 'events' => [ + "message" => [ + 'new' => \Webklex\PHPIMAP\Events\MessageNewEvent::class, + 'moved' => \Webklex\PHPIMAP\Events\MessageMovedEvent::class, + 'copied' => \Webklex\PHPIMAP\Events\MessageCopiedEvent::class, + 'deleted' => \Webklex\PHPIMAP\Events\MessageDeletedEvent::class, + 'restored' => \Webklex\PHPIMAP\Events\MessageRestoredEvent::class, + ], + "folder" => [ + 'new' => \Webklex\PHPIMAP\Events\FolderNewEvent::class, + 'moved' => \Webklex\PHPIMAP\Events\FolderMovedEvent::class, + 'deleted' => \Webklex\PHPIMAP\Events\FolderDeletedEvent::class, + ], + "flag" => [ + 'new' => \Webklex\PHPIMAP\Events\FlagNewEvent::class, + 'deleted' => \Webklex\PHPIMAP\Events\FlagDeletedEvent::class, + ], + ], + + /* + |-------------------------------------------------------------------------- + | Available masking options + |-------------------------------------------------------------------------- + | + | By using your own custom masks you can implement your own methods for + | a better and faster access and less code to write. + | + | Checkout the two examples custom_attachment_mask and custom_message_mask + | for a quick start. + | + | The provided masks below are used as the default masks. + */ + 'masks' => [ + 'message' => \Webklex\PHPIMAP\Support\Masks\MessageMask::class, + 'attachment' => \Webklex\PHPIMAP\Support\Masks\AttachmentMask::class + ] +]; diff --git a/htdocs/includes/webklex/php-imap/tests/InitialTest.php b/htdocs/includes/webklex/php-imap/tests/InitialTest.php new file mode 100644 index 00000000000..fb854db4ad0 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/tests/InitialTest.php @@ -0,0 +1,26 @@ +cm = new ClientManager(); + } + + public function testConfigDefaultAccount() { + $this->assertEquals("default", ClientManager::get("default")); + } +} \ No newline at end of file From dc0e5e8d893ede8039b8d34cec614fb8392a84d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Fri, 12 Aug 2022 10:59:15 +0200 Subject: [PATCH 547/826] keep batch info when correcting stock --- .../product/stock/tpl/stockcorrection.tpl.php | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/htdocs/product/stock/tpl/stockcorrection.tpl.php b/htdocs/product/stock/tpl/stockcorrection.tpl.php index 08a66d1b8c6..eb927756263 100644 --- a/htdocs/product/stock/tpl/stockcorrection.tpl.php +++ b/htdocs/product/stock/tpl/stockcorrection.tpl.php @@ -41,6 +41,19 @@ if (empty($id)) { $id = $object->id; } +$pdluoid = GETPOST('pdluoid', 'int'); + +$pdluo = new Productbatch($db); + +if ($pdluoid > 0) { + $result = $pdluo->fetch($pdluoid); + if ($result > 0) { + $pdluoid = $pdluo->id; + } else { + dol_print_error($db, $pdluo->error, $pdluo->errors); + } +} + print ' + + + + + + + diff --git a/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/directory.html.dist b/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/directory.html.dist new file mode 100644 index 00000000000..efe743f5142 --- /dev/null +++ b/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/directory.html.dist @@ -0,0 +1,61 @@ + + + + + Code Coverage for {{full_path}} + + + + + + +
+
+
+
+ +
+
+
+
+
+ + + + + + + + + + + + + + +{{items}} + +
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
+ +
+ + + + + diff --git a/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/directory_item.html.dist b/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/directory_item.html.dist new file mode 100644 index 00000000000..78dbb3565ce --- /dev/null +++ b/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/directory_item.html.dist @@ -0,0 +1,13 @@ +
{{icon}}{{name}}{{lines_bar}}
{{lines_executed_percent}}
{{lines_number}}
{{methods_bar}}
{{methods_tested_percent}}
{{methods_number}}
{{classes_bar}}
{{classes_tested_percent}}
{{classes_number}}
+ + + + + + + + + + + + + +{{items}} + +
 
Code Coverage
 
Classes and Traits
Functions and Methods
Lines
+ + +{{lines}} + +
+
+
+ + + + + + diff --git a/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/file_item.html.dist b/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/file_item.html.dist new file mode 100644 index 00000000000..756fdd69b1b --- /dev/null +++ b/htdocs/includes/webklex/php-imap/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Template/file_item.html.dist @@ -0,0 +1,14 @@ +
{{name}}{{classes_bar}}
{{classes_tested_percent}}
{{classes_number}}
{{methods_bar}}
{{methods_tested_percent}}
{{methods_number}}
{{crap}}{{lines_bar}}
{{lines_executed_percent}}
{{lines_number}}
a",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function aa(){return!0}function ba(){return!1}function ca(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),ha=/^\s+/,ia=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ja=/<([\w:]+)/,ka=/
","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:k.htmlSerialize?[0,"",""]:[1,"X
","
"]},sa=da(y),ta=sa.appendChild(y.createElement("div"));ra.optgroup=ra.option,ra.tbody=ra.tfoot=ra.colgroup=ra.caption=ra.thead,ra.th=ra.td;function ua(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ua(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function va(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wa(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xa(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function ya(a){var b=pa.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function za(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Aa(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Ba(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xa(b).text=a.text,ya(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!ga.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(ta.innerHTML=a.outerHTML,ta.removeChild(f=ta.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ua(f),h=ua(a),g=0;null!=(e=h[g]);++g)d[g]&&Ba(e,d[g]);if(b)if(c)for(h=h||ua(a),d=d||ua(f),g=0;null!=(e=h[g]);g++)Aa(e,d[g]);else Aa(a,f);return d=ua(f,"script"),d.length>0&&za(d,!i&&ua(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=da(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(la.test(f)){h=h||o.appendChild(b.createElement("div")),i=(ja.exec(f)||["",""])[1].toLowerCase(),l=ra[i]||ra._default,h.innerHTML=l[1]+f.replace(ia,"<$1>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&ha.test(f)&&p.push(b.createTextNode(ha.exec(f)[0])),!k.tbody){f="table"!==i||ka.test(f)?""!==l[1]||ka.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ua(p,"input"),va),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ua(o.appendChild(f),"script"),g&&za(h),c)){e=0;while(f=h[e++])oa.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ua(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&za(ua(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ua(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fa,""):void 0;if(!("string"!=typeof a||ma.test(a)||!k.htmlSerialize&&ga.test(a)||!k.leadingWhitespace&&ha.test(a)||ra[(ja.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ia,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ua(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ua(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&na.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ua(i,"script"),xa),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ua(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,ya),j=0;f>j;j++)d=g[j],oa.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qa,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Ca,Da={};function Ea(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fa(a){var b=y,c=Da[a];return c||(c=Ea(a,b),"none"!==c&&c||(Ca=(Ca||m("\'); - $tmpdialog.dialog({ - autoOpen: false, - modal: true, - height: (window.innerHeight - 150), - width: \'80%\', - title: \''.dol_escape_js($label).'\', - open: function (event, ui) { - console.log("open popup name='.$name.', backtopagejsfields='.$backtopagejsfields.'"); - }, - close: function (event, ui) { - returnedid = jQuery("#varforreturndialogid'.$name.'").text(); - returnedlabel = jQuery("#varforreturndialoglabel'.$name.'").text(); - console.log("popup has been closed. returnedid (js var defined into parent page)="+returnedid+" returnedlabel="+returnedlabel); - if (returnedid != "" && returnedid != "div for returned id") { - jQuery("#'.(empty($backtopagejsfieldsid)?"none":$backtopagejsfieldsid).'").val(returnedid); + $out .= ''; + $out .= 'use_javascript_ajax)) { + $out .= ' href="'.DOL_URL_ROOT.$url.'" target="_blank"'; + } + $out .= '>'.$buttonstring.''; + if (!empty($conf->use_javascript_ajax)) { + $out .= ''; + $out .= ''; + $out .= ''; + $out .= ''; + $out .= ''; + '; + } return $out; } diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 29cfb898a2c..dd922e6cba4 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -2093,8 +2093,11 @@ if ($module == 'initmodule') { print ''.$langs->trans("IdModule").''; print ''; - print '   ('.$langs->trans("SeeIDsInUse").''; - print ' - '.$langs->trans("SeeReservedIDsRangeHere").')'; + print '   ('; + print dolButtonToOpenUrlInDialogPopup('popup_modules_id', $langs->transnoentitiesnoconv("SeeIDsInUse"), $langs->transnoentitiesnoconv("SeeIDsInUse"), '/admin/system/modules.php?mainmenu=home&leftmenu=admintools_info', '', ''); + print ' - '; + print ''.$langs->trans("SeeReservedIDsRangeHere").''; + print ')'; print ''; print '
'; print ''.$langs->trans("Version").'
'; From 48c94afd4c29133d59d325f467c35b796b44a82e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 23 Aug 2022 12:46:54 +0200 Subject: [PATCH 764/826] Trans --- htdocs/langs/en_US/modulebuilder.lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/langs/en_US/modulebuilder.lang b/htdocs/langs/en_US/modulebuilder.lang index 0bac9e2c435..cab8fa37f16 100644 --- a/htdocs/langs/en_US/modulebuilder.lang +++ b/htdocs/langs/en_US/modulebuilder.lang @@ -2,7 +2,7 @@ IdModule= Module id ModuleBuilderDesc=This tool must be used only by experienced users or developers. It provides utilities to build or edit your own module. Documentation for alternative manual development is here. EnterNameOfModuleDesc=Enter the name of the module/application to create with no spaces. Use uppercase to separate words (For example: MyModule, EcommerceForShop, SyncWithMySystem...) -EnterNameOfObjectDesc=Enter the name of the object to create with no spaces. Use uppercase to separate words (For example: MyObject, Student, Teacher...). The CRUD class file, but also API file, pages to list/add/edit/delete object and SQL files will be generated. +EnterNameOfObjectDesc=Enter the name of the object to create with no spaces. Use uppercase to separate words (For example: MyObject, Student, Teacher...). The CRUD class file, the pages to list/add/edit/delete the object and the SQL files will be generated. EnterNameOfDictionaryDesc=Enter the name of the dictionary to create with no spaces. Use uppercase to separate words (For example: MyDico...). The class file, but also the SQL file will be generated. ModuleBuilderDesc2=Path where modules are generated/edited (first directory for external modules defined into %s): %s ModuleBuilderDesc3=Generated/editable modules found: %s From 6c172b30f5acb27d587e676c4f37acf0b839fb9e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 23 Aug 2022 12:55:07 +0200 Subject: [PATCH 765/826] Fix translation of label --- htdocs/core/modules/modHoliday.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/modHoliday.class.php b/htdocs/core/modules/modHoliday.class.php index 53f69dfefaf..429e511de48 100644 --- a/htdocs/core/modules/modHoliday.class.php +++ b/htdocs/core/modules/modHoliday.class.php @@ -140,7 +140,7 @@ class modHoliday extends DolibarrModules $datestart = dol_mktime(4, 0, 0, $arraydate['mon'], $arraydate['mday'], $arraydate['year']); $this->cronjobs = array( 0 => array( - 'label' => 'HolidayBalanceMonthlyUpdate', + 'label' => 'HolidayBalanceMonthlyUpdate:holiday', 'jobtype' => 'method', 'class' => 'holiday/class/holiday.class.php', 'objectname' => 'Holiday', From f2dd9904ea0e9a10365a583f02d32114baad7981 Mon Sep 17 00:00:00 2001 From: Quatadah Nasdami Date: Tue, 23 Aug 2022 13:19:10 +0200 Subject: [PATCH 766/826] template 04 improved --- .../websites/website_template-style04.zip | Bin 6971768 -> 6973584 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/htdocs/install/doctemplates/websites/website_template-style04.zip b/htdocs/install/doctemplates/websites/website_template-style04.zip index 322c9d34ece6fe2378888f53437b689e11e83b0c..996d98697c36c01d275a51085df08610d19753ff 100644 GIT binary patch delta 32537 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 F{{RD>b%Ou^ delta 31042 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 E2ehRIb^rhX From 0696fcc5953676c4168f2e153d58f6c05cc1d27b Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Tue, 23 Aug 2022 19:47:21 +0200 Subject: [PATCH 767/826] Update ChangeLog Changelog 16 - For developers ... add section API --- ChangeLog | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index f5a53161ae1..e99731fe548 100644 --- a/ChangeLog +++ b/ChangeLog @@ -149,7 +149,6 @@ For developers or integrators: NEW: dol_uncompress() supports more extensions (.gz, .bz2, .zstd). Only .zip was supported before. NEW: Implement a generic method for Kaban views NEW: Upgrade chartjs library to 3.7.1 -NEW: update rank line is possible on API for customer invoices, sales orders and supplier invoice NEW: stripe element with more gateways NEW: solde() function evolution to be able to get solde until a chosen date NEW: Suggest a way to run upgrade per entities. @@ -158,7 +157,6 @@ NEW: ModuleBuilder - Add tabs view in module builder NEW: ModuleBuilder - More feature that can be modifed after module generation NEW: Identification of tr is possible with by attribute data-id on some pages NEW: Import with select boxes V2 -NEW: Can update rank of invoice, proposal and order lines with API update NEW: Can use current entity filter on 'chkbxlst' NEW: Creation of the function select_bom() used to display bom select list NEW: add printFieldListWhere hook in product reassort card @@ -166,32 +164,33 @@ NEW: Add trigger and event on completely received status change NEW: Add utility function send backup by mail NEW: add WordPress OAuth to save a token (not SSO) NEW: A module can embed a sql script run at each Dolibarr upgrade -NEW: API Proposals - Add POST lines -NEW: API REST filter states by country NEW: Add option INVOICEREC_SET_AUTOFILL_DATE_START/END -NEW: Add option MAIN_API_DEBUG to save API logs into a file NEW: Add param to keep the robot=index meta tag on public pages NEW: Add method hintindex() in database handlers. NEW: add modifications for new function "$db->prefix()" NEW: addMoreActionsButtonsList hook for button in list -NEW: Add API to get a template invoice NEW: Standardize a lot of code. -NEW: #20736 Allow extrafields SQL filters on REST API product lookup -NEW: #19294 implement detailed timespent in task of project API NEW: Add a protection into PHPunit to avoid to forget a var_dump -NEW: Add datem and type parameters to API to create movements NEW: Add hidden option on contract PDF line to hide qty and price NEW: Option MAIL_MASS_ACTION_ADD_LAST_IF_MAIN_DOC_NOT_FOUND to send last document in mass mailing action +API: +NEW: API Proposals - Add POST lines +NEW: API REST filter states by country +NEW: Add API to get a template invoice +NEW: Add datem and type parameters to API to create movements +NEW: #19294 implement detailed timespent in task of project API +NEW: #20736 Allow extrafields SQL filters on REST API product lookup +NEW: Can update rank of invoice, proposal and order lines with API update +NEW: update rank line is possible on API for customer invoices, sales orders and supplier invoice +NEW: Add option MAIN_API_DEBUG to save API logs into a file + Hooks: NEW: Hook getNomUrl available everywhere in tooltip of ref links NEW: Add hooks: selectContactListWhere hook, selectThirdpartyListWhere hook -NEW: TakePos - add hooks complete product display -NEW: TakePos - add hooks for cart display -NEW: TakePos - add hooks to complete ajax return array NEW: Add hook before the public ticket list NEW: Add hook doaction in takepos invoice -NEW: Add Hook for Notif +NEW: Add hook for Notif NEW: Add hook for more buttons NEW: Add hook printFieldListWhere in "show_contacts" function NEW: Add hook printFieldWhere in load_state_board function @@ -204,6 +203,9 @@ NEW: Add hooks on project task time page NEW: Add hooks on salaries and sociales card NEW: Add hooks select product list and select thirdparty list function NEW: Add hook to getSellPrice function +NEW: TakePos - add hooks complete product display +NEW: TakePos - add hooks for cart display +NEW: TakePos - add hooks to complete ajax return array WARNING: From 4bef0f574586398f447190541c9362d510d97666 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20France?= Date: Tue, 23 Aug 2022 20:01:34 +0200 Subject: [PATCH 768/826] use isModEnabled --- htdocs/adherents/admin/member.php | 12 +++--- htdocs/adherents/class/adherent.class.php | 2 +- htdocs/adherents/subscription/card.php | 8 ++-- htdocs/admin/commande.php | 2 +- htdocs/admin/dict.php | 38 +++++++++---------- htdocs/admin/eventorganization.php | 2 +- htdocs/admin/fckeditor.php | 6 +-- htdocs/admin/hrm.php | 2 +- htdocs/admin/ldap.php | 2 +- htdocs/admin/mails_templates.php | 8 ++-- htdocs/admin/notification.php | 6 +-- htdocs/admin/propal.php | 2 +- htdocs/admin/stock.php | 8 ++-- htdocs/admin/webhook.php | 2 +- htdocs/admin/workflow.php | 18 ++++----- htdocs/asset/admin/setup.php | 2 +- htdocs/blockedlog/class/blockedlog.class.php | 2 +- htdocs/bom/tpl/objectline_create.tpl.php | 2 +- htdocs/comm/action/card.php | 6 +-- .../action/class/api_agendaevents.class.php | 6 +-- .../comm/action/class/cactioncomm.class.php | 4 +- htdocs/comm/card.php | 16 ++++---- htdocs/comm/index.php | 8 ++-- htdocs/comm/propal/card.php | 8 ++-- htdocs/comm/propal/index.php | 4 +- htdocs/comm/propal/list.php | 4 +- htdocs/comm/prospect/index.php | 6 +-- htdocs/commande/card.php | 6 +-- htdocs/commande/class/commande.class.php | 2 +- htdocs/commande/list.php | 4 +- htdocs/compta/accounting-files.php | 2 +- .../bank/class/paymentvarious.class.php | 6 +-- htdocs/compta/bank/various_payment/card.php | 8 ++-- htdocs/compta/bank/various_payment/list.php | 4 +- htdocs/compta/charges/index.php | 10 ++--- htdocs/compta/facture/card.php | 22 +++++------ .../facture/class/api_invoices.class.php | 8 ++-- htdocs/compta/localtax/card.php | 4 +- .../compta/localtax/class/localtax.class.php | 6 +-- htdocs/compta/paiement.php | 6 +-- htdocs/compta/paiement/card.php | 6 +-- .../compta/paiement/class/paiement.class.php | 2 +- htdocs/compta/paiement/list.php | 4 +- htdocs/compta/paiement_charge.php | 2 +- htdocs/compta/paiement_vat.php | 2 +- htdocs/compta/payment_sc/card.php | 4 +- htdocs/compta/payment_vat/card.php | 4 +- htdocs/compta/resultat/clientfourn.php | 2 +- htdocs/compta/resultat/index.php | 2 +- htdocs/compta/sociales/card.php | 10 ++--- .../class/paymentsocialcontribution.class.php | 2 +- htdocs/compta/sociales/list.php | 2 +- htdocs/compta/sociales/payments.php | 8 ++-- htdocs/compta/stats/cabyuser.php | 2 +- htdocs/compta/stats/casoc.php | 2 +- htdocs/compta/tva/card.php | 10 ++--- htdocs/compta/tva/class/paymentvat.class.php | 2 +- htdocs/compta/tva/class/tva.class.php | 6 +-- htdocs/compta/tva/list.php | 2 +- htdocs/compta/tva/payments.php | 6 +-- .../actions_contactcard_common.class.php | 2 +- htdocs/contact/card.php | 12 +++--- htdocs/contact/consumption.php | 2 +- htdocs/contrat/card.php | 2 +- htdocs/core/boxes/box_activity.php | 2 +- .../boxes/box_graph_product_distribution.php | 4 +- htdocs/core/boxes/box_produits.php | 2 +- .../core/boxes/box_produits_alerte_stock.php | 2 +- htdocs/core/class/html.form.class.php | 8 ++-- htdocs/core/class/html.formbarcode.class.php | 4 +- htdocs/core/class/html.formmargin.class.php | 4 +- htdocs/core/class/html.formsetup.class.php | 2 +- htdocs/core/lib/contact.lib.php | 2 +- htdocs/core/lib/expedition.lib.php | 2 +- htdocs/core/lib/files.lib.php | 4 +- htdocs/core/lib/functions.lib.php | 8 ++-- htdocs/core/lib/ldap.lib.php | 2 +- htdocs/core/lib/order.lib.php | 2 +- htdocs/core/lib/pdf.lib.php | 2 +- htdocs/core/lib/product.lib.php | 8 ++-- htdocs/core/lib/project.lib.php | 8 ++-- htdocs/core/lib/propal.lib.php | 4 +- htdocs/core/lib/security.lib.php | 6 +-- htdocs/core/modules/DolibarrModules.class.php | 2 +- .../doc/pdf_standard.modules.php | 4 +- htdocs/core/modules/modAdherent.class.php | 6 +-- htdocs/core/modules/modCategorie.class.php | 18 ++++----- .../doc/doc_generic_project_odt.modules.php | 2 +- .../task/doc/doc_generic_task_odt.modules.php | 2 +- .../modules/propale/doc/pdf_azur.modules.php | 4 +- .../modules/propale/doc/pdf_cyan.modules.php | 4 +- .../modules/rapport/pdf_paiement.class.php | 12 +++--- htdocs/core/tpl/objectline_create.tpl.php | 12 +++--- htdocs/core/tpl/objectline_edit.tpl.php | 2 +- ...e_20_modWorkflow_WorkflowManager.class.php | 12 +++--- htdocs/delivery/card.php | 6 +-- htdocs/delivery/class/delivery.class.php | 2 +- htdocs/don/admin/donation.php | 2 +- htdocs/don/card.php | 8 ++-- htdocs/don/class/paymentdonation.class.php | 2 +- htdocs/don/payment/card.php | 4 +- htdocs/don/payment/payment.php | 2 +- htdocs/ecm/index_auto.php | 10 ++--- htdocs/ecm/search.php | 10 ++--- htdocs/expedition/card.php | 10 ++--- htdocs/expedition/class/expedition.class.php | 2 +- htdocs/expedition/contact.php | 4 +- htdocs/expedition/note.php | 2 +- htdocs/expedition/shipment.php | 4 +- htdocs/expensereport/card.php | 8 ++-- .../class/paymentexpensereport.class.php | 2 +- htdocs/expensereport/payment/card.php | 4 +- htdocs/expensereport/payment/list.php | 2 +- htdocs/expensereport/payment/payment.php | 4 +- htdocs/fichinter/card.php | 2 +- htdocs/fourn/card.php | 2 +- .../class/api_supplier_invoices.class.php | 4 +- htdocs/fourn/commande/card.php | 6 +-- htdocs/fourn/commande/dispatch.php | 6 +-- htdocs/fourn/facture/card.php | 12 +++--- htdocs/fourn/facture/paiement.php | 4 +- htdocs/fourn/paiement/card.php | 2 +- htdocs/fourn/paiement/document.php | 2 +- htdocs/fourn/paiement/list.php | 2 +- htdocs/install/upgrade2.php | 2 +- htdocs/loan/card.php | 2 +- htdocs/loan/class/paymentloan.class.php | 2 +- htdocs/loan/payment/card.php | 4 +- htdocs/loan/payment/payment.php | 2 +- htdocs/main.inc.php | 8 ++-- htdocs/paybox/admin/paybox.php | 2 +- htdocs/paypal/admin/paypal.php | 2 +- htdocs/product/card.php | 10 ++--- htdocs/product/class/product.class.php | 4 +- htdocs/product/composition/card.php | 2 +- htdocs/product/document.php | 4 +- htdocs/product/fournisseurs.php | 2 +- htdocs/product/index.php | 10 ++--- htdocs/product/list.php | 30 +++++++-------- htdocs/product/price.php | 6 +-- htdocs/product/stock/product.php | 4 +- htdocs/product/stock/replenish.php | 2 +- htdocs/projet/card.php | 2 +- htdocs/projet/element.php | 8 ++-- htdocs/public/payment/paymentok.php | 16 ++++---- htdocs/reception/card.php | 16 ++++---- htdocs/reception/class/reception.class.php | 2 +- htdocs/reception/contact.php | 2 +- htdocs/reception/note.php | 2 +- htdocs/resource/element_resource.php | 2 +- htdocs/salaries/card.php | 14 +++---- htdocs/salaries/class/paymentsalary.class.php | 2 +- htdocs/salaries/class/salary.class.php | 4 +- htdocs/salaries/list.php | 8 ++-- htdocs/salaries/paiement_salary.php | 2 +- htdocs/salaries/payment_salary/card.php | 4 +- htdocs/salaries/payments.php | 6 +-- htdocs/societe/admin/societe.php | 2 +- htdocs/societe/consumption.php | 2 +- htdocs/societe/paymentmodes.php | 2 +- htdocs/supplier_proposal/card.php | 6 +-- htdocs/takepos/admin/terminal.php | 4 +- htdocs/takepos/index.php | 2 +- htdocs/takepos/invoice.php | 2 +- htdocs/ticket/agenda.php | 2 +- htdocs/ticket/card.php | 2 +- htdocs/ticket/contact.php | 2 +- htdocs/ticket/document.php | 2 +- htdocs/ticket/messaging.php | 2 +- htdocs/user/card.php | 4 +- htdocs/user/param_ihm.php | 6 +-- htdocs/user/perms.php | 4 +- htdocs/variants/combinations.php | 2 +- htdocs/webservices/admin/index.php | 8 ++-- 174 files changed, 450 insertions(+), 450 deletions(-) diff --git a/htdocs/adherents/admin/member.php b/htdocs/adherents/admin/member.php index 80092ea96a5..12ce3973c32 100644 --- a/htdocs/adherents/admin/member.php +++ b/htdocs/adherents/admin/member.php @@ -111,7 +111,7 @@ if ($action == 'set_default') { if (isModEnabled('facture')) { $res4 = dolibarr_set_const($db, 'ADHERENT_VAT_FOR_SUBSCRIPTIONS', GETPOST('ADHERENT_VAT_FOR_SUBSCRIPTIONS', 'alpha'), 'chaine', 0, '', $conf->entity); $res5 = dolibarr_set_const($db, 'ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS', GETPOST('ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS', 'alpha'), 'chaine', 0, '', $conf->entity); - if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { + if (isModEnabled("product") || !empty($conf->service->enabled)) { $res6 = dolibarr_set_const($db, 'ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS', GETPOST('ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS', 'alpha'), 'chaine', 0, '', $conf->entity); } } @@ -238,13 +238,13 @@ print "\n"; // Insert subscription into bank account print ''; $arraychoices = array('0'=>$langs->trans("None")); -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { $arraychoices['bankdirect'] = $langs->trans("MoreActionBankDirect"); } -if (!empty($conf->banque->enabled) && !empty($conf->societe->enabled) && isModEnabled('facture')) { +if (isModEnabled("banque") && isModEnabled("societe") && isModEnabled('facture')) { $arraychoices['invoiceonly'] = $langs->trans("MoreActionInvoiceOnly"); } -if (!empty($conf->banque->enabled) && !empty($conf->societe->enabled) && isModEnabled('facture')) { +if (isModEnabled("banque") && isModEnabled("societe") && isModEnabled('facture')) { $arraychoices['bankviainvoice'] = $langs->trans("MoreActionBankViaInvoice"); } print '\n"; // Use vat for invoice creation if (isModEnabled('facture')) { print ''; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print ''; @@ -269,7 +269,7 @@ if (isModEnabled('facture')) { } print "\n"; - if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { + if (isModEnabled("product") || !empty($conf->service->enabled)) { print ''; print ''; // Bank line - if (!empty($conf->banque->enabled) && ($conf->global->ADHERENT_BANK_USE || $object->fk_bank)) { + if (isModEnabled("banque") && ($conf->global->ADHERENT_BANK_USE || $object->fk_bank)) { print ''; // Bank line - if (!empty($conf->banque->enabled) && ($conf->global->ADHERENT_BANK_USE || $object->fk_bank)) { + if (isModEnabled("banque") && ($conf->global->ADHERENT_BANK_USE || $object->fk_bank)) { print ''; print ""; print "'; // Synchro contact active -if (!empty($conf->societe->enabled)) { +if (isModEnabled("societe")) { print ''; diff --git a/htdocs/admin/mails_templates.php b/htdocs/admin/mails_templates.php index 0c12ba1a3a0..95fd36d91d6 100644 --- a/htdocs/admin/mails_templates.php +++ b/htdocs/admin/mails_templates.php @@ -185,13 +185,13 @@ if (!empty($conf->adherent->enabled) && !empty($user->rights->adherent->lire)) { if (!empty($conf->recruitment->enabled) && !empty($user->rights->recruitment->recruitmentjobposition->read)) { $elementList['recruitmentcandidature_send'] = img_picto('', 'recruitmentcandidature', 'class="pictofixedwidth"').dol_escape_htmltag($langs->trans('RecruitmentCandidatures')); } -if (!empty($conf->societe->enabled) && !empty($user->rights->societe->lire)) { +if (isModEnabled("societe") && !empty($user->rights->societe->lire)) { $elementList['thirdparty'] = img_picto('', 'company', 'class="pictofixedwidth"').dol_escape_htmltag($langs->trans('MailToThirdparty')); } if (!empty($conf->project->enabled)) { $elementList['project'] = img_picto('', 'project', 'class="pictofixedwidth"').dol_escape_htmltag($langs->trans('MailToProject')); } -if (!empty($conf->propal->enabled) && !empty($user->rights->propal->lire)) { +if (isModEnabled("propal") && !empty($user->rights->propal->lire)) { $elementList['propal_send'] = img_picto('', 'propal', 'class="pictofixedwidth"').dol_escape_htmltag($langs->trans('MailToSendProposal')); } if (!empty($conf->commande->enabled) && !empty($user->rights->commande->lire)) { @@ -200,10 +200,10 @@ if (!empty($conf->commande->enabled) && !empty($user->rights->commande->lire)) { if (isModEnabled('facture') && !empty($user->rights->facture->lire)) { $elementList['facture_send'] = img_picto('', 'bill', 'class="pictofixedwidth"').dol_escape_htmltag($langs->trans('MailToSendInvoice')); } -if (!empty($conf->expedition->enabled)) { +if (isModEnabled("expedition")) { $elementList['shipping_send'] = img_picto('', 'dolly', 'class="pictofixedwidth"').dol_escape_htmltag($langs->trans('MailToSendShipment')); } -if (!empty($conf->reception->enabled)) { +if (isModEnabled("reception")) { $elementList['reception_send'] = img_picto('', 'dollyrevert', 'class="pictofixedwidth"').dol_escape_htmltag($langs->trans('MailToSendReception')); } if (!empty($conf->ficheinter->enabled)) { diff --git a/htdocs/admin/notification.php b/htdocs/admin/notification.php index 760df948d34..44b5c104813 100644 --- a/htdocs/admin/notification.php +++ b/htdocs/admin/notification.php @@ -177,7 +177,7 @@ print load_fiche_titre($langs->trans("NotificationSetup"), $linkback, 'title_set print ''; print $langs->trans("NotificationsDesc").'
'; print $langs->trans("NotificationsDescUser").'
'; -if (!empty($conf->societe->enabled)) { +if (isModEnabled("societe")) { print $langs->trans("NotificationsDescContact").'
'; } print $langs->trans("NotificationsDescGlobal").'
'; @@ -361,7 +361,7 @@ print $form->buttonsSaveCancel("Save", ''); print '
'; print '* '.$langs->trans("GoOntoUserCardToAddMore").'
'; - if (!empty($conf->societe->enabled)) { + if (isModEnabled("societe")) { print '** '.$langs->trans("GoOntoContactCardToAddMore").'
'; } print '
'; @@ -384,7 +384,7 @@ print load_fiche_titre($langs->trans("ListOfFixedNotifications"), '', 'email'); print '
'; print $langs->trans("Note").':
'; print '* '.$langs->trans("GoOntoUserCardToAddMore").'
'; -if (!empty($conf->societe->enabled)) { +if (isModEnabled("societe")) { print '** '.$langs->trans("GoOntoContactCardToAddMore").'
'; } print '
'; diff --git a/htdocs/admin/propal.php b/htdocs/admin/propal.php index c324f33ba92..a83e08ba4cf 100644 --- a/htdocs/admin/propal.php +++ b/htdocs/admin/propal.php @@ -525,7 +525,7 @@ print '
'; print ""; print "'; print ''; print ''; print ''; print '\n\n"; $found++; -if (!empty($conf->reception->enabled)) { +if (isModEnabled("reception")) { print ''; print ''; print '\n"; } -if (!empty($conf->expedition->enabled)) { +if (isModEnabled("expedition")) { print ''; print ''; print '
'.$langs->trans("MoreActionsOnSubscription").''; @@ -258,7 +258,7 @@ print "
'.$langs->trans("VATToUseForSubscriptions").''; print $form->selectarray('ADHERENT_VAT_FOR_SUBSCRIPTIONS', array('0'=>$langs->trans("NoVatOnSubscription"), 'defaultforfoundationcountry'=>$langs->trans("Default")), (empty($conf->global->ADHERENT_VAT_FOR_SUBSCRIPTIONS) ? '0' : $conf->global->ADHERENT_VAT_FOR_SUBSCRIPTIONS), 0); print '
'.$langs->trans("ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS").''; $selected = (empty($conf->global->ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS) ? '' : $conf->global->ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS); diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 36efd3bc7d1..185213db838 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -1773,7 +1773,7 @@ class Adherent extends CommonObject if (!$error) { // Add line to draft invoice $idprodsubscription = 0; - if (!empty($conf->global->ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS) && (!empty($conf->product->enabled) || !empty($conf->service->enabled))) { + if (!empty($conf->global->ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS) && (isModEnabled("product") || !empty($conf->service->enabled))) { $idprodsubscription = $conf->global->ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS; } diff --git a/htdocs/adherents/subscription/card.php b/htdocs/adherents/subscription/card.php index a18259fefe4..cd1c208e62c 100644 --- a/htdocs/adherents/subscription/card.php +++ b/htdocs/adherents/subscription/card.php @@ -27,7 +27,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/member.lib.php'; require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php'; require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent_type.class.php'; require_once DOL_DOCUMENT_ROOT.'/adherents/class/subscription.class.php'; -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; } @@ -229,7 +229,7 @@ if ($user->rights->adherent->cotisation->creer && $action == 'edit') { print '
'.$langs->trans("BankTransactionLine").''; if ($object->fk_bank) { $bankline = new AccountLine($db); @@ -270,7 +270,7 @@ if ($rowid && $action != 'edit') { //$formquestion=array(); //$formquestion['text']=''.$langs->trans("ThisWillAlsoDeleteBankRecord").''; $text = $langs->trans("ConfirmDeleteSubscription"); - if (!empty($conf->banque->enabled) && !empty($conf->global->ADHERENT_BANK_USE)) { + if (isModEnabled("banque") && !empty($conf->global->ADHERENT_BANK_USE)) { $text .= '
'.img_warning().' '.$langs->trans("ThisWillAlsoDeleteBankRecord"); } print $form->formconfirm($_SERVER["PHP_SELF"]."?rowid=".$object->id, $langs->trans("DeleteSubscription"), $text, "confirm_delete", $formquestion, 0, 1); @@ -325,7 +325,7 @@ if ($rowid && $action != 'edit') { print '
'.$langs->trans("Label").''.$object->note.'
'.$langs->trans("BankTransactionLine").''; if ($object->fk_bank) { $bankline = new AccountLine($db); diff --git a/htdocs/admin/commande.php b/htdocs/admin/commande.php index a2aa663f189..eec8bb16417 100644 --- a/htdocs/admin/commande.php +++ b/htdocs/admin/commande.php @@ -507,7 +507,7 @@ print '
".$langs->trans("SuggestPaymentByRIBOnAccount").""; if (empty($conf->facture->enabled)) { - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $sql = "SELECT rowid, label"; $sql .= " FROM ".MAIN_DB_PREFIX."bank_account"; $sql .= " WHERE clos = 0"; diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index 3cba1a333ca..987ef05cb37 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -483,33 +483,33 @@ $tabrowid[44] = "rowid"; // Condition to show dictionary in setup page $tabcond = array(); -$tabcond[1] = (!empty($conf->societe->enabled)); +$tabcond[1] = (isModEnabled("societe")); $tabcond[2] = true; $tabcond[3] = true; $tabcond[4] = true; -$tabcond[5] = (!empty($conf->societe->enabled) || !empty($conf->adherent->enabled)); +$tabcond[5] = (isModEnabled("societe") || !empty($conf->adherent->enabled)); $tabcond[6] = isModEnabled('agenda'); $tabcond[7] = !empty($conf->tax->enabled); -$tabcond[8] = !empty($conf->societe->enabled); +$tabcond[8] = isModEnabled("societe"); $tabcond[9] = true; $tabcond[10] = true; -$tabcond[11] = (!empty($conf->societe->enabled)); -$tabcond[12] = (!empty($conf->commande->enabled) || !empty($conf->propal->enabled) || isModEnabled('facture') || (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_invoice->enabled) || !empty($conf->supplier_order->enabled)); -$tabcond[13] = (!empty($conf->commande->enabled) || !empty($conf->propal->enabled) || isModEnabled('facture') || (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_invoice->enabled) || !empty($conf->supplier_order->enabled)); -$tabcond[14] = (!empty($conf->product->enabled) && (!empty($conf->ecotax->enabled) || !empty($conf->global->MAIN_SHOW_ECOTAX_DICTIONNARY))); +$tabcond[11] = (isModEnabled("societe")); +$tabcond[12] = (!empty($conf->commande->enabled) || isModEnabled("propal") || isModEnabled('facture') || (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_invoice->enabled) || !empty($conf->supplier_order->enabled)); +$tabcond[13] = (!empty($conf->commande->enabled) || isModEnabled("propal") || isModEnabled('facture') || (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_invoice->enabled) || !empty($conf->supplier_order->enabled)); +$tabcond[14] = (isModEnabled("product") && (!empty($conf->ecotax->enabled) || !empty($conf->global->MAIN_SHOW_ECOTAX_DICTIONNARY))); $tabcond[15] = true; -$tabcond[16] = (!empty($conf->societe->enabled) && empty($conf->global->SOCIETE_DISABLE_PROSPECTS)); +$tabcond[16] = (isModEnabled("societe") && empty($conf->global->SOCIETE_DISABLE_PROSPECTS)); $tabcond[17] = (!empty($conf->deplacement->enabled) || !empty($conf->expensereport->enabled)); -$tabcond[18] = !empty($conf->expedition->enabled) || !empty($conf->reception->enabled); -$tabcond[19] = !empty($conf->societe->enabled); +$tabcond[18] = isModEnabled("expedition") || isModEnabled("reception"); +$tabcond[19] = isModEnabled("societe"); $tabcond[20] = (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled); -$tabcond[21] = !empty($conf->propal->enabled); -$tabcond[22] = (!empty($conf->commande->enabled) || !empty($conf->propal->enabled)); +$tabcond[21] = isModEnabled("propal"); +$tabcond[22] = (!empty($conf->commande->enabled) || isModEnabled("propal")); $tabcond[23] = true; $tabcond[24] = !empty($conf->resource->enabled); $tabcond[25] = !empty($conf->website->enabled); -//$tabcond[26]= !empty($conf->product->enabled); -$tabcond[27] = !empty($conf->societe->enabled); +//$tabcond[26]= isModEnabled("product"); +$tabcond[27] = isModEnabled("societe"); $tabcond[28] = !empty($conf->holiday->enabled); $tabcond[29] = !empty($conf->project->enabled); $tabcond[30] = !empty($conf->label->enabled); @@ -519,13 +519,13 @@ $tabcond[33] = !empty($conf->hrm->enabled); $tabcond[34] = !empty($conf->hrm->enabled); $tabcond[35] = !empty($conf->expensereport->enabled) && !empty($conf->global->MAIN_USE_EXPENSE_IK); $tabcond[36] = !empty($conf->expensereport->enabled) && !empty($conf->global->MAIN_USE_EXPENSE_IK); -$tabcond[37] = !empty($conf->product->enabled); +$tabcond[37] = isModEnabled("product"); $tabcond[38] = !empty($conf->socialnetworks->enabled); -$tabcond[39] = (!empty($conf->societe->enabled) && empty($conf->global->SOCIETE_DISABLE_PROSPECTS) && !empty($conf->global->THIRDPARTY_ENABLE_PROSPECTION_ON_ALTERNATIVE_ADRESSES)); -$tabcond[40] = (!empty($conf->societe->enabled) && !empty($conf->global->THIRDPARTY_ENABLE_PROSPECTION_ON_ALTERNATIVE_ADRESSES)); +$tabcond[39] = (isModEnabled("societe") && empty($conf->global->SOCIETE_DISABLE_PROSPECTS) && !empty($conf->global->THIRDPARTY_ENABLE_PROSPECTION_ON_ALTERNATIVE_ADRESSES)); +$tabcond[40] = (isModEnabled("societe") && !empty($conf->global->THIRDPARTY_ENABLE_PROSPECTION_ON_ALTERNATIVE_ADRESSES)); $tabcond[41] = !empty($conf->intracommreport->enabled); -$tabcond[42] = !empty($conf->product->enabled); -$tabcond[43] = !empty($conf->product->enabled) && !empty($conf->productbatch->enabled) && $conf->global->MAIN_FEATURES_LEVEL >= 2; +$tabcond[42] = isModEnabled("product"); +$tabcond[43] = isModEnabled("product") && !empty($conf->productbatch->enabled) && $conf->global->MAIN_FEATURES_LEVEL >= 2; $tabcond[44] = !empty($conf->asset->enabled); // List of help for fields (no more used, help is defined into tabcomplete) diff --git a/htdocs/admin/eventorganization.php b/htdocs/admin/eventorganization.php index 66c6cc9a204..afeaa98d77e 100644 --- a/htdocs/admin/eventorganization.php +++ b/htdocs/admin/eventorganization.php @@ -278,7 +278,7 @@ if ($action == 'edit') { include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; print dolJSToSetRandomPassword($constname, 'generate_token'.$constname); } elseif ($val['type'] == 'product') { - if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { + if (isModEnabled("product") || !empty($conf->service->enabled)) { $selected = (empty($conf->global->$constname) ? '' : $conf->global->$constname); $form->select_produits($selected, $constname, '', 0); } diff --git a/htdocs/admin/fckeditor.php b/htdocs/admin/fckeditor.php index 3ea92bb48ad..c74645439bd 100644 --- a/htdocs/admin/fckeditor.php +++ b/htdocs/admin/fckeditor.php @@ -62,11 +62,11 @@ $conditions = array( 'NOTE_PUBLIC' => 1, 'NOTE_PRIVATE' => 1, 'SOCIETE' => 1, - 'PRODUCTDESC' => (!empty($conf->product->enabled) || !empty($conf->service->enabled)), - 'DETAILS' => (isModEnabled('facture') || !empty($conf->propal->enabled) || !empty($conf->commande->enabled) || !empty($conf->supplier_proposal->enabled) || (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)), + 'PRODUCTDESC' => (isModEnabled("product") || !empty($conf->service->enabled)), + 'DETAILS' => (isModEnabled('facture') || isModEnabled("propal") || !empty($conf->commande->enabled) || !empty($conf->supplier_proposal->enabled) || (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)), 'USERSIGN' => 1, 'MAILING' => !empty($conf->mailing->enabled), - 'MAIL' => (isModEnabled('facture') || !empty($conf->propal->enabled) || !empty($conf->commande->enabled)), + 'MAIL' => (isModEnabled('facture') || isModEnabled("propal") || !empty($conf->commande->enabled)), 'TICKET' => !empty($conf->ticket->enabled), ); // Picto diff --git a/htdocs/admin/hrm.php b/htdocs/admin/hrm.php index cfe40c006b7..2f90d6e9a77 100644 --- a/htdocs/admin/hrm.php +++ b/htdocs/admin/hrm.php @@ -545,7 +545,7 @@ if ($action == 'edit') { include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; print dolJSToSetRandomPassword($constname, 'generate_token'.$constname); } elseif ($val['type'] == 'product') { - if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { + if (isModEnabled("product") || !empty($conf->service->enabled)) { $selected = (empty($conf->global->$constname) ? '' : $conf->global->$constname); $form->select_produits($selected, $constname, '', 0); } diff --git a/htdocs/admin/ldap.php b/htdocs/admin/ldap.php index ef488943a4b..84d6a052196 100644 --- a/htdocs/admin/ldap.php +++ b/htdocs/admin/ldap.php @@ -158,7 +158,7 @@ if (!empty($conf->global->LDAP_SYNCHRO_ACTIVE) && empty($conf->global->LDAP_USER print '
'.$langs->trans("LDAPDnContactActive").''; print $formldap->selectLdapDnSynchroActive(getDolGlobalInt('LDAP_CONTACT_ACTIVE'), 'activecontact', array(Ldap::SYNCHRO_LDAP_TO_DOLIBARR)); print ''.$langs->trans("LDAPDnContactActiveExample").'
".$langs->trans("SuggestPaymentByRIBOnAccount").""; if (empty($conf->facture->enabled)) { - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $sql = "SELECT rowid, label"; $sql .= " FROM ".MAIN_DB_PREFIX."bank_account"; $sql .= " WHERE clos = 0"; diff --git a/htdocs/admin/stock.php b/htdocs/admin/stock.php index 2b25d7deb5a..cc025258587 100644 --- a/htdocs/admin/stock.php +++ b/htdocs/admin/stock.php @@ -245,7 +245,7 @@ $found++; print '
'.$langs->trans("DeStockOnShipment").''; -if (!empty($conf->expedition->enabled)) { +if (isModEnabled("expedition")) { if ($conf->use_javascript_ajax) { print ajax_constantonoff('STOCK_CALCULATE_ON_SHIPMENT', array(), null, 0, 0, 0, 2, 1); } else { @@ -262,7 +262,7 @@ $found++; print '
'.$langs->trans("DeStockOnShipmentOnClosing").''; -if (!empty($conf->expedition->enabled)) { +if (isModEnabled("expedition")) { if ($conf->use_javascript_ajax) { print ajax_constantonoff('STOCK_CALCULATE_ON_SHIPMENT_CLOSE', array(), null, 0, 0, 0, 2, 1); } else { @@ -324,7 +324,7 @@ if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SU print "
'.$langs->trans("StockOnReception").''; @@ -422,7 +422,7 @@ if (!empty($conf->order->enabled)) { print "
'.$langs->trans("StockMustBeEnoughForShipment").''; diff --git a/htdocs/admin/webhook.php b/htdocs/admin/webhook.php index 9dec7a8eeec..4527df95d89 100644 --- a/htdocs/admin/webhook.php +++ b/htdocs/admin/webhook.php @@ -343,7 +343,7 @@ if ($action == 'edit') { include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; print dolJSToSetRandomPassword($constname, 'generate_token'.$constname); } elseif ($val['type'] == 'product') { - if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { + if (isModEnabled("product") || !empty($conf->service->enabled)) { $selected = (empty($conf->global->$constname) ? '' : $conf->global->$constname); $form->select_produits($selected, $constname, '', 0); } diff --git a/htdocs/admin/workflow.php b/htdocs/admin/workflow.php index 47e6e87a244..6540cd4e0fa 100644 --- a/htdocs/admin/workflow.php +++ b/htdocs/admin/workflow.php @@ -62,7 +62,7 @@ $workflowcodes = array( 'WORKFLOW_PROPAL_AUTOCREATE_ORDER'=>array( 'family'=>'create', 'position'=>10, - 'enabled'=>(!empty($conf->propal->enabled) && !empty($conf->commande->enabled)), + 'enabled'=>(isModEnabled("propal") && !empty($conf->commande->enabled)), 'picto'=>'order' ), 'WORKFLOW_ORDER_AUTOCREATE_INVOICE'=>array( @@ -84,14 +84,14 @@ $workflowcodes = array( 'WORKFLOW_ORDER_CLASSIFY_BILLED_PROPAL'=>array( 'family'=>'classify_proposal', 'position'=>30, - 'enabled'=>(!empty($conf->propal->enabled) && !empty($conf->commande->enabled)), + 'enabled'=>(isModEnabled("propal") && !empty($conf->commande->enabled)), 'picto'=>'propal', 'warning'=>'' ), 'WORKFLOW_INVOICE_CLASSIFY_BILLED_PROPAL'=>array( 'family'=>'classify_proposal', 'position'=>31, - 'enabled'=>(!empty($conf->propal->enabled) && isModEnabled('facture')), + 'enabled'=>(isModEnabled("propal") && isModEnabled('facture')), 'picto'=>'propal', 'warning'=>'' ), @@ -100,13 +100,13 @@ $workflowcodes = array( 'WORKFLOW_ORDER_CLASSIFY_SHIPPED_SHIPPING'=>array( // when shipping validated 'family'=>'classify_order', 'position'=>40, - 'enabled'=>(!empty($conf->expedition->enabled) && !empty($conf->commande->enabled)), + 'enabled'=>(isModEnabled("expedition") && !empty($conf->commande->enabled)), 'picto'=>'order' ), 'WORKFLOW_ORDER_CLASSIFY_SHIPPED_SHIPPING_CLOSED'=>array( // when shipping closed 'family'=>'classify_order', 'position'=>41, - 'enabled'=>(!empty($conf->expedition->enabled) && !empty($conf->commande->enabled)), + 'enabled'=>(isModEnabled("expedition") && !empty($conf->commande->enabled)), 'picto'=>'order' ), 'WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_ORDER'=>array( @@ -132,7 +132,7 @@ $workflowcodes = array( 'WORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION'=>array( 'family'=>'classify_supplier_order', 'position'=>63, - 'enabled'=>(!empty($conf->global->MAIN_FEATURES_LEVEL) && (!empty($conf->reception->enabled)) && ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || empty($conf->supplier_order->enabled))), + 'enabled'=>(!empty($conf->global->MAIN_FEATURES_LEVEL) && (isModEnabled("reception")) && ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || empty($conf->supplier_order->enabled))), 'picto'=>'supplier_order', 'warning'=>'' ), @@ -140,7 +140,7 @@ $workflowcodes = array( 'WORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED'=>array( 'family'=>'classify_supplier_order', 'position'=>64, - 'enabled'=>(!empty($conf->global->MAIN_FEATURES_LEVEL) && (!empty($conf->reception->enabled)) && ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || empty($conf->supplier_order->enabled))), + 'enabled'=>(!empty($conf->global->MAIN_FEATURES_LEVEL) && (isModEnabled("reception")) && ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || empty($conf->supplier_order->enabled))), 'picto'=>'supplier_order', 'warning'=>'' ), @@ -157,7 +157,7 @@ $workflowcodes = array( 'WORKFLOW_BILL_ON_RECEPTION'=>array( 'family'=>'classify_reception', 'position'=>80, - 'enabled'=>(!empty($conf->reception->enabled) && ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled))), + 'enabled'=>(isModEnabled("reception") && ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled))), 'picto'=>'reception' ), @@ -165,7 +165,7 @@ $workflowcodes = array( 'WORKFLOW_SHIPPING_CLASSIFY_CLOSED_INVOICE' => array( 'family' => 'classify_shipping', 'position' => 90, - 'enabled' => !empty($conf->expedition->enabled) && !empty($conf->facture->enabled), + 'enabled' => isModEnabled("expedition") && isModEnabled("facture"), 'picto' => 'shipment' ), diff --git a/htdocs/asset/admin/setup.php b/htdocs/asset/admin/setup.php index 448473003b3..64025c9b18a 100644 --- a/htdocs/asset/admin/setup.php +++ b/htdocs/asset/admin/setup.php @@ -524,7 +524,7 @@ if ($action == 'edit') { include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; print dolJSToSetRandomPassword($constname, 'generate_token'.$constname); } elseif ($val['type'] == 'product') { - if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { + if (isModEnabled("product") || !empty($conf->service->enabled)) { $selected = (empty($conf->global->$constname) ? '' : $conf->global->$constname); $form->select_produits($selected, $constname, '', 0); } diff --git a/htdocs/blockedlog/class/blockedlog.class.php b/htdocs/blockedlog/class/blockedlog.class.php index 37db04868cb..d5b668d6c1a 100644 --- a/htdocs/blockedlog/class/blockedlog.class.php +++ b/htdocs/blockedlog/class/blockedlog.class.php @@ -184,7 +184,7 @@ class BlockedLog $this->trackedevents['MEMBER_SUBSCRIPTION_MODIFY'] = 'logMEMBER_SUBSCRIPTION_MODIFY'; $this->trackedevents['MEMBER_SUBSCRIPTION_DELETE'] = 'logMEMBER_SUBSCRIPTION_DELETE'; } - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $this->trackedevents['PAYMENT_VARIOUS_CREATE'] = 'logPAYMENT_VARIOUS_CREATE'; $this->trackedevents['PAYMENT_VARIOUS_MODIFY'] = 'logPAYMENT_VARIOUS_MODIFY'; $this->trackedevents['PAYMENT_VARIOUS_DELETE'] = 'logPAYMENT_VARIOUS_DELETE'; diff --git a/htdocs/bom/tpl/objectline_create.tpl.php b/htdocs/bom/tpl/objectline_create.tpl.php index 0a3a3b34e7a..cd29623af8c 100644 --- a/htdocs/bom/tpl/objectline_create.tpl.php +++ b/htdocs/bom/tpl/objectline_create.tpl.php @@ -87,7 +87,7 @@ $coldisplay++; print ''; // Predefined product/service -if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { +if (isModEnabled("product") || !empty($conf->service->enabled)) { if (!empty($conf->global->BOM_SUB_BOM)) { print $langs->trans("Product"); } diff --git a/htdocs/comm/action/card.php b/htdocs/comm/action/card.php index 6dd6cd5663b..f44fd104067 100644 --- a/htdocs/comm/action/card.php +++ b/htdocs/comm/action/card.php @@ -1378,7 +1378,7 @@ if ($action == 'create') { print ''; - if (!empty($conf->societe->enabled)) { + if (isModEnabled("societe")) { // Related company print '
'.$langs->trans("ActionOnCompany").''; if (GETPOST('socid', 'int') > 0) { @@ -1891,7 +1891,7 @@ if ($id > 0) { print ''; - if (!empty($conf->societe->enabled)) { + if (isModEnabled("societe")) { // Related company print ''; print '
'.$langs->trans("ActionOnCompany").''; @@ -2300,7 +2300,7 @@ if ($id > 0) { print '
'; print ''; - if (!empty($conf->societe->enabled)) { + if (isModEnabled("societe")) { // Related company print '"; print ''; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { // Compte bancaire par défaut print '
'.$langs->trans("ActionOnCompany").''.($object->thirdparty->id ? $object->thirdparty->getNomUrl(1) : (''.$langs->trans("None").'')); if (is_object($object->thirdparty) && $object->thirdparty->id > 0 && $object->type_code == 'AC_TEL') { diff --git a/htdocs/comm/action/class/api_agendaevents.class.php b/htdocs/comm/action/class/api_agendaevents.class.php index 2d868e9bfaa..e7745f1d5fd 100644 --- a/htdocs/comm/action/class/api_agendaevents.class.php +++ b/htdocs/comm/action/class/api_agendaevents.class.php @@ -129,19 +129,19 @@ class AgendaEvents extends DolibarrApi } $sql = "SELECT t.id as rowid"; - if (!empty($conf->societe->enabled)) { + if (isModEnabled("societe")) { if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) } } $sql .= " FROM ".MAIN_DB_PREFIX."actioncomm as t"; - if (!empty($conf->societe->enabled)) { + if (isModEnabled("societe")) { if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale } } $sql .= ' WHERE t.entity IN ('.getEntity('agenda').')'; - if (!empty($conf->societe->enabled)) { + if (isModEnabled("societe")) { if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { $sql .= " AND t.fk_soc = sc.fk_soc"; } diff --git a/htdocs/comm/action/class/cactioncomm.class.php b/htdocs/comm/action/class/cactioncomm.class.php index 75cbefec3ec..f6586a853d2 100644 --- a/htdocs/comm/action/class/cactioncomm.class.php +++ b/htdocs/comm/action/class/cactioncomm.class.php @@ -204,7 +204,7 @@ class CActionComm if ($obj->module == 'order' && !empty($conf->commande->enabled) && empty($user->rights->commande->lire)) { $qualified = 1; } - if ($obj->module == 'propal' && !empty($conf->propal->enabled) && !empty($user->rights->propale->lire)) { + if ($obj->module == 'propal' && isModEnabled("propal") && !empty($user->rights->propale->lire)) { $qualified = 1; } if ($obj->module == 'invoice_supplier' && ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && !empty($user->rights->fournisseur->facture->lire)) || (!empty($conf->rights->supplier_invoice->enabled) && !empty($user->rights->supplier_invoice->lire)))) { @@ -213,7 +213,7 @@ class CActionComm if ($obj->module == 'order_supplier' && ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && !empty($user->rights->fournisseur->commande->lire)) || (empty($conf->rights->supplier_order->enabled) && !empty($user->rights->supplier_order->lire)))) { $qualified = 1; } - if ($obj->module == 'shipping' && !empty($conf->expedition->enabled) && !empty($user->rights->expedition->lire)) { + if ($obj->module == 'shipping' && isModEnabled("expedition") && !empty($user->rights->expedition->lire)) { $qualified = 1; } // For case module = 'myobject@eventorganization' diff --git a/htdocs/comm/card.php b/htdocs/comm/card.php index 173ee8a6510..ec8ebdd67e6 100644 --- a/htdocs/comm/card.php +++ b/htdocs/comm/card.php @@ -44,13 +44,13 @@ if (isModEnabled('facture')) { require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture-rec.class.php'; } -if (!empty($conf->propal->enabled)) { +if (isModEnabled("propal")) { require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php'; } if (!empty($conf->commande->enabled)) { require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; } -if (!empty($conf->expedition->enabled)) { +if (isModEnabled("expedition")) { require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php'; } if (!empty($conf->contrat->enabled)) { @@ -72,7 +72,7 @@ if (!empty($conf->contrat->enabled)) { if (!empty($conf->commande->enabled)) { $langs->load("orders"); } -if (!empty($conf->expedition->enabled)) { +if (isModEnabled("expedition")) { $langs->load("sendings"); } if (isModEnabled('facture')) { @@ -438,7 +438,7 @@ if ($object->id > 0) { print "
'; print '
'; @@ -697,7 +697,7 @@ if ($object->id > 0) { $boxstat .= ''; $boxstat .= ''; // Bank Account - if (!empty($conf->global->BANK_ASK_PAYMENT_BANK_DURING_PROPOSAL) && !empty($conf->banque->enabled)) { + if (!empty($conf->global->BANK_ASK_PAYMENT_BANK_DURING_PROPOSAL) && isModEnabled("banque")) { print ''; @@ -1773,7 +1773,7 @@ if ($action == 'create') { print ''; // Shipping Method - if (!empty($conf->expedition->enabled)) { + if (isModEnabled("expedition")) { if (!empty($conf->global->SOCIETE_ASK_FOR_SHIPPING_METHOD) && !empty($soc->shipping_method_id)) { $shipping_method_id = $soc->shipping_method_id; } @@ -2434,7 +2434,7 @@ if ($action == 'create') { print ''; // Shipping Method - if (!empty($conf->expedition->enabled)) { + if (isModEnabled("expedition")) { print '
'; - if (!empty($conf->propal->enabled) && $user->rights->propal->lire) { + if (isModEnabled("propal") && $user->rights->propal->lire) { // Box proposals $tmp = $object->getOutstandingProposals(); $outstandingOpened = $tmp['opened']; @@ -818,7 +818,7 @@ if ($object->id > 0) { /* * Latest proposals */ - if (!empty($conf->propal->enabled) && $user->rights->propal->lire) { + if (isModEnabled("propal") && $user->rights->propal->lire) { $langs->load("propal"); $sql = "SELECT s.nom, s.rowid, p.rowid as propalid, p.fk_statut, p.total_ht"; @@ -1024,7 +1024,7 @@ if ($object->id > 0) { /* * Latest shipments */ - if (!empty($conf->expedition->enabled) && $user->rights->expedition->lire) { + if (isModEnabled("expedition") && $user->rights->expedition->lire) { $sql = 'SELECT e.rowid as id'; $sql .= ', e.ref, e.entity'; $sql .= ', e.date_creation'; @@ -1548,7 +1548,7 @@ if ($object->id > 0) { print ''; } - if (!empty($conf->propal->enabled) && $user->rights->propal->creer && $object->status == 1) { + if (isModEnabled("propal") && $user->rights->propal->creer && $object->status == 1) { $langs->load("propal"); print ''; } diff --git a/htdocs/comm/index.php b/htdocs/comm/index.php index 7127fd2dd5b..83766254f28 100644 --- a/htdocs/comm/index.php +++ b/htdocs/comm/index.php @@ -90,7 +90,7 @@ $maxofloop = (empty($conf->global->MAIN_MAXLIST_OVERLOAD) ? 500 : $conf->global- $form = new Form($db); $formfile = new FormFile($db); $companystatic = new Societe($db); -if (!empty($conf->propal->enabled)) { +if (isModEnabled("propal")) { $propalstatic = new Propal($db); } if (!empty($conf->supplier_proposal->enabled)) { @@ -128,7 +128,7 @@ if ($tmp) { * Draft customer proposals */ -if (!empty($conf->propal->enabled) && $user->rights->propal->lire) { +if (isModEnabled("propal") && $user->rights->propal->lire) { $sql = "SELECT p.rowid, p.ref, p.ref_client, p.total_ht, p.total_tva, p.total_ttc, p.fk_statut as status"; $sql .= ", s.rowid as socid, s.nom as name, s.name_alias"; $sql .= ", s.code_client, s.code_compta, s.client"; @@ -592,7 +592,7 @@ print '
'; /* * Last modified customers or prospects */ -if (!empty($conf->societe->enabled) && $user->rights->societe->lire) { +if (isModEnabled("societe") && $user->rights->societe->lire) { $sql = "SELECT s.rowid as socid, s.nom as name, s.name_alias"; $sql .= ", s.code_client, s.code_compta, s.client"; $sql .= ", s.code_fournisseur, s.code_compta_fournisseur, s.fournisseur"; @@ -887,7 +887,7 @@ if (!empty($conf->contrat->enabled) && $user->rights->contrat->lire && 0) { // T /* * Opened (validated) proposals */ -if (!empty($conf->propal->enabled) && $user->rights->propal->lire) { +if (isModEnabled("propal") && $user->rights->propal->lire) { $sql = "SELECT p.rowid as propalid, p.entity, p.total_ttc, p.total_ht, p.total_tva, p.ref, p.ref_client, p.fk_statut, p.datep as dp, p.fin_validite as dfv"; $sql .= ", s.rowid as socid, s.nom as name, s.name_alias"; $sql .= ", s.code_client, s.code_compta, s.client"; diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index f4e1866613e..c88ffdad6eb 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -1750,7 +1750,7 @@ if ($action == 'create') { print '
'; print ''; } - if (!empty($conf->global->BANK_ASK_PAYMENT_BANK_DURING_PROPOSAL) && !empty($conf->banque->enabled)) { + if (!empty($conf->global->BANK_ASK_PAYMENT_BANK_DURING_PROPOSAL) && isModEnabled("banque")) { // Bank Account print '
'; print $langs->trans('SendingMethod'); @@ -2552,7 +2552,7 @@ if ($action == 'create') { print '
'; print ''; // Bank Account - if (!empty($conf->global->BANK_ASK_PAYMENT_BANK_DURING_ORDER) && !empty($conf->banque->enabled)) { + if (!empty($conf->global->BANK_ASK_PAYMENT_BANK_DURING_ORDER) && isModEnabled("banque")) { print ''; @@ -2581,7 +2581,7 @@ if ($action == 'create' && $usercancreate) { } // Bank Account - if (!empty($conf->global->BANK_ASK_PAYMENT_BANK_DURING_ORDER) && !empty($conf->banque->enabled)) { + if (!empty($conf->global->BANK_ASK_PAYMENT_BANK_DURING_ORDER) && isModEnabled("banque")) { print ''; // Bank - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print ''; // Number - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print ''; @@ -642,7 +642,7 @@ if ($id) { print $form->editfieldval('SubledgerAccount', 'subledger_account', $object->subledger_account, $object, (!$alreadyaccounted && $user->rights->banque->modifier), 'string', '', 0); print ''; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { if ($object->fk_account > 0) { $bankline = new AccountLine($db); $bankline->fetch($object->fk_bank); diff --git a/htdocs/compta/bank/various_payment/list.php b/htdocs/compta/bank/various_payment/list.php index fdebf7f795c..aa65ac8d2a3 100644 --- a/htdocs/compta/bank/various_payment/list.php +++ b/htdocs/compta/bank/various_payment/list.php @@ -152,8 +152,8 @@ $arrayfields = array( 'datev' =>array('label'=>"DateValue", 'checked'=>-1, 'position'=>130), 'type' =>array('label'=>"PaymentMode", 'checked'=>1, 'position'=>140), 'project' =>array('label'=>"Project", 'checked'=>1, 'position'=>200, "enabled"=>!empty($conf->project->enabled)), - 'bank' =>array('label'=>"BankAccount", 'checked'=>1, 'position'=>300, "enabled"=>!empty($conf->banque->enabled)), - 'entry' =>array('label'=>"BankTransactionLine", 'checked'=>1, 'position'=>310, "enabled"=>!empty($conf->banque->enabled)), + 'bank' =>array('label'=>"BankAccount", 'checked'=>1, 'position'=>300, "enabled"=>isModEnabled("banque")), + 'entry' =>array('label'=>"BankTransactionLine", 'checked'=>1, 'position'=>310, "enabled"=>isModEnabled("banque")), 'account' =>array('label'=>"AccountAccountingShort", 'checked'=>1, 'position'=>400, "enabled"=>!empty($conf->accounting->enabled)), 'subledger' =>array('label'=>"SubledgerAccount", 'checked'=>1, 'position'=>410, "enabled"=>!empty($conf->accounting->enabled)), 'debit' =>array('label'=>"Debit", 'checked'=>1, 'position'=>500), diff --git a/htdocs/compta/charges/index.php b/htdocs/compta/charges/index.php index 169666477f4..a80916cdc0d 100644 --- a/htdocs/compta/charges/index.php +++ b/htdocs/compta/charges/index.php @@ -146,7 +146,7 @@ if (!empty($conf->tax->enabled) && $user->rights->tax->charges->lire) { print_liste_field_titre("RefPayment", $_SERVER["PHP_SELF"], "pc.rowid", "", $param, '', $sortfield, $sortorder); print_liste_field_titre("DatePayment", $_SERVER["PHP_SELF"], "pc.datep", "", $param, 'align="center"', $sortfield, $sortorder); print_liste_field_titre("Type", $_SERVER["PHP_SELF"], "pct.code", "", $param, '', $sortfield, $sortorder); - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print_liste_field_titre("Account", $_SERVER["PHP_SELF"], "ba.label", "", $param, "", $sortfield, $sortorder); } print_liste_field_titre("PayedByThisPayment", $_SERVER["PHP_SELF"], "pc.amount", "", $param, 'class="right"', $sortfield, $sortorder); @@ -220,7 +220,7 @@ if (!empty($conf->tax->enabled) && $user->rights->tax->charges->lire) { } print $obj->num_payment.''; // Account - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print ''; print ''; print ''; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print ''; } print '"; @@ -304,7 +304,7 @@ if (!empty($conf->tax->enabled) && $user->rights->tax->charges->lire) { print_liste_field_titre("RefPayment", $_SERVER["PHP_SELF"], "ptva.rowid", "", $param, '', $sortfield, $sortorder); print_liste_field_titre("DatePayment", $_SERVER["PHP_SELF"], "ptva.datep", "", $param, 'align="center"', $sortfield, $sortorder); print_liste_field_titre("Type", $_SERVER["PHP_SELF"], "pct.code", "", $param, '', $sortfield, $sortorder); - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print_liste_field_titre("Account", $_SERVER["PHP_SELF"], "ba.label", "", $param, "", $sortfield, $sortorder); } print_liste_field_titre("PayedByThisPayment", $_SERVER["PHP_SELF"], "ptva.amount", "", $param, 'class="right"', $sortfield, $sortorder); @@ -341,7 +341,7 @@ if (!empty($conf->tax->enabled) && $user->rights->tax->charges->lire) { print $obj->num_payment.''; // Account - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print ''; // Bank Account - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print '
'; diff --git a/htdocs/comm/propal/index.php b/htdocs/comm/propal/index.php index 9f020bc1613..c03cdf4fdcc 100644 --- a/htdocs/comm/propal/index.php +++ b/htdocs/comm/propal/index.php @@ -76,7 +76,7 @@ if ($tmp) { /* * Draft proposals */ -if (!empty($conf->propal->enabled)) { +if (isModEnabled("propal")) { $sql = "SELECT p.rowid, p.ref, p.ref_client, p.total_ht, p.total_tva, p.total_ttc"; $sql .= ", s.rowid as socid, s.nom as name, s.client, s.canvas, s.code_client, s.email, s.entity, s.code_compta"; $sql .= " FROM ".MAIN_DB_PREFIX."propal as p"; @@ -226,7 +226,7 @@ if ($resql) { /* * Open (validated) proposals */ -if (!empty($conf->propal->enabled) && $user->rights->propale->lire) { +if (isModEnabled("propal") && $user->rights->propale->lire) { $sql = "SELECT s.nom as socname, s.rowid as socid, s.canvas, s.client, s.email, s.code_compta"; $sql .= ", p.rowid as propalid, p.entity, p.total_ttc, p.total_ht, p.ref, p.fk_statut, p.datep as dp, p.fin_validite as dfv"; $sql .= " FROM ".MAIN_DB_PREFIX."societe as s"; diff --git a/htdocs/comm/propal/list.php b/htdocs/comm/propal/list.php index 9012b105b55..6b717d3ea6f 100644 --- a/htdocs/comm/propal/list.php +++ b/htdocs/comm/propal/list.php @@ -52,7 +52,7 @@ require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; // Load translation files required by the page $langs->loadLangs(array('companies', 'propal', 'compta', 'bills', 'orders', 'products', 'deliveries', 'categories')); -if (!empty($conf->expedition->enabled)) { +if (isModEnabled("expedition")) { $langs->loadLangs(array('sendings')); } @@ -218,7 +218,7 @@ $arrayfields = array( 'p.date_livraison'=>array('label'=>"DeliveryDate", 'checked'=>0), 'p.date_signature'=>array('label'=>"DateSigning", 'checked'=>0), 'ava.rowid'=>array('label'=>"AvailabilityPeriod", 'checked'=>0), - 'p.fk_shipping_method'=>array('label'=>"SendingMethod", 'checked'=>0, 'enabled'=>!empty($conf->expedition->enabled)), + 'p.fk_shipping_method'=>array('label'=>"SendingMethod", 'checked'=>0, 'enabled'=>isModEnabled("expedition")), 'p.fk_input_reason'=>array('label'=>"Origin", 'checked'=>0, 'enabled'=>1), 'p.fk_cond_reglement'=>array('label'=>"PaymentConditionsShort", 'checked'=>0), 'p.fk_mode_reglement'=>array('label'=>"PaymentMode", 'checked'=>0), diff --git a/htdocs/comm/prospect/index.php b/htdocs/comm/prospect/index.php index e63aee6f240..bda09507ed0 100644 --- a/htdocs/comm/prospect/index.php +++ b/htdocs/comm/prospect/index.php @@ -59,7 +59,7 @@ print load_fiche_titre($langs->trans("ProspectionArea")); print '
'; -if (!empty($conf->propal->enabled)) { +if (isModEnabled("propal")) { $var = false; print '
'; print ''; @@ -118,7 +118,7 @@ if ($resql) { /* * Liste des propal brouillons */ -if (!empty($conf->propal->enabled) && $user->rights->propale->lire) { +if (isModEnabled("propal") && $user->rights->propale->lire) { $sql = "SELECT p.rowid, p.ref, p.price, s.nom as sname"; $sql .= " FROM ".MAIN_DB_PREFIX."propal as p"; $sql .= ", ".MAIN_DB_PREFIX."societe as s"; @@ -176,7 +176,7 @@ if (isModEnabled('agenda')) { /* * Dernieres propales ouvertes */ -if (!empty($conf->propal->enabled) && $user->rights->propale->lire) { +if (isModEnabled("propal") && $user->rights->propale->lire) { $sql = "SELECT s.nom as name, s.rowid as socid, s.client, s.canvas,"; $sql .= " p.rowid as propalid, p.total_ttc, p.ref, p.datep as dp, c.label as statut, c.id as statutid"; $sql .= " FROM ".MAIN_DB_PREFIX."societe as s"; diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 12e29ac9b2b..2cdb14779ba 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -45,7 +45,7 @@ require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/order.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; -if (!empty($conf->propal->enabled)) { +if (isModEnabled("propal")) { require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php'; } if (!empty($conf->project->enabled)) { @@ -1783,7 +1783,7 @@ if ($action == 'create' && $usercancreate) { print '
'.$langs->trans('BankAccount').''; print img_picto('', 'bank_account', 'class="pictofixedwidth"').$form->select_comptes($fk_account, 'fk_account', 0, '', 1, '', 0, 'maxwidth200 widthcentpercentminusx', 1); print '
'; $editenable = $usercancreate; print $form->editfieldkey("BankAccount", 'bankaccount', '', $object, $editenable); diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index 9a93e8a5047..9a9f1d78df0 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -3710,7 +3710,7 @@ class Commande extends CommonOrder $result = ''; - if (!empty($conf->expedition->enabled) && ($option == '1' || $option == '2')) { + if (isModEnabled("expedition") && ($option == '1' || $option == '2')) { $url = DOL_URL_ROOT.'/expedition/shipment.php?id='.$this->id; } else { $url = DOL_URL_ROOT.'/commande/card.php?id='.$this->id; diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index dbb99d0f993..4a7216e30d8 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -176,7 +176,7 @@ $arrayfields = array( 'typent.code'=>array('label'=>"ThirdPartyType", 'checked'=>$checkedtypetiers, 'position'=>55), 'c.date_commande'=>array('label'=>"OrderDateShort", 'checked'=>1, 'position'=>60), 'c.date_delivery'=>array('label'=>"DateDeliveryPlanned", 'checked'=>1, 'enabled'=>empty($conf->global->ORDER_DISABLE_DELIVERY_DATE), 'position'=>65), - 'c.fk_shipping_method'=>array('label'=>"SendingMethod", 'checked'=>-1, 'position'=>66 , 'enabled'=>!empty($conf->expedition->enabled)), + 'c.fk_shipping_method'=>array('label'=>"SendingMethod", 'checked'=>-1, 'position'=>66 , 'enabled'=>isModEnabled("expedition")), 'c.fk_cond_reglement'=>array('label'=>"PaymentConditionsShort", 'checked'=>-1, 'position'=>67), 'c.fk_mode_reglement'=>array('label'=>"PaymentMode", 'checked'=>-1, 'position'=>68), 'c.fk_input_reason'=>array('label'=>"Channel", 'checked'=>-1, 'position'=>69), @@ -199,7 +199,7 @@ $arrayfields = array( 'c.date_cloture'=>array('label'=>"DateClosing", 'checked'=>0, 'position'=>130), 'c.note_public'=>array('label'=>'NotePublic', 'checked'=>0, 'enabled'=>(empty($conf->global->MAIN_LIST_ALLOW_PUBLIC_NOTES)), 'position'=>135), 'c.note_private'=>array('label'=>'NotePrivate', 'checked'=>0, 'enabled'=>(empty($conf->global->MAIN_LIST_ALLOW_PRIVATE_NOTES)), 'position'=>140), - 'shippable'=>array('label'=>"Shippable", 'checked'=>1,'enabled'=>(!empty($conf->expedition->enabled)), 'position'=>990), + 'shippable'=>array('label'=>"Shippable", 'checked'=>1,'enabled'=>(isModEnabled("expedition")), 'position'=>990), 'c.facture'=>array('label'=>"Billed", 'checked'=>1, 'enabled'=>(empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT)), 'position'=>995), 'c.import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'position'=>999), 'c.fk_statut'=>array('label'=>"Status", 'checked'=>1, 'position'=>1000) diff --git a/htdocs/compta/accounting-files.php b/htdocs/compta/accounting-files.php index ab8175c4d38..a3cb900befb 100644 --- a/htdocs/compta/accounting-files.php +++ b/htdocs/compta/accounting-files.php @@ -139,7 +139,7 @@ $listofchoices = array( 'selectdonations'=>array('label'=>'Donations', 'lang'=>'donation', 'enabled' => !empty($conf->don->enabled), 'perms' => !empty($user->rights->don->lire)), 'selectsocialcontributions'=>array('label'=>'SocialContributions', 'enabled' => !empty($conf->tax->enabled), 'perms' => !empty($user->rights->tax->charges->lire)), 'selectpaymentsofsalaries'=>array('label'=>'SalariesPayments', 'lang'=>'salaries', 'enabled' => !empty($conf->salaries->enabled), 'perms' => !empty($user->rights->salaries->read)), - 'selectvariouspayment'=>array('label'=>'VariousPayment', 'enabled' => !empty($conf->banque->enabled), 'perms' => !empty($user->rights->banque->lire)), + 'selectvariouspayment'=>array('label'=>'VariousPayment', 'enabled' => isModEnabled("banque"), 'perms' => !empty($user->rights->banque->lire)), 'selectloanspayment'=>array('label'=>'PaymentLoan', 'enabled' => !empty($conf->loan->enabled), 'perms' => !empty($user->rights->loan->read)), ); diff --git a/htdocs/compta/bank/class/paymentvarious.class.php b/htdocs/compta/bank/class/paymentvarious.class.php index 48ea553abf0..3d07c280559 100644 --- a/htdocs/compta/bank/class/paymentvarious.class.php +++ b/htdocs/compta/bank/class/paymentvarious.class.php @@ -423,11 +423,11 @@ class PaymentVarious extends CommonObject $this->error = $langs->trans("ErrorFieldRequired", $langs->transnoentities("Amount")); return -5; } - if (!empty($conf->banque->enabled) && (empty($this->fk_account) || $this->fk_account <= 0)) { + if (isModEnabled("banque") && (empty($this->fk_account) || $this->fk_account <= 0)) { $this->error = $langs->trans("ErrorFieldRequired", $langs->transnoentities("BankAccount")); return -6; } - if (!empty($conf->banque->enabled) && (empty($this->type_payment) || $this->type_payment <= 0)) { + if (isModEnabled("banque") && (empty($this->type_payment) || $this->type_payment <= 0)) { $this->error = $langs->trans("ErrorFieldRequired", $langs->transnoentities("PaymentMode")); return -7; } @@ -481,7 +481,7 @@ class PaymentVarious extends CommonObject $this->ref = $this->id; if ($this->id > 0) { - if (!empty($conf->banque->enabled) && !empty($this->amount)) { + if (isModEnabled("banque") && !empty($this->amount)) { // Insert into llx_bank require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; diff --git a/htdocs/compta/bank/various_payment/card.php b/htdocs/compta/bank/various_payment/card.php index cbcb2fd5417..23621157e5a 100644 --- a/htdocs/compta/bank/various_payment/card.php +++ b/htdocs/compta/bank/various_payment/card.php @@ -139,7 +139,7 @@ if (empty($reshook)) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Amount")), null, 'errors'); $error++; } - if (!empty($conf->banque->enabled) && !$object->accountid > 0) { + if (isModEnabled("banque") && !$object->accountid > 0) { $langs->load('errors'); setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("BankAccount")), null, 'errors'); $error++; @@ -413,7 +413,7 @@ if ($action == 'create') { print '
'; print $form->editfieldkey('BankAccount', 'selectaccountid', '', $object, 0, 'string', '', 1).''; print img_picto('', 'bank_account', 'class="pictofixedwidth"'); @@ -428,7 +428,7 @@ if ($action == 'create') { print '
'; if ($obj->fk_bank > 0) { //$accountstatic->fetch($obj->fk_bank); @@ -254,7 +254,7 @@ if (!empty($conf->tax->enabled) && $user->rights->tax->charges->lire) { print '   '.price($totalpaid)."'; if ($obj->fk_bank > 0) { //$accountstatic->fetch($obj->fk_bank); diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index ffa8b97b7bd..d505f3dd718 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -3688,7 +3688,7 @@ if ($action == 'create') { print '
'.$langs->trans('BankAccount').''; print img_picto('', 'bank_account', 'class="pictofixedwidth"'); print $form->select_comptes(($fk_account < 0 ? '' : $fk_account), 'fk_account', 0, '', 1, '', 0, 'maxwidth200 widthcentpercentminusx', 1); @@ -4588,7 +4588,7 @@ if ($action == 'create') { } // Bank Account - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print '
'; print ''; print ''; print ''; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print ''; } print ''; @@ -4897,7 +4897,7 @@ if ($action == 'create') { print ''; print ''; print ''; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print ''; } print ''; @@ -4917,7 +4917,7 @@ if ($action == 'create') { print ''; print ''; print ''; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print ''; } print ''; @@ -4940,7 +4940,7 @@ if ($action == 'create') { $i++; } print ''; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print ''; } print ''; @@ -4972,7 +4972,7 @@ if ($action == 'create') { print ''; print ''; print ''; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print ''; } print ''; @@ -4986,7 +4986,7 @@ if ($action == 'create') { print ''; print ''; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print ''; } print ''; @@ -5013,7 +5013,7 @@ if ($action == 'create') { print ''; print ''; print ''; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print ''; } print ''; @@ -5062,7 +5062,7 @@ if ($action == 'create') { print ''; $label = ($langs->trans("PaymentType".$objp->payment_code) != ("PaymentType".$objp->payment_code)) ? $langs->trans("PaymentType".$objp->payment_code) : $objp->payment_label; print ''; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $bankaccountstatic->id = $objp->baid; $bankaccountstatic->ref = $objp->baref; $bankaccountstatic->label = $objp->baref; diff --git a/htdocs/compta/facture/class/api_invoices.class.php b/htdocs/compta/facture/class/api_invoices.class.php index 285d9d366f7..51c094d898e 100644 --- a/htdocs/compta/facture/class/api_invoices.class.php +++ b/htdocs/compta/facture/class/api_invoices.class.php @@ -1410,7 +1410,7 @@ class Invoices extends DolibarrApi throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { if (empty($accountid)) { throw new RestException(400, 'Account ID is mandatory'); } @@ -1469,7 +1469,7 @@ class Invoices extends DolibarrApi throw new RestException(400, 'Payment error : '.$paymentobj->error); } - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $label = '(CustomerInvoicePayment)'; if ($paymentobj->paiementcode == 'CHQ' && empty($chqemetteur)) { @@ -1533,7 +1533,7 @@ class Invoices extends DolibarrApi } } - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { if (empty($accountid)) { throw new RestException(400, 'Account ID is mandatory'); } @@ -1617,7 +1617,7 @@ class Invoices extends DolibarrApi $this->db->rollback(); throw new RestException(400, 'Payment error : '.$paymentobj->error); } - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $label = '(CustomerInvoicePayment)'; if ($paymentobj->paiementcode == 'CHQ' && empty($chqemetteur)) { throw new RestException(400, 'Emetteur is mandatory when payment code is '.$paymentobj->paiementcode); diff --git a/htdocs/compta/localtax/card.php b/htdocs/compta/localtax/card.php index 9bd37eafa36..84f40f5cd19 100644 --- a/htdocs/compta/localtax/card.php +++ b/htdocs/compta/localtax/card.php @@ -174,7 +174,7 @@ if ($action == 'create') { // Amount print ''; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { // Type payment print ''; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { if ($object->fk_account > 0) { $bankline = new AccountLine($db); $bankline->fetch($object->fk_bank); diff --git a/htdocs/compta/localtax/class/localtax.class.php b/htdocs/compta/localtax/class/localtax.class.php index 63b4f982316..ed467ec91f4 100644 --- a/htdocs/compta/localtax/class/localtax.class.php +++ b/htdocs/compta/localtax/class/localtax.class.php @@ -467,11 +467,11 @@ class Localtax extends CommonObject $this->error = $langs->trans("ErrorFieldRequired", $langs->transnoentities("Amount")); return -4; } - if (!empty($conf->banque->enabled) && (empty($this->accountid) || $this->accountid <= 0)) { + if (isModEnabled("banque") && (empty($this->accountid) || $this->accountid <= 0)) { $this->error = $langs->trans("ErrorFieldRequired", $langs->transnoentities("Account")); return -5; } - if (!empty($conf->banque->enabled) && (empty($this->paymenttype) || $this->paymenttype <= 0)) { + if (isModEnabled("banque") && (empty($this->paymenttype) || $this->paymenttype <= 0)) { $this->error = $langs->trans("ErrorFieldRequired", $langs->transnoentities("PaymentMode")); return -5; } @@ -503,7 +503,7 @@ class Localtax extends CommonObject $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."localtax"); // TODO devrait s'appeler paiementlocaltax if ($this->id > 0) { $ok = 1; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { // Insertion dans llx_bank require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; diff --git a/htdocs/compta/paiement.php b/htdocs/compta/paiement.php index aea9f917dab..5aa41f10405 100644 --- a/htdocs/compta/paiement.php +++ b/htdocs/compta/paiement.php @@ -170,7 +170,7 @@ if (empty($reshook)) { $error++; } - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { // If bank module is on, account is required to enter a payment if (GETPOST('accountid') <= 0) { setEventMessages($langs->transnoentities('ErrorFieldRequired', $langs->transnoentities('AccountToCredit')), null, 'errors'); @@ -244,7 +244,7 @@ if (empty($reshook)) { $multicurrency_code[$key] = $tmpinvoice->multicurrency_code; } - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { // If the bank module is active, an account is required to input a payment if (GETPOST('accountid', 'int') <= 0) { setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentities('AccountToCredit')), null, 'errors'); @@ -492,7 +492,7 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie // Bank account print ''; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { if ($facture->type != 2) { print ''; } diff --git a/htdocs/compta/paiement/card.php b/htdocs/compta/paiement/card.php index bd5c114e983..54b1e0e7bcd 100644 --- a/htdocs/compta/paiement/card.php +++ b/htdocs/compta/paiement/card.php @@ -32,7 +32,7 @@ require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/modules/facture/modules_facture.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php'; -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; } @@ -285,7 +285,7 @@ print ''; */ // Bank account -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { if ($object->fk_account > 0) { if ($object->type_code == 'CHQ' && $bankline->fk_bordereau > 0) { include_once DOL_DOCUMENT_ROOT.'/compta/paiement/cheque/class/remisecheque.class.php'; diff --git a/htdocs/compta/paiement/class/paiement.class.php b/htdocs/compta/paiement/class/paiement.class.php index 25543ed9d82..6f83f9ebc0b 100644 --- a/htdocs/compta/paiement/class/paiement.class.php +++ b/htdocs/compta/paiement/class/paiement.class.php @@ -628,7 +628,7 @@ class Paiement extends CommonObject $error = 0; $bank_line_id = 0; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { if ($accountid <= 0) { $this->error = 'Bad value for parameter accountid='.$accountid; dol_syslog(get_class($this).'::addPaymentToBank '.$this->error, LOG_ERR); diff --git a/htdocs/compta/paiement/list.php b/htdocs/compta/paiement/list.php index 988d6e041be..e6b57137df8 100644 --- a/htdocs/compta/paiement/list.php +++ b/htdocs/compta/paiement/list.php @@ -104,8 +104,8 @@ $arrayfields = array( 'p.datep' => array('label'=>"Date", 'checked'=>1, 'position'=>20), 's.nom' => array('label'=>"ThirdParty", 'checked'=>1, 'position'=>30), 'c.libelle' => array('label'=>"Type", 'checked'=>1, 'position'=>40), - 'transaction' => array('label'=>"BankTransactionLine", 'checked'=>1, 'position'=>50, 'enabled'=>(!empty($conf->banque->enabled))), - 'ba.label' => array('label'=>"Account", 'checked'=>1, 'position'=>60, 'enabled'=>(!empty($conf->banque->enabled))), + 'transaction' => array('label'=>"BankTransactionLine", 'checked'=>1, 'position'=>50, 'enabled'=>(isModEnabled("banque"))), + 'ba.label' => array('label'=>"Account", 'checked'=>1, 'position'=>60, 'enabled'=>(isModEnabled("banque"))), 'p.num_paiement' => array('label'=>"Numero", 'checked'=>1, 'position'=>70, 'tooltip'=>"ChequeOrTransferNumber"), 'p.amount' => array('label'=>"Amount", 'checked'=>1, 'position'=>80), 'p.statut' => array('label'=>"Status", 'checked'=>1, 'position'=>90, 'enabled'=>(!empty($conf->global->BILL_ADD_PAYMENT_VALIDATION))), diff --git a/htdocs/compta/paiement_charge.php b/htdocs/compta/paiement_charge.php index 99940ecffcb..50236a29e64 100644 --- a/htdocs/compta/paiement_charge.php +++ b/htdocs/compta/paiement_charge.php @@ -71,7 +71,7 @@ if ($action == 'add_payment' || ($action == 'confirm_paiement' && $confirm == 'y $error++; $action = 'create'; } - if (!empty($conf->banque->enabled) && !(GETPOST("accountid") > 0)) { + if (isModEnabled("banque") && !(GETPOST("accountid") > 0)) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("AccountToCredit")), null, 'errors'); $error++; $action = 'create'; diff --git a/htdocs/compta/paiement_vat.php b/htdocs/compta/paiement_vat.php index 645fd36bc2a..f1f243bc06d 100644 --- a/htdocs/compta/paiement_vat.php +++ b/htdocs/compta/paiement_vat.php @@ -69,7 +69,7 @@ if ($action == 'add_payment' || ($action == 'confirm_paiement' && $confirm == 'y $error++; $action = 'create'; } - if (!empty($conf->banque->enabled) && !(GETPOST("accountid", 'int') > 0)) { + if (isModEnabled("banque") && !(GETPOST("accountid", 'int') > 0)) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("AccountToDebit")), null, 'errors'); $error++; $action = 'create'; diff --git a/htdocs/compta/payment_sc/card.php b/htdocs/compta/payment_sc/card.php index f5ff5a101f2..f76cc6b27c1 100644 --- a/htdocs/compta/payment_sc/card.php +++ b/htdocs/compta/payment_sc/card.php @@ -31,7 +31,7 @@ require_once DOL_DOCUMENT_ROOT.'/compta/sociales/class/chargesociales.class.php' require_once DOL_DOCUMENT_ROOT.'/compta/sociales/class/paymentsocialcontribution.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/modules/facture/modules_facture.php'; -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; } @@ -141,7 +141,7 @@ print ''; // Bank account -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { if ($object->bank_account) { $bankline = new AccountLine($db); $bankline->fetch($object->bank_line); diff --git a/htdocs/compta/payment_vat/card.php b/htdocs/compta/payment_vat/card.php index 94dd817900e..401752af11b 100644 --- a/htdocs/compta/payment_vat/card.php +++ b/htdocs/compta/payment_vat/card.php @@ -31,7 +31,7 @@ require_once DOL_DOCUMENT_ROOT.'/compta/tva/class/tva.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/tva/class/paymentvat.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/modules/facture/modules_facture.php'; -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; } @@ -194,7 +194,7 @@ print ''; // Bank account -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { if ($object->bank_account) { $bankline = new AccountLine($db); $bankline->fetch($object->bank_line); diff --git a/htdocs/compta/resultat/clientfourn.php b/htdocs/compta/resultat/clientfourn.php index 2be668fac5c..b322fdb3ce2 100644 --- a/htdocs/compta/resultat/clientfourn.php +++ b/htdocs/compta/resultat/clientfourn.php @@ -1127,7 +1127,7 @@ if ($modecompta == 'BOOKKEEPING') { */ //$conf->global->ACCOUNTING_REPORTS_INCLUDE_VARPAY = 1; - if (!empty($conf->global->ACCOUNTING_REPORTS_INCLUDE_VARPAY) && !empty($conf->banque->enabled) && ($modecompta == 'CREANCES-DETTES' || $modecompta == "RECETTES-DEPENSES")) { + if (!empty($conf->global->ACCOUNTING_REPORTS_INCLUDE_VARPAY) && isModEnabled("banque") && ($modecompta == 'CREANCES-DETTES' || $modecompta == "RECETTES-DEPENSES")) { $subtotal_ht = 0; $subtotal_ttc = 0; diff --git a/htdocs/compta/resultat/index.php b/htdocs/compta/resultat/index.php index 719b1deb29a..bc3cc906960 100644 --- a/htdocs/compta/resultat/index.php +++ b/htdocs/compta/resultat/index.php @@ -796,7 +796,7 @@ if (!empty($conf->don->enabled) && ($modecompta == 'CREANCES-DETTES' || $modecom * Various Payments */ -if (!empty($conf->global->ACCOUNTING_REPORTS_INCLUDE_VARPAY) && !empty($conf->banque->enabled) && ($modecompta == 'CREANCES-DETTES' || $modecompta == "RECETTES-DEPENSES")) { +if (!empty($conf->global->ACCOUNTING_REPORTS_INCLUDE_VARPAY) && isModEnabled("banque") && ($modecompta == 'CREANCES-DETTES' || $modecompta == "RECETTES-DEPENSES")) { // decaiss $sql = "SELECT date_format(p.datep, '%Y-%m') AS dm, SUM(p.amount) AS amount FROM ".MAIN_DB_PREFIX."payment_various as p"; diff --git a/htdocs/compta/sociales/card.php b/htdocs/compta/sociales/card.php index 0bb69c444ba..f6bc9b5fa02 100644 --- a/htdocs/compta/sociales/card.php +++ b/htdocs/compta/sociales/card.php @@ -426,7 +426,7 @@ if ($action == 'create') { print ''; // Bank Account - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print ''; @@ -638,7 +638,7 @@ if ($id > 0) { print ''; // Bank account - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print '
'; print $langs->trans('BankAccount'); @@ -4844,7 +4844,7 @@ if ($action == 'create') { if (!empty($conf->project->enabled)) { $nbrows++; } - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $nbrows++; $nbcols++; } @@ -4873,7 +4873,7 @@ if ($action == 'create') { print ''.$langs->trans('ListOfSituationInvoices').''.$langs->trans('Situation').''.$langs->trans('AmountHT').''.$prev_invoice->getNomUrl(1).''.(($prev_invoice->type == Facture::TYPE_CREDIT_NOTE) ? $langs->trans('situationInvoiceShortcode_AS') : $langs->trans('situationInvoiceShortcode_S')).$prev_invoice->situation_counter.''.price($prev_invoice->total_ht).''.$object->getNomUrl(1).''.(($object->type == Facture::TYPE_CREDIT_NOTE) ? $langs->trans('situationInvoiceShortcode_AS') : $langs->trans('situationInvoiceShortcode_S')).$object->situation_counter.''.price($object->total_ht).''.price($total_global_ht).''.$next_invoice->getNomUrl(1).''.(($next_invoice->type == Facture::TYPE_CREDIT_NOTE) ? $langs->trans('situationInvoiceShortcode_AS') : $langs->trans('situationInvoiceShortcode_S')).$next_invoice->situation_counter.''.price($next_invoice->total_ht).'
'.price($total_global_ht).''.($object->type == Facture::TYPE_CREDIT_NOTE ? $langs->trans("PaymentsBack") : $langs->trans('Payments')).''.$langs->trans('Date').''.$langs->trans('Type').''.$langs->trans('BankAccount').''.$langs->trans('Amount').''.$label.' '.$objp->num_payment.'
'.$langs->trans("Amount").'
'.$langs->trans("PaymentMode").''; $form->select_types_paiements(GETPOST("paiementtype"), "paiementtype", '', 0, 1, 0, 0, 1, 'maxwidth500 widthcentpercentminusx'); @@ -243,7 +243,7 @@ if ($id) { print '
'.$langs->trans("Amount").''.price($object->amount).'
'.$langs->trans('AccountToCredit').'
'.$langs->trans('Amount').''.price($object->amount, '', $disable_delete = 0; // Bank account -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { $bankline = new AccountLine($db); if ($object->fk_account > 0) { @@ -327,7 +327,7 @@ print '
'.$langs->trans('Amount').''.price($object-> print '
'.$langs->trans('Note').''.nl2br($object->note).'
'.$langs->trans('Amount').''.price($object-> print '
'.$langs->trans('Note').''.nl2br($object->note).'
'.$langs->trans('DefaultBankAccount').''; print img_picto('', 'bank_account', 'class="pictofixedwidth"').$form->select_comptes(GETPOST('fk_account', 'int'), 'fk_account', 0, '', 2, '', 0, '', 1); print '
'; print ''; print ''; print ''; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print ''; } print ''; @@ -726,7 +726,7 @@ if ($id > 0) { print '\n"; $labeltype = $langs->trans("PaymentType".$objp->type_code) != ("PaymentType".$objp->type_code) ? $langs->trans("PaymentType".$objp->type_code) : $objp->paiement_type; print "\n"; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $bankaccountstatic->id = $objp->baid; $bankaccountstatic->ref = $objp->baref; $bankaccountstatic->label = $objp->baref; diff --git a/htdocs/compta/sociales/class/paymentsocialcontribution.class.php b/htdocs/compta/sociales/class/paymentsocialcontribution.class.php index 318e7fcd96b..0bf402c6c21 100644 --- a/htdocs/compta/sociales/class/paymentsocialcontribution.class.php +++ b/htdocs/compta/sociales/class/paymentsocialcontribution.class.php @@ -552,7 +552,7 @@ class PaymentSocialContribution extends CommonObject $error = 0; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { include_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; $acc = new Account($this->db); diff --git a/htdocs/compta/sociales/list.php b/htdocs/compta/sociales/list.php index 14b8bfa043f..80b231ac381 100644 --- a/htdocs/compta/sociales/list.php +++ b/htdocs/compta/sociales/list.php @@ -107,7 +107,7 @@ $arrayfields = array( 'cs.paye' =>array('label'=>"Status", 'checked'=>1, 'position'=>110), ); -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { $arrayfields['cs.fk_account'] = array('checked'=>-1, 'position'=>90, 'label'=>"DefaultBankAccount"); } diff --git a/htdocs/compta/sociales/payments.php b/htdocs/compta/sociales/payments.php index 843dbd58a50..7d59f16cd24 100644 --- a/htdocs/compta/sociales/payments.php +++ b/htdocs/compta/sociales/payments.php @@ -225,7 +225,7 @@ print ''; print ''; print ''; print ''; -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { print ''; print ''; } @@ -245,7 +245,7 @@ print_liste_field_titre("DatePayment", $_SERVER["PHP_SELF"], "pc.datep", "", $pa print_liste_field_titre("Employee", $_SERVER["PHP_SELF"], "u.rowid", "", $param, "", $sortfield, $sortorder); print_liste_field_titre("PaymentMode", $_SERVER["PHP_SELF"], "pct.code", "", $param, '', $sortfield, $sortorder); print_liste_field_titre("Numero", $_SERVER["PHP_SELF"], "pc.num_paiement", "", $param, '', $sortfield, $sortorder, '', 'ChequeOrTransferNumber'); -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { print_liste_field_titre("BankTransactionLine", $_SERVER["PHP_SELF"], "pc.fk_bank", "", $param, '', $sortfield, $sortorder); print_liste_field_titre("Account", $_SERVER["PHP_SELF"], "ba.label", "", $param, "", $sortfield, $sortorder); } @@ -323,7 +323,7 @@ while ($i < min($num, $limit)) { print ''; // Account - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { // Bank transaction print ''; print ''; print ''; print ''; -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { print ''; print ''; } diff --git a/htdocs/compta/stats/cabyuser.php b/htdocs/compta/stats/cabyuser.php index 2b8f40b3aba..c02a8805ceb 100644 --- a/htdocs/compta/stats/cabyuser.php +++ b/htdocs/compta/stats/cabyuser.php @@ -478,7 +478,7 @@ if (count($amount)) { // Other stats print '\n"; print ""; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { // Bank account print ''; // Bank account - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print '
'; print $langs->trans('DefaultBankAccount'); @@ -668,7 +668,7 @@ if ($id > 0) { print '
'; $nbcols = 3; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $nbcols++; } @@ -703,7 +703,7 @@ if ($id > 0) { print '
'.$langs->trans("RefPayment").''.$langs->trans("Date").''.$langs->trans("Type").''.$langs->trans('BankAccount').''.$langs->trans("Amount").''.dol_print_date($db->jdate($objp->dp), 'day')."".$labeltype.' '.$objp->num_payment."'.$obj->num_payment.''; $accountlinestatic->id = $obj->fk_bank; @@ -379,7 +379,7 @@ print '    '; - if (!empty($conf->propal->enabled) && $key > 0) { + if (isModEnabled("propal") && $key > 0) { print ' '.img_picto($langs->trans("ProposalStats"), "stats").' '; } if (!empty($conf->commande->enabled) && $key > 0) { diff --git a/htdocs/compta/stats/casoc.php b/htdocs/compta/stats/casoc.php index 320efa36ed6..945db5c916a 100644 --- a/htdocs/compta/stats/casoc.php +++ b/htdocs/compta/stats/casoc.php @@ -652,7 +652,7 @@ if (count($amount)) { // Other stats print ''; - if (!empty($conf->propal->enabled) && $key > 0) { + if (isModEnabled("propal") && $key > 0) { print ' '.img_picto($langs->trans("ProposalStats"), "stats").' '; } if (!empty($conf->commande->enabled) && $key > 0) { diff --git a/htdocs/compta/tva/card.php b/htdocs/compta/tva/card.php index e40b9b9b409..b4f16f0e564 100644 --- a/htdocs/compta/tva/card.php +++ b/htdocs/compta/tva/card.php @@ -494,7 +494,7 @@ if ($action == 'create') { print "
'.$langs->trans("BankAccount").''; print img_picto('', 'bank_account', 'pictofixedwidth'); @@ -629,7 +629,7 @@ if ($id > 0) { print '
'; print ''; print ''; print ''; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print ''; } print ''; @@ -712,7 +712,7 @@ if ($id > 0) { print '\n"; $labeltype = $langs->trans("PaymentType".$objp->type_code) != ("PaymentType".$objp->type_code) ? $langs->trans("PaymentType".$objp->type_code) : $objp->paiement_type; print "\n"; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $bankaccountstatic->id = $objp->baid; $bankaccountstatic->ref = $objp->baref; $bankaccountstatic->label = $objp->baref; diff --git a/htdocs/compta/tva/class/paymentvat.class.php b/htdocs/compta/tva/class/paymentvat.class.php index b7500fffaa0..ec951d8d72d 100644 --- a/htdocs/compta/tva/class/paymentvat.class.php +++ b/htdocs/compta/tva/class/paymentvat.class.php @@ -560,7 +560,7 @@ class PaymentVAT extends CommonObject $error = 0; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { include_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; $acc = new Account($this->db); diff --git a/htdocs/compta/tva/class/tva.class.php b/htdocs/compta/tva/class/tva.class.php index f54ed42fb06..1ce6bed212b 100644 --- a/htdocs/compta/tva/class/tva.class.php +++ b/htdocs/compta/tva/class/tva.class.php @@ -572,11 +572,11 @@ class Tva extends CommonObject $this->error = $langs->trans("ErrorFieldRequired", $langs->transnoentities("Amount")); return -4; } - if (!empty($conf->banque->enabled) && (empty($this->accountid) || $this->accountid <= 0)) { + if (isModEnabled("banque") && (empty($this->accountid) || $this->accountid <= 0)) { $this->error = $langs->trans("ErrorFieldRequired", $langs->transnoentities("Account")); return -5; } - if (!empty($conf->banque->enabled) && (empty($this->type_payment) || $this->type_payment <= 0)) { + if (isModEnabled("banque") && (empty($this->type_payment) || $this->type_payment <= 0)) { $this->error = $langs->trans("ErrorFieldRequired", $langs->transnoentities("PaymentMode")); return -5; } @@ -633,7 +633,7 @@ class Tva extends CommonObject if ($this->id > 0) { $ok = 1; - if (!empty($conf->banque->enabled) && !empty($this->amount)) { + if (isModEnabled("banque") && !empty($this->amount)) { // Insert into llx_bank require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; diff --git a/htdocs/compta/tva/list.php b/htdocs/compta/tva/list.php index 5f76b2e9190..524f8b0105b 100644 --- a/htdocs/compta/tva/list.php +++ b/htdocs/compta/tva/list.php @@ -83,7 +83,7 @@ $arrayfields = array( 't.status' =>array('checked'=>1, 'position'=>90, 'label'=>"Status"), ); -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { $arrayfields['t.fk_account'] = array('checked'=>1, 'position'=>60, 'label'=>"DefaultBankAccount"); } diff --git a/htdocs/compta/tva/payments.php b/htdocs/compta/tva/payments.php index 0279acdeaa4..9e7c19c8754 100644 --- a/htdocs/compta/tva/payments.php +++ b/htdocs/compta/tva/payments.php @@ -129,7 +129,7 @@ if (!empty($conf->tax->enabled) && $user->rights->tax->charges->lire) { print_liste_field_titre("DatePayment", $_SERVER["PHP_SELF"], "ptva.datep", "", $param, 'align="center"', $sortfield, $sortorder); print_liste_field_titre("PaymentMode", $_SERVER["PHP_SELF"], "pct.code", "", $param, '', $sortfield, $sortorder); print_liste_field_titre("Numero", $_SERVER["PHP_SELF"], "ptva.num_paiement", "", $param, '', $sortfield, $sortorder, '', 'ChequeOrTransferNumber'); - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print_liste_field_titre("BankTransactionLine", $_SERVER["PHP_SELF"], "ptva.fk_bank", "", $param, '', $sortfield, $sortorder); print_liste_field_titre("BankAccount", $_SERVER["PHP_SELF"], "bank.ref", "", $param, '', $sortfield, $sortorder); } @@ -221,7 +221,7 @@ if (!empty($conf->tax->enabled) && $user->rights->tax->charges->lire) { // Chq number print ''; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { // Bank transaction print ''; // A total here has no sense print ''; print ''; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print ''; print ''; } diff --git a/htdocs/contact/canvas/actions_contactcard_common.class.php b/htdocs/contact/canvas/actions_contactcard_common.class.php index a72ea3d7d21..2c7ac145b78 100644 --- a/htdocs/contact/canvas/actions_contactcard_common.class.php +++ b/htdocs/contact/canvas/actions_contactcard_common.class.php @@ -196,7 +196,7 @@ abstract class ActionsContactCardCommon $this->tpl['contact_element'][$i]['linked_element_value'] = $this->object->ref_commande ? $this->object->ref_commande : $langs->trans("NoContactForAnyOrder"); $i++; } - if (!empty($conf->propal->enabled)) { + if (isModEnabled("propal")) { $this->tpl['contact_element'][$i]['linked_element_label'] = $langs->trans("ContactForProposals"); $this->tpl['contact_element'][$i]['linked_element_value'] = $this->object->ref_propal ? $this->object->ref_propal : $langs->trans("NoContactForAnyProposal"); $i++; diff --git a/htdocs/contact/card.php b/htdocs/contact/card.php index 888c09124ad..d486432f142 100644 --- a/htdocs/contact/card.php +++ b/htdocs/contact/card.php @@ -1228,7 +1228,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print ''; } - if (!empty($conf->propal->enabled)) { + if (isModEnabled("propal")) { print ''; @@ -1326,7 +1326,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { //array('label' => $form->textwithpicto($langs->trans("Type"),$langs->trans("InternalExternalDesc")), 'type' => 'select', 'name' => 'intern', 'default' => 1, 'values' => array(0=>$langs->trans('Internal'),1=>$langs->trans('External'))) ); $text = $langs->trans("ConfirmCreateContact").'
'; - if (!empty($conf->societe->enabled)) { + if (isModEnabled("societe")) { if ($object->socid > 0) { $text .= $langs->trans("UserWillBeExternalUser"); } else { @@ -1489,22 +1489,22 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { $object->load_ref_elements(); - if (!empty($conf->propal->enabled)) { + if (isModEnabled("propal")) { print ''; } - if (!empty($conf->commande->enabled) || !empty($conf->expedition->enabled)) { + if (!empty($conf->commande->enabled) || isModEnabled("expedition")) { print ''; if ($object->thirdparty->client) { $thirdTypeArray['customer'] = $langs->trans("customer"); - if (!empty($conf->propal->enabled) && $user->rights->propal->lire) { + if (isModEnabled("propal") && $user->rights->propal->lire) { $elementTypeArray['propal'] = $langs->transnoentitiesnoconv('Proposals'); } if (!empty($conf->commande->enabled) && $user->rights->commande->lire) { diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php index ff3a6db84f1..8c2dbad409d 100644 --- a/htdocs/contrat/card.php +++ b/htdocs/contrat/card.php @@ -41,7 +41,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; -if (!empty($conf->propal->enabled)) { +if (isModEnabled("propal")) { require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php'; } if (!empty($conf->project->enabled)) { diff --git a/htdocs/core/boxes/box_activity.php b/htdocs/core/boxes/box_activity.php index 49690dc893e..12656518efc 100644 --- a/htdocs/core/boxes/box_activity.php +++ b/htdocs/core/boxes/box_activity.php @@ -102,7 +102,7 @@ class box_activity extends ModeleBoxes // list the summary of the propals - if (!empty($conf->propal->enabled) && $user->rights->propale->lire) { + if (isModEnabled("propal") && $user->rights->propale->lire) { include_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php'; $propalstatic = new Propal($this->db); diff --git a/htdocs/core/boxes/box_graph_product_distribution.php b/htdocs/core/boxes/box_graph_product_distribution.php index 44f94fd48d1..42a77f14b9c 100644 --- a/htdocs/core/boxes/box_graph_product_distribution.php +++ b/htdocs/core/boxes/box_graph_product_distribution.php @@ -152,7 +152,7 @@ class box_graph_product_distribution extends ModeleBoxes $WIDTH = ($nbofgraph >= 2 || !empty($conf->dol_optimize_smallscreen)) ? '300' : '320'; $HEIGHT = '150'; // Height require to have 5+1 entries into legend visible. - if (!empty($conf->propal->enabled) && !empty($user->rights->propale->lire)) { + if (isModEnabled("propal") && !empty($user->rights->propale->lire)) { // Build graphic number of object. $data = array(array('Lib',val1,val2,val3),...) if ($showpropalnb) { $langs->load("propal"); @@ -365,7 +365,7 @@ class box_graph_product_distribution extends ModeleBoxes $stringtoshow .= ''; $stringtoshow .= ''; $stringtoshow .= ''; - if (!empty($conf->propal->enabled) || !empty($user->rights->propale->lire)) { + if (isModEnabled("propal") || !empty($user->rights->propale->lire)) { $stringtoshow .= ' '.$langs->trans("ForProposals"); $stringtoshow .= ' '; } diff --git a/htdocs/core/boxes/box_produits.php b/htdocs/core/boxes/box_produits.php index afd0db27990..ed4dea21cc1 100644 --- a/htdocs/core/boxes/box_produits.php +++ b/htdocs/core/boxes/box_produits.php @@ -62,7 +62,7 @@ class box_produits extends ModeleBoxes $this->db = $db; $listofmodulesforexternal = explode(',', $conf->global->MAIN_MODULES_FOR_EXTERNAL); - $tmpentry = array('enabled'=>(!empty($conf->product->enabled) || !empty($conf->service->enabled)), 'perms'=>(!empty($user->rights->produit->lire) || !empty($user->rights->service->lire)), 'module'=>'product|service'); + $tmpentry = array('enabled'=>(isModEnabled("product") || !empty($conf->service->enabled)), 'perms'=>(!empty($user->rights->produit->lire) || !empty($user->rights->service->lire)), 'module'=>'product|service'); $showmode = isVisibleToUserType(($user->socid > 0 ? 1 : 0), $tmpentry, $listofmodulesforexternal); $this->hidden = ($showmode != 1); } diff --git a/htdocs/core/boxes/box_produits_alerte_stock.php b/htdocs/core/boxes/box_produits_alerte_stock.php index 72b1957b287..16370917dbd 100644 --- a/htdocs/core/boxes/box_produits_alerte_stock.php +++ b/htdocs/core/boxes/box_produits_alerte_stock.php @@ -64,7 +64,7 @@ class box_produits_alerte_stock extends ModeleBoxes $this->db = $db; $listofmodulesforexternal = explode(',', $conf->global->MAIN_MODULES_FOR_EXTERNAL); - $tmpentry = array('enabled'=>((!empty($conf->product->enabled) || !empty($conf->service->enabled)) && !empty($conf->stock->enabled)), 'perms'=>!empty($user->rights->stock->lire), 'module'=>'product|service|stock'); + $tmpentry = array('enabled'=>((isModEnabled("product") || !empty($conf->service->enabled)) && !empty($conf->stock->enabled)), 'perms'=>!empty($user->rights->stock->lire), 'module'=>'product|service|stock'); $showmode = isVisibleToUserType(($user->socid > 0 ? 1 : 0), $tmpentry, $listofmodulesforexternal); $this->hidden = ($showmode != 1); } diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 777322631b0..b6da0e8822e 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -1104,7 +1104,7 @@ class Form global $langs, $conf; // If product & services are enabled or both disabled. - if ($forceall == 1 || (empty($forceall) && !empty($conf->product->enabled) && !empty($conf->service->enabled)) + if ($forceall == 1 || (empty($forceall) && isModEnabled("product") && !empty($conf->service->enabled)) || (empty($forceall) && empty($conf->product->enabled) && empty($conf->service->enabled))) { if (empty($hidetext)) { print $langs->trans("Type").': '; @@ -1138,7 +1138,7 @@ class Form print $langs->trans("Service"); print ''; } - if ((empty($forceall) && !empty($conf->product->enabled) && empty($conf->service->enabled)) || $forceall == 2) { + if ((empty($forceall) && isModEnabled("product") && empty($conf->service->enabled)) || $forceall == 2) { print $langs->trans("Product"); print ''; } @@ -2278,8 +2278,8 @@ class Form $ajaxoptions = array(); } - if (strval($filtertype) === '' && (!empty($conf->product->enabled) || !empty($conf->service->enabled))) { - if (!empty($conf->product->enabled) && empty($conf->service->enabled)) { + if (strval($filtertype) === '' && (isModEnabled("product") || !empty($conf->service->enabled))) { + if (isModEnabled("product") && empty($conf->service->enabled)) { $filtertype = '0'; } elseif (empty($conf->product->enabled) && !empty($conf->service->enabled)) { $filtertype = '1'; diff --git a/htdocs/core/class/html.formbarcode.class.php b/htdocs/core/class/html.formbarcode.class.php index 8c3d84dffa4..def8be3cd40 100644 --- a/htdocs/core/class/html.formbarcode.class.php +++ b/htdocs/core/class/html.formbarcode.class.php @@ -80,8 +80,8 @@ class FormBarCode } // We check if barcode is already selected by default - if (((!empty($conf->product->enabled) || !empty($conf->service->enabled)) && $conf->global->PRODUIT_DEFAULT_BARCODE_TYPE == $code_id) || - (!empty($conf->societe->enabled) && $conf->global->GENBARCODE_BARCODETYPE_THIRDPARTY == $code_id)) { + if (((isModEnabled("product") || !empty($conf->service->enabled)) && $conf->global->PRODUIT_DEFAULT_BARCODE_TYPE == $code_id) || + (isModEnabled("societe") && $conf->global->GENBARCODE_BARCODETYPE_THIRDPARTY == $code_id)) { $disable = 'disabled'; } diff --git a/htdocs/core/class/html.formmargin.class.php b/htdocs/core/class/html.formmargin.class.php index f39680d1fe3..8f6c911a095 100644 --- a/htdocs/core/class/html.formmargin.class.php +++ b/htdocs/core/class/html.formmargin.class.php @@ -254,7 +254,7 @@ class FormMargin } print ''; - if (!empty($conf->product->enabled)) { + if (isModEnabled("product")) { //if ($marginInfo['margin_on_products'] != 0 && $marginInfo['margin_on_services'] != 0) { print ''; print ''; @@ -285,7 +285,7 @@ class FormMargin print ''; } - if (!empty($conf->product->enabled) && !empty($conf->service->enabled)) { + if (isModEnabled("product") && !empty($conf->service->enabled)) { print ''; print ''; print ''; diff --git a/htdocs/core/class/html.formsetup.class.php b/htdocs/core/class/html.formsetup.class.php index 87fc937429c..67d07cb6992 100644 --- a/htdocs/core/class/html.formsetup.class.php +++ b/htdocs/core/class/html.formsetup.class.php @@ -851,7 +851,7 @@ class FormSetupItem } elseif ($this->type == 'securekey') { $out.= $this->generateInputFieldSecureKey(); } elseif ($this->type == 'product') { - if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { + if (isModEnabled("product") || !empty($conf->service->enabled)) { $selected = (empty($this->fieldValue) ? '' : $this->fieldValue); $out.= $this->form->select_produits($selected, $this->confKey, '', 0, 0, 1, 2, '', 0, array(), 0, '1', 0, $this->cssClass, 0, '', null, 1); } diff --git a/htdocs/core/lib/contact.lib.php b/htdocs/core/lib/contact.lib.php index b63e7b025c7..f3b85233ca7 100644 --- a/htdocs/core/lib/contact.lib.php +++ b/htdocs/core/lib/contact.lib.php @@ -92,7 +92,7 @@ function contact_prepare_head(Contact $object) } // Related items - if (!empty($conf->commande->enabled) || !empty($conf->propal->enabled) || isModEnabled('facture') || !empty($conf->ficheinter->enabled) || (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { + if (!empty($conf->commande->enabled) || isModEnabled("propal") || isModEnabled('facture') || !empty($conf->ficheinter->enabled) || (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { $head[$tab][0] = DOL_URL_ROOT.'/contact/consumption.php?id='.$object->id; $head[$tab][1] = $langs->trans("Referers"); $head[$tab][2] = 'consumption'; diff --git a/htdocs/core/lib/expedition.lib.php b/htdocs/core/lib/expedition.lib.php index 99118197174..b9eb90d7f9f 100644 --- a/htdocs/core/lib/expedition.lib.php +++ b/htdocs/core/lib/expedition.lib.php @@ -35,7 +35,7 @@ function expedition_prepare_head(Expedition $object) { global $langs, $conf, $user; - if (!empty($conf->expedition->enabled)) { + if (isModEnabled("expedition")) { $langs->load("sendings"); } $langs->load("orders"); diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index cd4ff50044e..ce33ed2553b 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -318,7 +318,7 @@ function completeFileArrayWithDatabaseInfo(&$filearray, $relativedir) if ($modulepart == 'produit' && !empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) { global $object; if (!empty($object->id)) { - if (!empty($conf->product->enabled)) { + if (isModEnabled("product")) { $upload_dirold = $conf->product->multidir_output[$object->entity].'/'.substr(substr("000".$object->id, -2), 1, 1).'/'.substr(substr("000".$object->id, -2), 0, 1).'/'.$object->id."/photos"; } else { $upload_dirold = $conf->service->multidir_output[$object->entity].'/'.substr(substr("000".$object->id, -2), 1, 1).'/'.substr(substr("000".$object->id, -2), 0, 1).'/'.$object->id."/photos"; @@ -2921,7 +2921,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, if (($fuser->rights->produit->{$lire} || $fuser->rights->service->{$lire}) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; } - if (!empty($conf->product->enabled)) { + if (isModEnabled("product")) { $original_file = $conf->product->multidir_output[$entity].'/'.$original_file; } elseif (!empty($conf->service->enabled)) { $original_file = $conf->service->multidir_output[$entity].'/'.$original_file; diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index bddb4e665d3..1c619028b0b 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -7347,7 +7347,7 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, $substitutionarray['__NOTE_PRIVATE__'] = '__NOTE_PRIVATE__'; $substitutionarray['__EXTRAFIELD_XXX__'] = '__EXTRAFIELD_XXX__'; - if (!empty($conf->societe->enabled)) { // Most objects are concerned + if (isModEnabled("societe")) { // Most objects are concerned $substitutionarray['__THIRDPARTY_ID__'] = '__THIRDPARTY_ID__'; $substitutionarray['__THIRDPARTY_NAME__'] = '__THIRDPARTY_NAME__'; $substitutionarray['__THIRDPARTY_NAME_ALIAS__'] = '__THIRDPARTY_NAME_ALIAS__'; @@ -7409,7 +7409,7 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, $substitutionarray['__CONTRACT_LOWEST_EXPIRATION_DATE__'] = 'Lowest data for planned expiration of service'; $substitutionarray['__CONTRACT_LOWEST_EXPIRATION_DATETIME__'] = 'Lowest date and hour for planned expiration of service'; } - if (!empty($conf->propal->enabled) && (!is_object($object) || $object->element == 'propal')) { + if (isModEnabled("propal") && (!is_object($object) || $object->element == 'propal')) { $substitutionarray['__ONLINE_SIGN_URL__'] = 'ToOfferALinkForOnlineSignature'; } $substitutionarray['__ONLINE_PAYMENT_URL__'] = 'UrlToPayOnlineIfApplicable'; @@ -7426,11 +7426,11 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, $substitutionarray['__DIRECTDOWNLOAD_URL_CONTRACT__'] = 'Direct download url of a contract'; $substitutionarray['__DIRECTDOWNLOAD_URL_SUPPLIER_PROPOSAL__'] = 'Direct download url of a supplier proposal'; - if (!empty($conf->expedition->enabled) && (!is_object($object) || $object->element == 'shipping')) { + if (isModEnabled("expedition") && (!is_object($object) || $object->element == 'shipping')) { $substitutionarray['__SHIPPINGTRACKNUM__'] = 'Shipping tracking number'; $substitutionarray['__SHIPPINGTRACKNUMURL__'] = 'Shipping tracking url'; } - if (!empty($conf->reception->enabled) && (!is_object($object) || $object->element == 'reception')) { + if (isModEnabled("reception") && (!is_object($object) || $object->element == 'reception')) { $substitutionarray['__RECEPTIONTRACKNUM__'] = 'Shippin tracking number of shipment'; $substitutionarray['__RECEPTIONTRACKNUMURL__'] = 'Shipping tracking url'; } diff --git a/htdocs/core/lib/ldap.lib.php b/htdocs/core/lib/ldap.lib.php index 56a8bcc4285..7e173bd269e 100644 --- a/htdocs/core/lib/ldap.lib.php +++ b/htdocs/core/lib/ldap.lib.php @@ -57,7 +57,7 @@ function ldap_prepare_head() $h++; } - if (!empty($conf->societe->enabled) && !empty($conf->global->LDAP_CONTACT_ACTIVE)) { + if (isModEnabled("societe") && !empty($conf->global->LDAP_CONTACT_ACTIVE)) { $head[$h][0] = DOL_URL_ROOT."/admin/ldap_contacts.php"; $head[$h][1] = $langs->trans("LDAPContactsSynchro"); $head[$h][2] = 'contacts'; diff --git a/htdocs/core/lib/order.lib.php b/htdocs/core/lib/order.lib.php index bde894940de..9a5e9ae56a5 100644 --- a/htdocs/core/lib/order.lib.php +++ b/htdocs/core/lib/order.lib.php @@ -34,7 +34,7 @@ function commande_prepare_head(Commande $object) { global $db, $langs, $conf, $user; - if (!empty($conf->expedition->enabled)) { + if (isModEnabled("expedition")) { $langs->load("sendings"); } $langs->load("orders"); diff --git a/htdocs/core/lib/pdf.lib.php b/htdocs/core/lib/pdf.lib.php index be89f4700b8..228ca7d4b76 100644 --- a/htdocs/core/lib/pdf.lib.php +++ b/htdocs/core/lib/pdf.lib.php @@ -61,7 +61,7 @@ function pdf_admin_prepare_head() // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab complete_head_from_modules($conf, $langs, null, $head, $h, 'pdf_admin'); - if (!empty($conf->propal->enabled)) { + if (isModEnabled("propal")) { $head[$h][0] = DOL_URL_ROOT.'/admin/pdf_other.php'; $head[$h][1] = $langs->trans("Other"); $head[$h][2] = 'other'; diff --git a/htdocs/core/lib/product.lib.php b/htdocs/core/lib/product.lib.php index 7b3d1e4637f..c6ddf3b756d 100644 --- a/htdocs/core/lib/product.lib.php +++ b/htdocs/core/lib/product.lib.php @@ -171,7 +171,7 @@ function product_prepare_head($object) // Attachments require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php'; - if (!empty($conf->product->enabled) && ($object->type == Product::TYPE_PRODUCT)) { + if (isModEnabled("product") && ($object->type == Product::TYPE_PRODUCT)) { $upload_dir = $conf->product->multidir_output[$object->entity].'/'.dol_sanitizeFileName($object->ref); } if (!empty($conf->service->enabled) && ($object->type == Product::TYPE_SERVICE)) { @@ -179,7 +179,7 @@ function product_prepare_head($object) } $nbFiles = count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$')); if (!empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) { - if (!empty($conf->product->enabled) && ($object->type == Product::TYPE_PRODUCT)) { + if (isModEnabled("product") && ($object->type == Product::TYPE_PRODUCT)) { $upload_dir = $conf->product->multidir_output[$object->entity].'/'.get_exdir($object->id, 2, 0, 0, $object, 'product').$object->id.'/photos'; } if (!empty($conf->service->enabled) && ($object->type == Product::TYPE_SERVICE)) { @@ -374,7 +374,7 @@ function show_stats_for_company($product, $socid) print ''; // Customer proposals - if (!empty($conf->propal->enabled) && $user->rights->propale->lire) { + if (isModEnabled("propal") && $user->rights->propale->lire) { $nblines++; $ret = $product->load_stats_propale($socid); if ($ret < 0) { @@ -469,7 +469,7 @@ function show_stats_for_company($product, $socid) print ''; } // Customer template invoices - if (!empty($conf->facture->enabled) && $user->rights->facture->lire) { + if (isModEnabled("facture") && $user->rights->facture->lire) { $nblines++; $ret = $product->load_stats_facturerec($socid); if ($ret < 0) { diff --git a/htdocs/core/lib/project.lib.php b/htdocs/core/lib/project.lib.php index 776d0f0776f..14dbbe81c70 100644 --- a/htdocs/core/lib/project.lib.php +++ b/htdocs/core/lib/project.lib.php @@ -125,7 +125,7 @@ function project_prepare_head(Project $project, $moreparam = '') } if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) - || !empty($conf->propal->enabled) || !empty($conf->commande->enabled) + || isModEnabled("propal") || !empty($conf->commande->enabled) || isModEnabled('facture') || !empty($conf->contrat->enabled) || !empty($conf->ficheinter->enabled) || !empty($conf->agenda->enabled) || !empty($conf->deplacement->enabled) || !empty($conf->stock->enabled)) { $nbElements = 0; @@ -138,7 +138,7 @@ function project_prepare_head(Project $project, $moreparam = '') if (!empty($conf->stock->enabled)) { $nbElements += $project->getElementCount('stock', 'entrepot', 'fk_project'); } - if (!empty($conf->propal->enabled)) { + if (isModEnabled("propal")) { $nbElements += $project->getElementCount('propal', 'propal'); } if (!empty($conf->commande->enabled)) { @@ -165,7 +165,7 @@ function project_prepare_head(Project $project, $moreparam = '') if (!empty($conf->ficheinter->enabled)) { $nbElements += $project->getElementCount('intervention', 'fichinter'); } - if (!empty($conf->expedition->enabled)) { + if (isModEnabled("expedition")) { $nbElements += $project->getElementCount('shipping', 'expedition'); } if (!empty($conf->mrp->enabled)) { @@ -195,7 +195,7 @@ function project_prepare_head(Project $project, $moreparam = '') if (!empty($conf->salaries->enabled)) { $nbElements += $project->getElementCount('salaries', 'payment_salary'); } - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $nbElements += $project->getElementCount('variouspayment', 'payment_various'); } dol_setcache($cachekey, $nbElements, 120); // If setting cache fails, this is not a problem, so we do not test result. diff --git a/htdocs/core/lib/propal.lib.php b/htdocs/core/lib/propal.lib.php index c5d2a647a57..71391f2e499 100644 --- a/htdocs/core/lib/propal.lib.php +++ b/htdocs/core/lib/propal.lib.php @@ -42,8 +42,8 @@ function propal_prepare_head($object) $head[$h][2] = 'comm'; $h++; - if ((empty($conf->commande->enabled) && ((!empty($conf->expedition->enabled) && !empty($conf->expedition_bon->enabled) && $user->rights->expedition->lire) - || (!empty($conf->expedition->enabled) && !empty($conf->delivery_note->enabled) && $user->rights->expedition->delivery->lire)))) { + if ((empty($conf->commande->enabled) && ((isModEnabled("expedition") && !empty($conf->expedition_bon->enabled) && $user->rights->expedition->lire) + || (isModEnabled("expedition") && !empty($conf->delivery_note->enabled) && $user->rights->expedition->delivery->lire)))) { $langs->load("sendings"); $text = ''; $head[$h][0] = DOL_URL_ROOT.'/expedition/propal.php?id='.$object->id; diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php index 1d3f013e9f3..4989edc3361 100644 --- a/htdocs/core/lib/security.lib.php +++ b/htdocs/core/lib/security.lib.php @@ -729,7 +729,7 @@ function checkUserAccessToObject($user, array $featuresarray, $object = 0, $tabl if ($user->socid != $objectid) { return false; } - } elseif (!empty($conf->societe->enabled) && ($user->rights->societe->lire && empty($user->rights->societe->client->voir))) { + } elseif (isModEnabled("societe") && ($user->rights->societe->lire && empty($user->rights->societe->client->voir))) { // If internal user: Check permission for internal users that are restricted on their objects $sql = "SELECT COUNT(sc.fk_soc) as nb"; $sql .= " FROM (".MAIN_DB_PREFIX."societe_commerciaux as sc"; @@ -755,7 +755,7 @@ function checkUserAccessToObject($user, array $featuresarray, $object = 0, $tabl $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt"; $sql .= " WHERE dbt.".$dbt_select." IN (".$db->sanitize($objectid, 1).")"; $sql .= " AND dbt.fk_soc = ".((int) $user->socid); - } elseif (!empty($conf->societe->enabled) && ($user->rights->societe->lire && empty($user->rights->societe->client->voir))) { + } elseif (isModEnabled("societe") && ($user->rights->societe->lire && empty($user->rights->societe->client->voir))) { // If internal user: Check permission for internal users that are restricted on their objects $sql = "SELECT COUNT(dbt.".$dbt_select.") as nb"; $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt"; @@ -827,7 +827,7 @@ function checkUserAccessToObject($user, array $featuresarray, $object = 0, $tabl $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt"; $sql .= " WHERE dbt.rowid IN (".$db->sanitize($objectid, 1).")"; $sql .= " AND dbt.".$dbt_keyfield." = ".((int) $user->socid); - } elseif (!empty($conf->societe->enabled) && empty($user->rights->societe->client->voir)) { + } elseif (isModEnabled("societe") && empty($user->rights->societe->client->voir)) { // If internal user: Check permission for internal users that are restricted on their objects if ($feature != 'ticket') { if (empty($dbt_keyfield)) { diff --git a/htdocs/core/modules/DolibarrModules.class.php b/htdocs/core/modules/DolibarrModules.class.php index 627a13a7844..e7fbb0420fe 100644 --- a/htdocs/core/modules/DolibarrModules.class.php +++ b/htdocs/core/modules/DolibarrModules.class.php @@ -1368,7 +1368,7 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it // For the moment, we manage this with hard coded exception //print "Remove box ".$file.'
'; if ($file == 'box_graph_product_distribution.php') { - if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { + if (isModEnabled("product") || !empty($conf->service->enabled)) { dol_syslog("We discard deleting module ".$file." because another module still active requires it."); continue; } diff --git a/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php b/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php index 43c1ae9e4de..365a2326281 100644 --- a/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php +++ b/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php @@ -1043,7 +1043,7 @@ class pdf_standard extends ModeleExpenseReport $pdf->MultiCell(15, 3, $outputlangs->transnoentities("Amount"), 0, 'C', 0); $pdf->SetXY($tab3_posx + 35, $tab3_top + 1); $pdf->MultiCell(30, 3, $outputlangs->transnoentities("Type"), 0, 'L', 0); - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $pdf->SetXY($tab3_posx + 65, $tab3_top + 1); $pdf->MultiCell(25, 3, $outputlangs->transnoentities("BankAccount"), 0, 'L', 0); } @@ -1083,7 +1083,7 @@ class pdf_standard extends ModeleExpenseReport $oper = $outputlangs->transnoentitiesnoconv("PaymentTypeShort".$row->p_code); $pdf->MultiCell(40, 3, $oper, 0, 'L', 0); - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $pdf->SetXY($tab3_posx + 65, $tab3_top + $y + 1); $pdf->MultiCell(30, 3, $row->baref, 0, 'L', 0); } diff --git a/htdocs/core/modules/modAdherent.class.php b/htdocs/core/modules/modAdherent.class.php index ec0546e9af1..d4d5b2beb89 100644 --- a/htdocs/core/modules/modAdherent.class.php +++ b/htdocs/core/modules/modAdherent.class.php @@ -345,7 +345,7 @@ class modAdherent extends DolibarrModules 'a.email'=>"Email", 'a.birth'=>"Birthday", 'a.statut'=>"Status*", 'a.photo'=>"Photo", 'a.note_public'=>"NotePublic", 'a.note_private'=>"NotePrivate", 'a.datec'=>'DateCreation', 'a.datefin'=>'DateEndSubscription' ); - if (!empty($conf->societe->enabled)) { + if (isModEnabled("societe")) { $this->import_fields_array[$r]['a.fk_soc'] = "ThirdParty"; } // Add extra fields @@ -380,7 +380,7 @@ class modAdherent extends DolibarrModules 'dict' => 'DictionaryCountry' ) ); - if (!empty($conf->societe->enabled)) { + if (isModEnabled("societe")) { $this->import_convertvalue_array[$r]['a.fk_soc'] = array('rule'=>'fetchidfromref', 'classfile'=>'/societe/class/societe.class.php', 'class'=>'Societe', 'method'=>'fetch', 'element'=>'ThirdParty'); } $this->import_fieldshidden_array[$r] = array('extra.fk_object'=>'lastrowid-'.MAIN_DB_PREFIX.'adherent'); // aliastable.field => ('user->id' or 'lastrowid-'.tableparent) @@ -394,7 +394,7 @@ class modAdherent extends DolibarrModules 'a.email'=>'jsmith@example.com', 'a.birth'=>'1972-10-10', 'a.statut'=>"0 or 1", 'a.note_public'=>"This is a public comment on member", 'a.note_private'=>"This is private comment on member", 'a.datec'=>dol_print_date($now, '%Y-%m__%d'), 'a.datefin'=>dol_print_date(dol_time_plus_duree($now, 1, 'y'), '%Y-%m-%d') ); - if (!empty($conf->societe->enabled)) { + if (isModEnabled("societe")) { $this->import_examplevalues_array[$r]['a.fk_soc'] = "rowid or name"; } $this->import_updatekeys_array[$r] = array('a.ref'=>'MemberRef', 'a.login'=>'Login'); diff --git a/htdocs/core/modules/modCategorie.class.php b/htdocs/core/modules/modCategorie.class.php index 57ac7a637dc..bee6f95f00d 100644 --- a/htdocs/core/modules/modCategorie.class.php +++ b/htdocs/core/modules/modCategorie.class.php @@ -127,19 +127,19 @@ class modCategorie extends DolibarrModules $this->export_permission[$r] = array(array("categorie", "lire")); $typeexample = ""; - if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { + if (isModEnabled("product") || !empty($conf->service->enabled)) { $typeexample .= ($typeexample ? " / " : "")."0=Product-Service"; } if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { $typeexample .= ($typeexample ? "/" : "")."1=Supplier"; } - if (!empty($conf->societe->enabled)) { + if (isModEnabled("societe")) { $typeexample .= ($typeexample ? " / " : "")."2=Customer-Prospect"; } if (!empty($conf->adherent->enabled)) { $typeexample .= ($typeexample ? " / " : "")."3=Member"; } - if (!empty($conf->societe->enabled)) { + if (isModEnabled("societe")) { $typeexample .= ($typeexample ? " / " : "")."4=Contact"; } if (!empty($conf->bank->enabled)) { @@ -179,7 +179,7 @@ class modCategorie extends DolibarrModules $this->export_code[$r] = $this->rights_class.'_0_'.Categorie::$MAP_ID_TO_CODE[0]; $this->export_label[$r] = 'CatProdList'; $this->export_icon[$r] = $this->picto; - $this->export_enabled[$r] = '!empty($conf->product->enabled) || !empty($conf->service->abled)'; + $this->export_enabled[$r] = 'isModEnabled("product") || !empty($conf->service->abled)'; $this->export_permission[$r] = array(array("categorie", "lire"), array("produit", "export")); $this->export_fields_array[$r] = array('cat.rowid'=>"CategId", 'cat.label'=>"Label", 'cat.description'=>"Description", 'cat.fk_parent'=>"ParentCategory", 'p.rowid'=>'ProductId', 'p.ref'=>'Ref', 'p.label'=>'Label'); $this->export_TypeFields_array[$r] = array('cat.label'=>"Text", 'cat.description'=>"Text", 'cat.fk_parent'=>'List:categorie:label:rowid', 'p.ref'=>'Text', 'p.label'=>'Text'); @@ -249,7 +249,7 @@ class modCategorie extends DolibarrModules $this->export_code[$r] = $this->rights_class.'_2_'.Categorie::$MAP_ID_TO_CODE[2]; $this->export_label[$r] = 'CatCusList'; $this->export_icon[$r] = $this->picto; - $this->export_enabled[$r] = '!empty($conf->societe->enabled)'; + $this->export_enabled[$r] = 'isModEnabled("societe")'; $this->export_permission[$r] = array(array("categorie", "lire"), array("societe", "export")); $this->export_fields_array[$r] = array( 'cat.rowid'=>"CategId", 'cat.label'=>"Label", 'cat.description'=>"Description", 'cat.fk_parent'=>"ParentCategory", @@ -321,7 +321,7 @@ class modCategorie extends DolibarrModules $this->export_code[$r] = $this->rights_class.'_4_'.Categorie::$MAP_ID_TO_CODE[4]; $this->export_label[$r] = 'CatContactList'; $this->export_icon[$r] = $this->picto; - $this->export_enabled[$r] = '!empty($conf->societe->enabled)'; + $this->export_enabled[$r] = 'isModEnabled("societe")'; $this->export_permission[$r] = array(array("categorie", "lire"), array("societe", "contact", "export")); $this->export_fields_array[$r] = array( 'cat.rowid'=>"CategId", 'cat.label'=>"Label", 'cat.description'=>"Description", 'cat.fk_parent'=>"ParentCategory", @@ -466,7 +466,7 @@ class modCategorie extends DolibarrModules $this->import_updatekeys_array[$r] = array('ca.label'=>'Label'); // 0 Products - if (!empty($conf->product->enabled)) { + if (isModEnabled("product")) { $r++; $this->import_code[$r] = $this->rights_class.'_0_'.Categorie::$MAP_ID_TO_CODE[0]; $this->import_label[$r] = "CatProdLinks"; // Translation key @@ -506,7 +506,7 @@ class modCategorie extends DolibarrModules } // 2 Customers - if (!empty($conf->societe->enabled)) { + if (isModEnabled("societe")) { $r++; $this->import_code[$r] = $this->rights_class.'_2_'.Categorie::$MAP_ID_TO_CODE[2]; $this->import_label[$r] = "CatCusLinks"; // Translation key @@ -545,7 +545,7 @@ class modCategorie extends DolibarrModules } // 4 Contacts/Addresses - if (!empty($conf->societe->enabled)) { + if (isModEnabled("societe")) { $r++; $this->import_code[$r] = $this->rights_class.'_4_'.Categorie::$MAP_ID_TO_CODE[4]; $this->import_label[$r] = "CatContactsLinks"; // Translation key diff --git a/htdocs/core/modules/project/doc/doc_generic_project_odt.modules.php b/htdocs/core/modules/project/doc/doc_generic_project_odt.modules.php index d00eee45219..4397faedb9c 100644 --- a/htdocs/core/modules/project/doc/doc_generic_project_odt.modules.php +++ b/htdocs/core/modules/project/doc/doc_generic_project_odt.modules.php @@ -37,7 +37,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/doc.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; -if (!empty($conf->propal->enabled)) { +if (isModEnabled("propal")) { require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php'; } if (isModEnabled('facture')) { diff --git a/htdocs/core/modules/project/task/doc/doc_generic_task_odt.modules.php b/htdocs/core/modules/project/task/doc/doc_generic_task_odt.modules.php index 410d3ae5b29..cb3fc54fa46 100644 --- a/htdocs/core/modules/project/task/doc/doc_generic_task_odt.modules.php +++ b/htdocs/core/modules/project/task/doc/doc_generic_task_odt.modules.php @@ -38,7 +38,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/doc.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; -if (!empty($conf->propal->enabled)) { +if (isModEnabled("propal")) { require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php'; } if (isModEnabled('facture')) { diff --git a/htdocs/core/modules/propale/doc/pdf_azur.modules.php b/htdocs/core/modules/propale/doc/pdf_azur.modules.php index 177443153ce..91cc9010f18 100644 --- a/htdocs/core/modules/propale/doc/pdf_azur.modules.php +++ b/htdocs/core/modules/propale/doc/pdf_azur.modules.php @@ -815,13 +815,13 @@ class pdf_azur extends ModelePDFPropales foreach ($filetomerge->lines as $linefile) { if (!empty($linefile->id) && !empty($linefile->file_name)) { if (!empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) { - if (!empty($conf->product->enabled)) { + if (isModEnabled("product")) { $filetomerge_dir = $conf->product->multidir_output[$entity_product_file].'/'.get_exdir($product->id, 2, 0, 0, $product, 'product').$product->id."/photos"; } elseif (!empty($conf->service->enabled)) { $filetomerge_dir = $conf->service->multidir_output[$entity_product_file].'/'.get_exdir($product->id, 2, 0, 0, $product, 'product').$product->id."/photos"; } } else { - if (!empty($conf->product->enabled)) { + if (isModEnabled("product")) { $filetomerge_dir = $conf->product->multidir_output[$entity_product_file].'/'.get_exdir(0, 0, 0, 0, $product, 'product'); } elseif (!empty($conf->service->enabled)) { $filetomerge_dir = $conf->service->multidir_output[$entity_product_file].'/'.get_exdir(0, 0, 0, 0, $product, 'product'); diff --git a/htdocs/core/modules/propale/doc/pdf_cyan.modules.php b/htdocs/core/modules/propale/doc/pdf_cyan.modules.php index 1ed76728b92..b8e002196a9 100644 --- a/htdocs/core/modules/propale/doc/pdf_cyan.modules.php +++ b/htdocs/core/modules/propale/doc/pdf_cyan.modules.php @@ -940,13 +940,13 @@ class pdf_cyan extends ModelePDFPropales foreach ($filetomerge->lines as $linefile) { if (!empty($linefile->id) && !empty($linefile->file_name)) { if (!empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) { - if (!empty($conf->product->enabled)) { + if (isModEnabled("product")) { $filetomerge_dir = $conf->product->multidir_output[$entity_product_file].'/'.get_exdir($product->id, 2, 0, 0, $product, 'product').$product->id."/photos"; } elseif (!empty($conf->service->enabled)) { $filetomerge_dir = $conf->service->multidir_output[$entity_product_file].'/'.get_exdir($product->id, 2, 0, 0, $product, 'product').$product->id."/photos"; } } else { - if (!empty($conf->product->enabled)) { + if (isModEnabled("product")) { $filetomerge_dir = $conf->product->multidir_output[$entity_product_file].'/'.get_exdir(0, 0, 0, 0, $product, 'product'); } elseif (!empty($conf->service->enabled)) { $filetomerge_dir = $conf->service->multidir_output[$entity_product_file].'/'.get_exdir(0, 0, 0, 0, $product, 'product'); diff --git a/htdocs/core/modules/rapport/pdf_paiement.class.php b/htdocs/core/modules/rapport/pdf_paiement.class.php index 215987054ce..e4991a5830d 100644 --- a/htdocs/core/modules/rapport/pdf_paiement.class.php +++ b/htdocs/core/modules/rapport/pdf_paiement.class.php @@ -185,14 +185,14 @@ class pdf_paiement $sql .= ", c.code as paiement_code, p.num_paiement as num_payment"; $sql .= ", p.amount as paiement_amount, f.total_ttc as facture_amount"; $sql .= ", pf.amount as pf_amount"; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $sql .= ", ba.ref as bankaccount"; } $sql .= ", p.rowid as prowid"; $sql .= " FROM ".MAIN_DB_PREFIX."paiement as p LEFT JOIN ".MAIN_DB_PREFIX."c_paiement as c ON p.fk_paiement = c.id"; $sql .= ", ".MAIN_DB_PREFIX."facture as f,"; $sql .= " ".MAIN_DB_PREFIX."paiement_facture as pf,"; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $sql .= " ".MAIN_DB_PREFIX."bank as b, ".MAIN_DB_PREFIX."bank_account as ba,"; } $sql .= " ".MAIN_DB_PREFIX."societe as s"; @@ -200,7 +200,7 @@ class pdf_paiement $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; } $sql .= " WHERE f.fk_soc = s.rowid AND pf.fk_facture = f.rowid AND pf.fk_paiement = p.rowid"; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $sql .= " AND p.fk_bank = b.rowid AND b.fk_account = ba.rowid "; } $sql .= " AND f.entity IN (".getEntity('invoice').")"; @@ -223,14 +223,14 @@ class pdf_paiement $sql .= ", c.code as paiement_code, p.num_paiement as num_payment"; $sql .= ", p.amount as paiement_amount, f.total_ttc as facture_amount"; $sql .= ", pf.amount as pf_amount"; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $sql .= ", ba.ref as bankaccount"; } $sql .= ", p.rowid as prowid"; $sql .= " FROM ".MAIN_DB_PREFIX."paiementfourn as p LEFT JOIN ".MAIN_DB_PREFIX."c_paiement as c ON p.fk_paiement = c.id"; $sql .= ", ".MAIN_DB_PREFIX."facture_fourn as f,"; $sql .= " ".MAIN_DB_PREFIX."paiementfourn_facturefourn as pf,"; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $sql .= " ".MAIN_DB_PREFIX."bank as b, ".MAIN_DB_PREFIX."bank_account as ba,"; } $sql .= " ".MAIN_DB_PREFIX."societe as s"; @@ -238,7 +238,7 @@ class pdf_paiement $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; } $sql .= " WHERE f.fk_soc = s.rowid AND pf.fk_facturefourn = f.rowid AND pf.fk_paiementfourn = p.rowid"; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $sql .= " AND p.fk_bank = b.rowid AND b.fk_account = ba.rowid "; } $sql .= " AND f.entity IN (".getEntity('invoice').")"; diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index 681dd5424ea..c641cdf68de 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -193,7 +193,7 @@ if ($nolinesbefore) { // Free line echo ''; // Show radio free line - if ($forceall >= 0 && (!empty($conf->product->enabled) || !empty($conf->service->enabled))) { + if ($forceall >= 0 && (isModEnabled("product") || !empty($conf->service->enabled))) { echo ''; } // Predefined product/service - if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { + if (isModEnabled("product") || !empty($conf->service->enabled)) { if ($forceall >= 0 && $freelines) { echo '
'; } else { @@ -230,7 +230,7 @@ if ($nolinesbefore) { $labelforradio = ''; if (empty($conf->dol_optimize_smallscreen)) { if (empty($senderissupplier)) { - if (!empty($conf->product->enabled) && empty($conf->service->enabled)) { + if (isModEnabled("product") && empty($conf->service->enabled)) { $labelforradio = $langs->trans('PredefinedProductsToSell'); } elseif ((empty($conf->product->enabled) && !empty($conf->service->enabled)) || ($object->element == 'contrat' && empty($conf->global->CONTRACT_SUPPORT_PRODUCTS))) { $labelforradio = $langs->trans('PredefinedServicesToSell'); @@ -238,7 +238,7 @@ if ($nolinesbefore) { $labelforradio = $langs->trans('PredefinedProductsAndServicesToSell'); } } else { - if (!empty($conf->product->enabled) && empty($conf->service->enabled)) { + if (isModEnabled("product") && empty($conf->service->enabled)) { $labelforradio = $langs->trans('PredefinedProductsToPurchase'); } elseif (empty($conf->product->enabled) && !empty($conf->service->enabled)) { $labelforradio = $langs->trans('PredefinedServicesToPurchase'); @@ -336,7 +336,7 @@ if ($nolinesbefore) { print $hookmanager->resPrint; } } - if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { + if (isModEnabled("product") || !empty($conf->service->enabled)) { echo '
'; if (!empty($conf->variants->enabled)) { echo '
'; @@ -446,7 +446,7 @@ if ($nolinesbefore) { ?>
\n"; print ''; } - if ($typeobject == 'propal' && $expedition->origin_id && !empty($conf->propal->enabled)) { + if ($typeobject == 'propal' && $expedition->origin_id && isModEnabled("propal")) { $propal = new Propal($db); $propal->fetch($expedition->origin_id); print ''; diff --git a/htdocs/delivery/class/delivery.class.php b/htdocs/delivery/class/delivery.class.php index 9edc080701b..9af06f87541 100644 --- a/htdocs/delivery/class/delivery.class.php +++ b/htdocs/delivery/class/delivery.class.php @@ -31,7 +31,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/commonincoterm.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php'; -if (!empty($conf->propal->enabled)) { +if (isModEnabled("propal")) { require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php'; } if (!empty($conf->commande->enabled)) { diff --git a/htdocs/don/admin/donation.php b/htdocs/don/admin/donation.php index c56effea73a..9a360f69882 100644 --- a/htdocs/don/admin/donation.php +++ b/htdocs/don/admin/donation.php @@ -310,7 +310,7 @@ print '\n"; print ''; print "\n"; -if (!empty($conf->societe->enabled)) { +if (isModEnabled("societe")) { print ''; print ''; // Company - if (!empty($conf->societe->enabled) && !empty($conf->global->DONATION_USE_THIRDPARTIES)) { + if (isModEnabled("societe") && !empty($conf->global->DONATION_USE_THIRDPARTIES)) { // Thirdparty if ($soc->id > 0) { print ''; @@ -591,7 +591,7 @@ if (!empty($id) && $action == 'edit') { print ""; print "\n"; - if (!empty($conf->societe->enabled) && !empty($conf->global->DONATION_USE_THIRDPARTIES)) { + if (isModEnabled("societe") && !empty($conf->global->DONATION_USE_THIRDPARTIES)) { $company = new Societe($db); print ''; - if (!empty($conf->societe->enabled) && !empty($conf->global->DONATION_USE_THIRDPARTIES)) { + if (isModEnabled("societe") && !empty($conf->global->DONATION_USE_THIRDPARTIES)) { $company = new Societe($db); print ''; // Bank account -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { if ($object->bank_account) { $bankline = new AccountLine($db); $bankline->fetch($object->bank_line); diff --git a/htdocs/don/payment/payment.php b/htdocs/don/payment/payment.php index 80ef94e6213..092f5114141 100644 --- a/htdocs/don/payment/payment.php +++ b/htdocs/don/payment/payment.php @@ -66,7 +66,7 @@ if ($action == 'add_payment') { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Date")), null, 'errors'); $error++; } - if (!empty($conf->banque->enabled) && !(GETPOST("accountid", 'int') > 0)) { + if (isModEnabled("banque") && !(GETPOST("accountid", 'int') > 0)) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("AccountToCredit")), null, 'errors'); $error++; } diff --git a/htdocs/ecm/index_auto.php b/htdocs/ecm/index_auto.php index 90ce79be330..ffc1d1b7dd7 100644 --- a/htdocs/ecm/index_auto.php +++ b/htdocs/ecm/index_auto.php @@ -309,14 +309,14 @@ llxHeader($moreheadcss.$moreheadjs, $langs->trans("ECMArea"), '', '', '', '', $m $rowspan = 0; $sectionauto = array(); if (!empty($conf->global->ECM_AUTO_TREE_ENABLED)) { - if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { + if (isModEnabled("product") || !empty($conf->service->enabled)) { $langs->load("products"); - $rowspan++; $sectionauto[] = array('position'=>10, 'level'=>1, 'module'=>'product', 'test'=>(!empty($conf->product->enabled) || !empty($conf->service->enabled)), 'label'=>$langs->trans("ProductsAndServices"), 'desc'=>$langs->trans("ECMDocsByProducts")); + $rowspan++; $sectionauto[] = array('position'=>10, 'level'=>1, 'module'=>'product', 'test'=>(isModEnabled("product") || !empty($conf->service->enabled)), 'label'=>$langs->trans("ProductsAndServices"), 'desc'=>$langs->trans("ECMDocsByProducts")); } - if (!empty($conf->societe->enabled)) { + if (isModEnabled("societe")) { $rowspan++; $sectionauto[] = array('position'=>20, 'level'=>1, 'module'=>'company', 'test'=>$conf->societe->enabled, 'label'=>$langs->trans("ThirdParties"), 'desc'=>$langs->trans("ECMDocsBy", $langs->transnoentitiesnoconv("ThirdParties"))); } - if (!empty($conf->propal->enabled)) { + if (isModEnabled("propal")) { $rowspan++; $sectionauto[] = array('position'=>30, 'level'=>1, 'module'=>'propal', 'test'=>$conf->propal->enabled, 'label'=>$langs->trans("Proposals"), 'desc'=>$langs->trans("ECMDocsBy", $langs->transnoentitiesnoconv("Proposals"))); } if (!empty($conf->contrat->enabled)) { @@ -363,7 +363,7 @@ if (!empty($conf->global->ECM_AUTO_TREE_ENABLED)) { $langs->load("holiday"); $rowspan++; $sectionauto[] = array('position'=>170, 'level'=>1, 'module'=>'holiday', 'test'=>$conf->holiday->enabled, 'label'=>$langs->trans("Holidays"), 'desc'=>$langs->trans("ECMDocsBy", $langs->transnoentitiesnoconv("Holidays"))); } - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $langs->load("banks"); $rowspan++; $sectionauto[] = array('position'=>180, 'level'=>1, 'module'=>'banque', 'test'=>$conf->banque->enabled, 'label'=>$langs->trans("BankAccount"), 'desc'=>$langs->trans("ECMDocsBy", $langs->transnoentitiesnoconv("BankAccount"))); $rowspan++; $sectionauto[] = array('position'=>190, 'level'=>1, 'module'=>'chequereceipt', 'test'=>$conf->banque->enabled, 'label'=>$langs->trans("CheckReceipt"), 'desc'=>$langs->trans("ECMDocsBy", $langs->transnoentitiesnoconv("CheckReceipt"))); diff --git a/htdocs/ecm/search.php b/htdocs/ecm/search.php index f348e0835e7..f52ea3233ab 100644 --- a/htdocs/ecm/search.php +++ b/htdocs/ecm/search.php @@ -113,13 +113,13 @@ $userstatic = new User($db); // Ajout rubriques automatiques $rowspan = 0; $sectionauto = array(); -if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { - $langs->load("products"); $rowspan++; $sectionauto[] = array('level'=>1, 'module'=>'product', 'test'=>(!empty($conf->product->enabled) || !empty($conf->service->enabled)), 'label'=>$langs->trans("ProductsAndServices"), 'desc'=>$langs->trans("ECMDocsByProducts")); +if (isModEnabled("product") || !empty($conf->service->enabled)) { + $langs->load("products"); $rowspan++; $sectionauto[] = array('level'=>1, 'module'=>'product', 'test'=>(isModEnabled("product") || !empty($conf->service->enabled)), 'label'=>$langs->trans("ProductsAndServices"), 'desc'=>$langs->trans("ECMDocsByProducts")); } -if (!empty($conf->societe->enabled)) { +if (isModEnabled("societe")) { $rowspan++; $sectionauto[] = array('level'=>1, 'module'=>'company', 'test'=>$conf->societe->enabled, 'label'=>$langs->trans("ThirdParties"), 'desc'=>$langs->trans("ECMDocsBy", $langs->transnoentitiesnoconv("ThirdParties"))); } -if (!empty($conf->propal->enabled)) { +if (isModEnabled("propal")) { $rowspan++; $sectionauto[] = array('level'=>1, 'module'=>'propal', 'test'=>$conf->propal->enabled, 'label'=>$langs->trans("Proposals"), 'desc'=>$langs->trans("ECMDocsBy", $langs->transnoentitiesnoconv("Proposals"))); } if (!empty($conf->contrat->enabled)) { @@ -155,7 +155,7 @@ if (!empty($conf->expensereport->enabled)) { if (!empty($conf->holiday->enabled)) { $langs->load("holiday"); $rowspan++; $sectionauto[] = array('level'=>1, 'module'=>'holiday', 'test'=>$conf->holiday->enabled, 'label'=>$langs->trans("Holidays"), 'desc'=>$langs->trans("ECMDocsBy", $langs->transnoentitiesnoconv("Holidays"))); } -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { $langs->load("banks"); $rowspan++; $sectionauto[] = array('level'=>1, 'module'=>'banque', 'test'=>$conf->banque->enabled, 'label'=>$langs->trans("BankAccount"), 'desc'=>$langs->trans("ECMDocsBy", $langs->transnoentitiesnoconv("BankAccount"))); } if (!empty($conf->mrp->enabled)) { diff --git a/htdocs/expedition/card.php b/htdocs/expedition/card.php index 52b78aa1e5c..30806231916 100644 --- a/htdocs/expedition/card.php +++ b/htdocs/expedition/card.php @@ -47,10 +47,10 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php'; require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; -if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { +if (isModEnabled("product") || !empty($conf->service->enabled)) { require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; } -if (!empty($conf->propal->enabled)) { +if (isModEnabled("propal")) { require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php'; } if (!empty($conf->productbatch->enabled)) { @@ -878,7 +878,7 @@ if ($action == 'create') { if ($origin == 'commande' && !empty($conf->commande->enabled)) { print $langs->trans("RefOrder"); } - if ($origin == 'propal' && !empty($conf->propal->enabled)) { + if ($origin == 'propal' && isModEnabled("propal")) { print $langs->trans("RefProposal"); } print '\n"; print ''; } - if ($typeobject == 'propal' && $object->$typeobject->id && !empty($conf->propal->enabled)) { + if ($typeobject == 'propal' && $object->$typeobject->id && isModEnabled("propal")) { print ''; print '\n"; print ''; } - if ($typeobject == 'propal' && $object->$typeobject->id && !empty($conf->propal->enabled)) { + if ($typeobject == 'propal' && $object->$typeobject->id && isModEnabled("propal")) { print ''; print ''; print ''; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print ''; } print ''; @@ -1983,7 +1983,7 @@ if ($action == 'create') { $labeltype = $langs->trans("PaymentType".$objp->payment_code) != ("PaymentType".$objp->payment_code) ? $langs->trans("PaymentType".$objp->payment_code) : $objp->payment_type; print "\n"; // Bank account - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $bankaccountstatic->id = $objp->baid; $bankaccountstatic->ref = $objp->baref; $bankaccountstatic->label = $objp->baref; @@ -2767,7 +2767,7 @@ if ($action != 'create' && $action != 'edit' && $action != 'editline') { } // If bank module is used - if ($user->rights->expensereport->to_paid && !empty($conf->banque->enabled) && $object->status == ExpenseReport::STATUS_APPROVED) { + if ($user->rights->expensereport->to_paid && isModEnabled("banque") && $object->status == ExpenseReport::STATUS_APPROVED) { // Pay if ($remaintopay == 0) { print '
'.$langs->trans('DoPayment').'
'; diff --git a/htdocs/expensereport/class/paymentexpensereport.class.php b/htdocs/expensereport/class/paymentexpensereport.class.php index f7ff6cf7e9c..e871cba86b3 100644 --- a/htdocs/expensereport/class/paymentexpensereport.class.php +++ b/htdocs/expensereport/class/paymentexpensereport.class.php @@ -516,7 +516,7 @@ class PaymentExpenseReport extends CommonObject $error = 0; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { include_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; $acc = new Account($this->db); diff --git a/htdocs/expensereport/payment/card.php b/htdocs/expensereport/payment/card.php index 847c059a9c6..c24689a9d69 100644 --- a/htdocs/expensereport/payment/card.php +++ b/htdocs/expensereport/payment/card.php @@ -26,7 +26,7 @@ require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php'; require_once DOL_DOCUMENT_ROOT.'/expensereport/class/paymentexpensereport.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/modules/expensereport/modules_expensereport.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/expensereport.lib.php'; -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; } @@ -120,7 +120,7 @@ print '\n"; print ''; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print ''; print ''; print ''; // Bank Account - if (!empty($conf->global->BANK_ASK_PAYMENT_BANK_DURING_SUPPLIER_ORDER) && !empty($conf->banque->enabled)) { + if (!empty($conf->global->BANK_ASK_PAYMENT_BANK_DURING_SUPPLIER_ORDER) && isModEnabled("banque")) { $langs->load("bank"); print '
'; print $langs->trans('BankAccount'); @@ -660,7 +660,7 @@ if ($id > 0) { print '
'; $nbcols = 3; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $nbcols++; } @@ -695,7 +695,7 @@ if ($id > 0) { print '
'.$langs->trans("RefPayment").''.$langs->trans("Date").''.$langs->trans("Type").''.$langs->trans('BankAccount').''.$langs->trans("Amount").''.dol_print_date($db->jdate($objp->dp), 'day')."".$labeltype.' '.$objp->num_payment."'.dol_escape_htmltag($obj->num_payment).''; $accountlinestatic->id = $obj->fk_bank; @@ -258,7 +258,7 @@ if (!empty($conf->tax->enabled) && $user->rights->tax->charges->lire) { print '    
'.$langs->trans("ContactForProposals").''; print $object->ref_propal ? $object->ref_propal : (''.$langs->trans("NoContactForAnyProposal").''); print '
'.$langs->trans("ContactForProposals").''; print $object->ref_propal ? $object->ref_propal : $langs->trans("NoContactForAnyProposal"); print '
'; - if (!empty($conf->expedition->enabled)) { + if (isModEnabled("expedition")) { print $langs->trans("ContactForOrdersOrShipments"); } else { print $langs->trans("ContactForOrders"); } print ''; $none = $langs->trans("NoContactForAnyOrder"); - if (!empty($conf->expedition->enabled)) { + if (isModEnabled("expedition")) { $none = $langs->trans("NoContactForAnyOrderOrShipments"); } print $object->ref_commande ? $object->ref_commande : $none; diff --git a/htdocs/contact/consumption.php b/htdocs/contact/consumption.php index f19c3e03684..b7300c4ed78 100644 --- a/htdocs/contact/consumption.php +++ b/htdocs/contact/consumption.php @@ -154,7 +154,7 @@ print '
' . $langs->trans('MarginOnProducts') . '
' . $langs->trans('TotalMargin') . '' . price($marginInfo['pv_total']) . '
- product->enabled) || !empty($conf->service->enabled)) { ?> + service->enabled)) { ?> diff --git a/htdocs/core/tpl/objectline_edit.tpl.php b/htdocs/core/tpl/objectline_edit.tpl.php index c59949d5fb7..83e6ff2da7c 100644 --- a/htdocs/core/tpl/objectline_edit.tpl.php +++ b/htdocs/core/tpl/objectline_edit.tpl.php @@ -290,7 +290,7 @@ $coldisplay++; ?> - product->enabled) || !empty($conf->service->enabled)) { ?> + service->enabled)) { ?> diff --git a/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php b/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php index cc6a1168c32..20eb56d8b56 100644 --- a/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php +++ b/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php @@ -117,7 +117,7 @@ class InterfaceWorkflowManager extends DolibarrTriggers // Order classify billed proposal if ($action == 'ORDER_CLASSIFY_BILLED') { dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); - if (!empty($conf->propal->enabled) && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_ORDER_CLASSIFY_BILLED_PROPAL)) { + if (isModEnabled("propal") && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_ORDER_CLASSIFY_BILLED_PROPAL)) { $object->fetchObjectLinked('', 'propal', $object->id, $object->element); if (!empty($object->linkedObjects)) { $totalonlinkedelements = 0; @@ -161,7 +161,7 @@ class InterfaceWorkflowManager extends DolibarrTriggers } // Second classify billed the proposal. - if (!empty($conf->propal->enabled) && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_INVOICE_CLASSIFY_BILLED_PROPAL)) { + if (isModEnabled("propal") && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_INVOICE_CLASSIFY_BILLED_PROPAL)) { $object->fetchObjectLinked('', 'propal', $object->id, $object->element); if (!empty($object->linkedObjects)) { $totalonlinkedelements = 0; @@ -179,7 +179,7 @@ class InterfaceWorkflowManager extends DolibarrTriggers } } - if (!empty($conf->expedition->enabled) && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_SHIPPING_CLASSIFY_CLOSED_INVOICE)) { + if (isModEnabled("expedition") && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_SHIPPING_CLASSIFY_CLOSED_INVOICE)) { /** @var Facture $object */ $object->fetchObjectLinked('', 'shipping', $object->id, $object->element); @@ -244,7 +244,7 @@ class InterfaceWorkflowManager extends DolibarrTriggers } // Then set reception to "Billed" if WORKFLOW_BILL_ON_RECEPTION is set - if (!empty($conf->reception->enabled) && !empty($conf->global->WORKFLOW_BILL_ON_RECEPTION)) { + if (isModEnabled("reception") && !empty($conf->global->WORKFLOW_BILL_ON_RECEPTION)) { $object->fetchObjectLinked('', 'reception', $object->id, $object->element); if (!empty($object->linkedObjects)) { $totalonlinkedelements = 0; @@ -296,7 +296,7 @@ class InterfaceWorkflowManager extends DolibarrTriggers if (($action == 'SHIPPING_VALIDATE') || ($action == 'SHIPPING_CLOSED')) { dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); - if (!empty($conf->commande->enabled) && !empty($conf->expedition->enabled) && !empty($conf->workflow->enabled) && + if (!empty($conf->commande->enabled) && isModEnabled("expedition") && !empty($conf->workflow->enabled) && ( (!empty($conf->global->WORKFLOW_ORDER_CLASSIFY_SHIPPED_SHIPPING) && ($action == 'SHIPPING_VALIDATE')) || (!empty($conf->global->WORKFLOW_ORDER_CLASSIFY_SHIPPED_SHIPPING_CLOSED) && ($action == 'SHIPPING_CLOSED')) @@ -365,7 +365,7 @@ class InterfaceWorkflowManager extends DolibarrTriggers if (($action == 'RECEPTION_VALIDATE') || ($action == 'RECEPTION_CLOSED')) { dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); - if ((!empty($conf->fournisseur->enabled) || !empty($conf->supplier_order->enabled)) && !empty($conf->reception->enabled) && !empty($conf->workflow->enabled) && + if ((!empty($conf->fournisseur->enabled) || !empty($conf->supplier_order->enabled)) && isModEnabled("reception") && !empty($conf->workflow->enabled) && ( (!empty($conf->global->WORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION) && ($action == 'RECEPTION_VALIDATE')) || (!empty($conf->global->WORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED) && ($action == 'RECEPTION_CLOSED')) diff --git a/htdocs/delivery/card.php b/htdocs/delivery/card.php index dba3d0de437..667ab889547 100644 --- a/htdocs/delivery/card.php +++ b/htdocs/delivery/card.php @@ -34,7 +34,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/sendings.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; -if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { +if (isModEnabled("product") || !empty($conf->service->enabled)) { require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; } if (!empty($conf->expedition_bon->enabled)) { @@ -312,7 +312,7 @@ if ($action == 'create') { // Create. Seems to no be used $objectsrc = new Commande($db); $objectsrc->fetch($expedition->origin_id); } - if ($typeobject == 'propal' && $expedition->origin_id > 0 && !empty($conf->propal->enabled)) { + if ($typeobject == 'propal' && $expedition->origin_id > 0 && isModEnabled("propal")) { $objectsrc = new Propal($db); $objectsrc->fetch($expedition->origin_id); } @@ -409,7 +409,7 @@ if ($action == 'create') { // Create. Seems to no be used print "
'.$langs->trans("RefProposal").''.$langs->trans("Value")."
'; print $langs->trans("DonationUseThirdparties"); diff --git a/htdocs/don/card.php b/htdocs/don/card.php index 30a3ec24c6c..8f7ea3be1df 100644 --- a/htdocs/don/card.php +++ b/htdocs/don/card.php @@ -211,7 +211,7 @@ if (empty($reshook)) { $error = 0; - if (!empty($conf->societe->enabled) && !empty($conf->global->DONATION_USE_THIRDPARTIES) && !(GETPOST("socid", 'int') > 0)) { + if (isModEnabled("societe") && !empty($conf->global->DONATION_USE_THIRDPARTIES) && !(GETPOST("socid", 'int') > 0)) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ThirdParty")), null, 'errors'); $action = "create"; $error++; @@ -402,7 +402,7 @@ if ($action == 'create') { print '
'.$langs->trans('Ref').''.$langs->trans('Draft').'
'.$langs->trans('ThirdParty').'
'.$langs->trans("ThirdParty").''; @@ -756,7 +756,7 @@ if (!empty($id) && $action != 'edit') { print yn($object->public); print '
'.$langs->trans("ThirdParty").''; diff --git a/htdocs/don/class/paymentdonation.class.php b/htdocs/don/class/paymentdonation.class.php index 6de83f5570e..e4928ac9363 100644 --- a/htdocs/don/class/paymentdonation.class.php +++ b/htdocs/don/class/paymentdonation.class.php @@ -574,7 +574,7 @@ class PaymentDonation extends CommonObject $error = 0; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; $acc = new Account($this->db); diff --git a/htdocs/don/payment/card.php b/htdocs/don/payment/card.php index 363ef6d34ef..1b4ebaaf88e 100644 --- a/htdocs/don/payment/card.php +++ b/htdocs/don/payment/card.php @@ -27,7 +27,7 @@ require_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php'; require_once DOL_DOCUMENT_ROOT.'/don/class/paymentdonation.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/modules/facture/modules_facture.php'; -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; } @@ -124,7 +124,7 @@ print '
'.$langs->trans('Amount').''.price($object->amount, 0, $ print '
'.$langs->trans('Note').''.nl2br($object->note_public).'
'; @@ -1718,7 +1718,7 @@ if ($action == 'create') { $objectsrc = new Commande($db); $objectsrc->fetch($object->$typeobject->id); } - if ($typeobject == 'propal' && $object->$typeobject->id && !empty($conf->propal->enabled)) { + if ($typeobject == 'propal' && $object->$typeobject->id && isModEnabled("propal")) { $objectsrc = new Propal($db); $objectsrc->fetch($object->$typeobject->id); } @@ -1787,7 +1787,7 @@ if ($action == 'create') { print "
'; print $langs->trans("RefProposal").''; diff --git a/htdocs/expedition/class/expedition.class.php b/htdocs/expedition/class/expedition.class.php index 9ce876eb039..5df7108e895 100644 --- a/htdocs/expedition/class/expedition.class.php +++ b/htdocs/expedition/class/expedition.class.php @@ -37,7 +37,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; require_once DOL_DOCUMENT_ROOT."/core/class/commonobjectline.class.php"; require_once DOL_DOCUMENT_ROOT.'/core/class/commonincoterm.class.php'; -if (!empty($conf->propal->enabled)) { +if (isModEnabled("propal")) { require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php'; } if (!empty($conf->commande->enabled)) { diff --git a/htdocs/expedition/contact.php b/htdocs/expedition/contact.php index 669c6f8e56d..112d35a63aa 100644 --- a/htdocs/expedition/contact.php +++ b/htdocs/expedition/contact.php @@ -57,7 +57,7 @@ if ($id > 0 || !empty($ref)) { $objectsrc = new Commande($db); $objectsrc->fetch($object->$typeobject->id); } - if ($typeobject == 'propal' && $object->$typeobject->id && !empty($conf->propal->enabled)) { + if ($typeobject == 'propal' && $object->$typeobject->id && isModEnabled("propal")) { $objectsrc = new Propal($db); $objectsrc->fetch($object->$typeobject->id); } @@ -206,7 +206,7 @@ if ($id > 0 || !empty($ref)) { print "
'; $objectsrc = new Propal($db); $objectsrc->fetch($object->$typeobject->id); diff --git a/htdocs/expedition/note.php b/htdocs/expedition/note.php index e391d5be180..c8fc0ff35be 100644 --- a/htdocs/expedition/note.php +++ b/htdocs/expedition/note.php @@ -55,7 +55,7 @@ if ($id > 0 || !empty($ref)) { $objectsrc = new Commande($db); $objectsrc->fetch($object->$typeobject->id); } - if ($typeobject == 'propal' && $object->$typeobject->id && !empty($conf->propal->enabled)) { + if ($typeobject == 'propal' && $object->$typeobject->id && isModEnabled("propal")) { $objectsrc = new Propal($db); $objectsrc->fetch($object->$typeobject->id); } diff --git a/htdocs/expedition/shipment.php b/htdocs/expedition/shipment.php index bf352ebe5da..c42ae6ec296 100644 --- a/htdocs/expedition/shipment.php +++ b/htdocs/expedition/shipment.php @@ -40,10 +40,10 @@ if (!empty($conf->project->enabled)) { if (!empty($conf->stock->enabled)) { require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php'; } -if (!empty($conf->propal->enabled)) { +if (isModEnabled("propal")) { require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php'; } -if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { +if (isModEnabled("product") || !empty($conf->service->enabled)) { require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; } diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php index 1da36a72e32..650457cbcc7 100644 --- a/htdocs/expensereport/card.php +++ b/htdocs/expensereport/card.php @@ -1930,7 +1930,7 @@ if ($action == 'create') { // List of payments already done $nbcols = 3; $nbrows = 0; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $nbrows++; $nbcols++; } @@ -1941,7 +1941,7 @@ if ($action == 'create') { print ''.$langs->trans('Payments').''.$langs->trans('Date').''.$langs->trans('Type').''.$langs->trans('BankAccount').''.$langs->trans('Amount').'".$labeltype.' '.$objp->num_payment."
'.$langs->trans('Note').''.nl2 $disable_delete = 0; // Bank account -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { if ($object->bank_account) { $bankline = new AccountLine($db); $bankline->fetch($object->bank_line); diff --git a/htdocs/expensereport/payment/list.php b/htdocs/expensereport/payment/list.php index 3f3e017612d..5a08c30f636 100644 --- a/htdocs/expensereport/payment/list.php +++ b/htdocs/expensereport/payment/list.php @@ -103,7 +103,7 @@ $arrayfields = array( 'u.login' =>array('label'=>"User", 'checked'=>1, 'position'=>30), 'c.libelle' =>array('label'=>"Type", 'checked'=>1, 'position'=>40), 'pndf.num_payment' =>array('label'=>"Numero", 'checked'=>1, 'position'=>50, 'tooltip'=>"ChequeOrTransferNumber"), - 'ba.label' =>array('label'=>"Account", 'checked'=>1, 'position'=>60, 'enable'=>(!empty($conf->banque->enabled))), + 'ba.label' =>array('label'=>"Account", 'checked'=>1, 'position'=>60, 'enable'=>(isModEnabled("banque"))), 'pndf.amount' =>array('label'=>"Amount", 'checked'=>1, 'position'=>70), ); $arrayfields = dol_sort_array($arrayfields, 'position'); diff --git a/htdocs/expensereport/payment/payment.php b/htdocs/expensereport/payment/payment.php index 3676f663ce8..74e0c63151b 100644 --- a/htdocs/expensereport/payment/payment.php +++ b/htdocs/expensereport/payment/payment.php @@ -76,7 +76,7 @@ if ($action == 'add_payment') { $error++; } - if (!empty($conf->banque->enabled) && !($accountid > 0)) { + if (isModEnabled("banque") && !($accountid > 0)) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("AccountToDebit")), null, 'errors'); $error++; } @@ -245,7 +245,7 @@ if ($action == 'create' || empty($action)) { print "
'.$langs->trans('AccountToDebit').''; diff --git a/htdocs/fichinter/card.php b/htdocs/fichinter/card.php index d03cb11a7e0..d3adde8c21a 100644 --- a/htdocs/fichinter/card.php +++ b/htdocs/fichinter/card.php @@ -1645,7 +1645,7 @@ if ($action == 'create') { } // Proposal - if ($conf->service->enabled && !empty($conf->propal->enabled) && $object->statut > Fichinter::STATUS_DRAFT) { + if ($conf->service->enabled && isModEnabled("propal") && $object->statut > Fichinter::STATUS_DRAFT) { $langs->load("propal"); if ($object->statut < Fichinter::STATUS_BILLED) { if ($user->rights->propal->creer) { diff --git a/htdocs/fourn/card.php b/htdocs/fourn/card.php index fb89cd2c455..2f44253579a 100644 --- a/htdocs/fourn/card.php +++ b/htdocs/fourn/card.php @@ -514,7 +514,7 @@ if ($object->id > 0) { /* * List of products */ - if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { + if (isModEnabled("product") || !empty($conf->service->enabled)) { $langs->load("products"); //Query from product/liste.php $sql = 'SELECT p.rowid, p.ref, p.label, p.fk_product_type, p.entity, p.tosell as status, p.tobuy as status_buy, p.tobatch as status_batch,'; diff --git a/htdocs/fourn/class/api_supplier_invoices.class.php b/htdocs/fourn/class/api_supplier_invoices.class.php index 17146eecd35..5cc3e5592a2 100644 --- a/htdocs/fourn/class/api_supplier_invoices.class.php +++ b/htdocs/fourn/class/api_supplier_invoices.class.php @@ -433,7 +433,7 @@ class SupplierInvoices extends DolibarrApi throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { if (empty($accountid)) { throw new RestException(400, 'Bank account ID is mandatory'); } @@ -482,7 +482,7 @@ class SupplierInvoices extends DolibarrApi throw new RestException(400, 'Payment error : '.$paiement->error); } - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $result = $paiement->addPaymentToBank(DolibarrApiAccess::$user, 'payment_supplier', '(SupplierInvoicePayment)', $accountid, $chqemetteur, $chqbank); if ($result < 0) { $this->db->rollback(); diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index 01cae8860d6..8e9c340b1df 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -46,7 +46,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; if (!empty($conf->supplier_proposal->enabled)) { require_once DOL_DOCUMENT_ROOT.'/supplier_proposal/class/supplier_proposal.class.php'; } -if (!empty($conf->product->enabled)) { +if (isModEnabled("product")) { require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; } if (!empty($conf->project->enabled)) { @@ -1742,7 +1742,7 @@ if ($action == 'create') { print '
'.$langs->trans('BankAccount').''; print img_picto('', 'bank_account', 'class="paddingrightonly"'); @@ -2216,7 +2216,7 @@ if ($action == 'create') { } // Bank Account - if (!empty($conf->global->BANK_ASK_PAYMENT_BANK_DURING_SUPPLIER_ORDER) && !empty($conf->banque->enabled)) { + if (!empty($conf->global->BANK_ASK_PAYMENT_BANK_DURING_SUPPLIER_ORDER) && isModEnabled("banque")) { print '
'; print ''; - } elseif (!empty($conf->reception->enabled)) { + } elseif (isModEnabled("reception")) { print ''; } @@ -1218,7 +1218,7 @@ if ($id > 0 || !empty($ref)) { print ''; // Reception ref - if (!empty($conf->reception->enabled)) { + if (isModEnabled("reception")) { print ''; - } elseif (!empty($conf->reception->enabled)) { + } elseif (isModEnabled("reception")) { print ''; // Bank Account - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print ''; @@ -3095,7 +3095,7 @@ if ($action == 'create') { } // Bank Account - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print '
'; print $langs->trans('BankAccount'); diff --git a/htdocs/fourn/commande/dispatch.php b/htdocs/fourn/commande/dispatch.php index c20768e8f38..2fb86bdd025 100644 --- a/htdocs/fourn/commande/dispatch.php +++ b/htdocs/fourn/commande/dispatch.php @@ -1191,7 +1191,7 @@ if ($id > 0 || !empty($ref)) { // Status if (!empty($conf->global->SUPPLIER_ORDER_USE_DISPATCH_STATUS) && empty($reception->rowid)) { print ''.$langs->trans("Status").'
'; if (!empty($objp->fk_reception)) { $reception = new Reception($db); @@ -1335,7 +1335,7 @@ if ($id > 0 || !empty($ref)) { } } print ''; if (!empty($reception->id)) { print $reception->getLibStatut(5); diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index bd06da5f987..dbb20c72d77 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -45,7 +45,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/fourn.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; -if (!empty($conf->product->enabled)) { +if (isModEnabled("product")) { require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php'; } @@ -2401,7 +2401,7 @@ if ($action == 'create') { print '
'.$langs->trans('BankAccount').''; print img_picto('', 'bank_account', 'class="pictofixedwidth"').$form->select_comptes((GETPOSTISSET('fk_account') ?GETPOST('fk_account', 'alpha') : $fk_account), 'fk_account', 0, '', 1, '', 0, 'maxwidth200 widthcentpercentminusx', 1); print '
'; print ''; print ''; print ''; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print ''; } print ''; @@ -3316,7 +3316,7 @@ if ($action == 'create') { print ''; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $bankaccountstatic->id = $objp->baid; $bankaccountstatic->ref = $objp->baref; $bankaccountstatic->label = $objp->baref; diff --git a/htdocs/fourn/facture/paiement.php b/htdocs/fourn/facture/paiement.php index 832e93ff026..09507929daf 100644 --- a/htdocs/fourn/facture/paiement.php +++ b/htdocs/fourn/facture/paiement.php @@ -224,7 +224,7 @@ if (empty($reshook)) { $error++; } - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { // If bank module is on, account is required to enter a payment if (GETPOST('accountid') <= 0) { setEventMessages($langs->transnoentities('ErrorFieldRequired', $langs->transnoentities('AccountToCredit')), null, 'errors'); @@ -504,7 +504,7 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie print ''; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print ''; // Bank account - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print ''; diff --git a/htdocs/loan/class/paymentloan.class.php b/htdocs/loan/class/paymentloan.class.php index ae31a8314aa..3ce8af01790 100644 --- a/htdocs/loan/class/paymentloan.class.php +++ b/htdocs/loan/class/paymentloan.class.php @@ -497,7 +497,7 @@ class PaymentLoan extends CommonObject $error = 0; $this->db->begin(); - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; $acc = new Account($this->db); diff --git a/htdocs/loan/payment/card.php b/htdocs/loan/payment/card.php index 198025215b7..8f7ad7da44c 100644 --- a/htdocs/loan/payment/card.php +++ b/htdocs/loan/payment/card.php @@ -24,7 +24,7 @@ require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/loan/class/loan.class.php'; require_once DOL_DOCUMENT_ROOT.'/loan/class/paymentloan.class.php'; -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; } @@ -129,7 +129,7 @@ print ''; // Bank account -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { if ($payment->bank_account) { $bankline = new AccountLine($db); $bankline->fetch($payment->bank_line); diff --git a/htdocs/loan/payment/payment.php b/htdocs/loan/payment/payment.php index 113c1151e24..c20c3978571 100644 --- a/htdocs/loan/payment/payment.php +++ b/htdocs/loan/payment/payment.php @@ -105,7 +105,7 @@ if ($action == 'add_payment') { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Date")), null, 'errors'); $error++; } - if (!empty($conf->banque->enabled) && !GETPOST('accountid', 'int') > 0) { + if (isModEnabled("banque") && !GETPOST('accountid', 'int') > 0) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("AccountToCredit")), null, 'errors'); $error++; } diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 675d7273c51..23699875474 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -2440,7 +2440,7 @@ function printDropdownQuickadd() "title" => "MenuNewThirdParty@companies", "name" => "ThirdParty@companies", "picto" => "object_company", - "activation" => !empty($conf->societe->enabled) && $user->hasRight("societe", "write"), // vs hooking + "activation" => isModEnabled("societe") && $user->hasRight("societe", "write"), // vs hooking "position" => 10, ), array( @@ -2448,7 +2448,7 @@ function printDropdownQuickadd() "title" => "NewContactAddress@companies", "name" => "Contact@companies", "picto" => "object_contact", - "activation" => !empty($conf->societe->enabled) && $user->hasRight("societe", "contact", "write"), // vs hooking + "activation" => isModEnabled("societe") && $user->hasRight("societe", "contact", "write"), // vs hooking "position" => 20, ), array( @@ -2456,7 +2456,7 @@ function printDropdownQuickadd() "title" => "NewPropal@propal", "name" => "Proposal@propal", "picto" => "object_propal", - "activation" => !empty($conf->propal->enabled) && $user->hasRight("propale", "write"), // vs hooking + "activation" => isModEnabled("propal") && $user->hasRight("propale", "write"), // vs hooking "position" => 30, ), @@ -2513,7 +2513,7 @@ function printDropdownQuickadd() "title" => "NewProduct@products", "name" => "Product@products", "picto" => "object_product", - "activation" => !empty($conf->product->enabled) && $user->hasRight("produit", "write"), // vs hooking + "activation" => isModEnabled("product") && $user->hasRight("produit", "write"), // vs hooking "position" => 100, ), array( diff --git a/htdocs/paybox/admin/paybox.php b/htdocs/paybox/admin/paybox.php index 710cef4f25c..f651ba43760 100644 --- a/htdocs/paybox/admin/paybox.php +++ b/htdocs/paybox/admin/paybox.php @@ -226,7 +226,7 @@ print '
'.$langs->trans("Example").': '.$mysoc->n print ''; -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { print ''; -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { print '
'; print $langs->trans('BankAccount'); @@ -3250,7 +3250,7 @@ if ($action == 'create') { if (!empty($conf->project->enabled)) { $nbrows++; } - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $nbrows++; $nbcols++; } if (!empty($conf->incoterm->enabled)) { @@ -3291,7 +3291,7 @@ if ($action == 'create') { print ''.($object->type == FactureFournisseur::TYPE_CREDIT_NOTE ? $langs->trans("PaymentsBack") : $langs->trans('Payments')).''.$langs->trans('Date').''.$langs->trans('Type').''.$langs->trans('BankAccount').''.$langs->trans('Amount').''; print $form->form_modes_reglement(null, $objp->paiement_type, 'none').' '.$objp->num_payment; print '
'.$langs->trans('PaymentMode').''; $form->select_types_paiements(!GETPOST('paiementid') ? $obj->fk_mode_reglement : GETPOST('paiementid'), 'paiementid'); print '
'.$langs->trans('Account').''; print img_picto('', 'bank_account', 'class="pictofixedwidth"'); print $form->select_comptes(empty($accountid) ? $obj->fk_account : $accountid, 'accountid', 0, '', 2, '', 0, 'widthcentpercentminusx maxwidth500', 1); diff --git a/htdocs/fourn/paiement/card.php b/htdocs/fourn/paiement/card.php index 3c2c864346a..d9144b3a83f 100644 --- a/htdocs/fourn/paiement/card.php +++ b/htdocs/fourn/paiement/card.php @@ -220,7 +220,7 @@ if ($result > 0) { $allow_delete = 1; // Bank account - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { if ($object->fk_account) { $bankline = new AccountLine($db); $bankline->fetch($object->bank_line); diff --git a/htdocs/fourn/paiement/document.php b/htdocs/fourn/paiement/document.php index a8a41b3fde6..58d04d097d5 100644 --- a/htdocs/fourn/paiement/document.php +++ b/htdocs/fourn/paiement/document.php @@ -124,7 +124,7 @@ if ($object->id > 0) { $allow_delete = 1; // Bank account - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { if ($object->fk_account) { $bankline = new AccountLine($db); $bankline->fetch($object->bank_line); diff --git a/htdocs/fourn/paiement/list.php b/htdocs/fourn/paiement/list.php index 13812e3595f..edffba6a7a8 100644 --- a/htdocs/fourn/paiement/list.php +++ b/htdocs/fourn/paiement/list.php @@ -103,7 +103,7 @@ $arrayfields = array( 's.nom' =>array('label'=>"ThirdParty", 'checked'=>1, 'position'=>30), 'c.libelle' =>array('label'=>"Type", 'checked'=>1, 'position'=>40), 'p.num_paiement' =>array('label'=>"Numero", 'checked'=>1, 'position'=>50, 'tooltip'=>"ChequeOrTransferNumber"), - 'ba.label' =>array('label'=>"Account", 'checked'=>1, 'position'=>60, 'enable'=>(!empty($conf->banque->enabled))), + 'ba.label' =>array('label'=>"Account", 'checked'=>1, 'position'=>60, 'enable'=>(isModEnabled("banque"))), 'p.amount' =>array('label'=>"Amount", 'checked'=>1, 'position'=>70), ); $arrayfields = dol_sort_array($arrayfields, 'position'); diff --git a/htdocs/install/upgrade2.php b/htdocs/install/upgrade2.php index 66200898e95..a9e48c96bf3 100644 --- a/htdocs/install/upgrade2.php +++ b/htdocs/install/upgrade2.php @@ -2037,7 +2037,7 @@ function migrate_modeles($db, $langs, $conf) } } - if (!empty($conf->expedition->enabled)) { + if (isModEnabled("expedition")) { include_once DOL_DOCUMENT_ROOT.'/core/modules/expedition/modules_expedition.php'; $modellist = ModelePDFExpedition::liste_modeles($db); if (count($modellist) == 0) { diff --git a/htdocs/loan/card.php b/htdocs/loan/card.php index f3d83a1d37d..d209c64d088 100644 --- a/htdocs/loan/card.php +++ b/htdocs/loan/card.php @@ -274,7 +274,7 @@ if ($action == 'create') { print '
'.$langs->trans("Label").'
'.$langs->trans("Account").''; $form->select_comptes(GETPOST("accountid"), "accountid", 0, "courant=1", 1); // Show list of bank account with courant print '
'.$langs->trans('NotePrivate').''.nl2br($payment->note_p print '
'.$langs->trans('NotePublic').''.nl2br($payment->note_public).'
'; print $langs->trans("BankAccount").''; $form->select_comptes($conf->global->PAYBOX_BANK_ACCOUNT_FOR_PAYMENTS, 'PAYBOX_BANK_ACCOUNT_FOR_PAYMENTS', 0, '', 1); diff --git a/htdocs/paypal/admin/paypal.php b/htdocs/paypal/admin/paypal.php index 197676d74e7..d5142c851d9 100644 --- a/htdocs/paypal/admin/paypal.php +++ b/htdocs/paypal/admin/paypal.php @@ -244,7 +244,7 @@ print ''.$langs->trans("Example").': '.$mysoc->name.''; print '
'; print $langs->trans("BankAccount").''; print img_picto('', 'bank_account').' '; diff --git a/htdocs/product/card.php b/htdocs/product/card.php index f0c765e59e9..ed921208624 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -54,7 +54,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/modules/product/modules_product.class.php'; -if (!empty($conf->propal->enabled)) { +if (isModEnabled("propal")) { require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php'; } if (isModEnabled('facture')) { @@ -136,14 +136,14 @@ if ($id > 0 || !empty($ref)) { if ($result < 0) { dol_print_error($db, $object->error, $object->errors); } - if (!empty($conf->product->enabled)) { + if (isModEnabled("product")) { $upload_dir = $conf->product->multidir_output[$object->entity].'/'.get_exdir(0, 0, 0, 0, $object, 'product').dol_sanitizeFileName($object->ref); } elseif (!empty($conf->service->enabled)) { $upload_dir = $conf->service->multidir_output[$object->entity].'/'.get_exdir(0, 0, 0, 0, $object, 'product').dol_sanitizeFileName($object->ref); } if (!empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) { // For backward compatiblity, we scan also old dirs - if (!empty($conf->product->enabled)) { + if (isModEnabled("product")) { $upload_dirold = $conf->product->multidir_output[$object->entity].'/'.substr(substr("000".$object->id, -2), 1, 1).'/'.substr(substr("000".$object->id, -2), 0, 1).'/'.$object->id."/photos"; } else { $upload_dirold = $conf->service->multidir_output[$object->entity].'/'.substr(substr("000".$object->id, -2), 1, 1).'/'.substr(substr("000".$object->id, -2), 0, 1).'/'.$object->id."/photos"; @@ -2298,7 +2298,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print ''; // Type - if (!empty($conf->product->enabled) && !empty($conf->service->enabled)) { + if (isModEnabled("product") && !empty($conf->service->enabled)) { $typeformat = 'select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service"); print '
'; print (empty($conf->global->PRODUCT_DENY_CHANGE_PRODUCT_TYPE)) ? $form->editfieldkey("Type", 'fk_product_type', $object->type, $object, $usercancreate, $typeformat) : $langs->trans('Type'); @@ -2798,7 +2798,7 @@ if (!empty($conf->global->PRODUCT_ADD_FORM_ADD_TO) && $object->id && ($action == //print '
'; // Propals - if (!empty($conf->propal->enabled) && $user->rights->propale->creer) { + if (isModEnabled("propal") && $user->rights->propale->creer) { $propal = new Propal($db); $langs->load("propal"); diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index a865a1f2343..d6393ab139b 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -5463,7 +5463,7 @@ class Product extends CommonObject } $stock_commande_client = $this->stats_commande['qty']; } - if (!empty($conf->expedition->enabled)) { + if (isModEnabled("expedition")) { require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php'; $filterShipmentStatus = ''; if (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT)) { @@ -5500,7 +5500,7 @@ class Product extends CommonObject } $stock_reception_fournisseur = $this->stats_reception['qty']; } - if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) && !empty($conf->reception->enabled)) { + if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) && isModEnabled("reception")) { // Case module reception is used $filterStatus = '4'; if (isset($includedraftpoforvirtual)) { diff --git a/htdocs/product/composition/card.php b/htdocs/product/composition/card.php index 2e4962066e9..613ff2c3ca8 100644 --- a/htdocs/product/composition/card.php +++ b/htdocs/product/composition/card.php @@ -231,7 +231,7 @@ if ($id > 0 || !empty($ref)) { print ''; // Type - if (!empty($conf->product->enabled) && !empty($conf->service->enabled)) { + if (isModEnabled("product") && !empty($conf->service->enabled)) { $typeformat = 'select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service"); print '
'; print (empty($conf->global->PRODUCT_DENY_CHANGE_PRODUCT_TYPE)) ? $form->editfieldkey("Type", 'fk_product_type', $object->type, $object, $usercancreate, $typeformat) : $langs->trans('Type'); diff --git a/htdocs/product/document.php b/htdocs/product/document.php index 79ff858ba6e..b396041af83 100644 --- a/htdocs/product/document.php +++ b/htdocs/product/document.php @@ -79,14 +79,14 @@ $object = new Product($db); if ($id > 0 || !empty($ref)) { $result = $object->fetch($id, $ref); - if (!empty($conf->product->enabled)) { + if (isModEnabled("product")) { $upload_dir = $conf->product->multidir_output[$object->entity].'/'.get_exdir(0, 0, 0, 1, $object, 'product'); } elseif (!empty($conf->service->enabled)) { $upload_dir = $conf->service->multidir_output[$object->entity].'/'.get_exdir(0, 0, 0, 1, $object, 'product'); } if (!empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) { // For backward compatiblity, we scan also old dirs - if (!empty($conf->product->enabled)) { + if (isModEnabled("product")) { $upload_dirold = $conf->product->multidir_output[$object->entity].'/'.substr(substr("000".$object->id, -2), 1, 1).'/'.substr(substr("000".$object->id, -2), 0, 1).'/'.$object->id."/photos"; } else { $upload_dirold = $conf->service->multidir_output[$object->entity].'/'.substr(substr("000".$object->id, -2), 1, 1).'/'.substr(substr("000".$object->id, -2), 0, 1).'/'.$object->id."/photos"; diff --git a/htdocs/product/fournisseurs.php b/htdocs/product/fournisseurs.php index db4fdedbc01..f5ee4cbf1c4 100644 --- a/htdocs/product/fournisseurs.php +++ b/htdocs/product/fournisseurs.php @@ -397,7 +397,7 @@ if ($id > 0 || $ref) { print ''; // Type - if (!empty($conf->product->enabled) && !empty($conf->service->enabled)) { + if (isModEnabled("product") && !empty($conf->service->enabled)) { $typeformat = 'select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service"); print ''; } else { // Type - if (!empty($conf->product->enabled) && !empty($conf->service->enabled)) { + if (isModEnabled("product") && !empty($conf->service->enabled)) { $typeformat = 'select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service"); print '
'; print (empty($conf->global->PRODUCT_DENY_CHANGE_PRODUCT_TYPE)) ? $form->editfieldkey("Type", 'fk_product_type', $object->type, $object, 0, $typeformat) : $langs->trans('Type'); diff --git a/htdocs/product/index.php b/htdocs/product/index.php index 40141fce304..540d685ca7e 100644 --- a/htdocs/product/index.php +++ b/htdocs/product/index.php @@ -90,7 +90,7 @@ print '
'; if (!empty($conf->global->MAIN_SEARCH_FORM_ON_HOME_AREAS)) { // This may be useless due to the global search combo // Search contract - if ((!empty($conf->product->enabled) || !empty($conf->service->enabled)) && ($user->rights->produit->lire || $user->rights->service->lire)) { + if ((isModEnabled("product") || !empty($conf->service->enabled)) && ($user->rights->produit->lire || $user->rights->service->lire)) { $listofsearchfields['search_product'] = array('text'=>'ProductOrService'); } @@ -123,7 +123,7 @@ if (!empty($conf->global->MAIN_SEARCH_FORM_ON_HOME_AREAS)) { // This may be /* * Number of products and/or services */ -if ((!empty($conf->product->enabled) || !empty($conf->service->enabled)) && ($user->rights->produit->lire || $user->rights->service->lire)) { +if ((isModEnabled("product") || !empty($conf->service->enabled)) && ($user->rights->produit->lire || $user->rights->service->lire)) { $prodser = array(); $prodser[0][0] = $prodser[0][1] = $prodser[0][2] = $prodser[0][3] = 0; $prodser[0]['sell'] = 0; @@ -185,7 +185,7 @@ if ((!empty($conf->product->enabled) || !empty($conf->service->enabled)) && ($us $total = $SommeA + $SommeB + $SommeC + $SommeD + $SommeE + $SommeF; $dataseries = array(); - if (!empty($conf->product->enabled)) { + if (isModEnabled("product")) { $dataseries[] = array($langs->transnoentitiesnoconv("ProductsOnSale"), round($SommeA)); $dataseries[] = array($langs->transnoentitiesnoconv("ProductsOnPurchase"), round($SommeB)); $dataseries[] = array($langs->transnoentitiesnoconv("ProductsNotOnSell"), round($SommeC)); @@ -281,7 +281,7 @@ print '
'; /* * Latest modified products */ -if ((!empty($conf->product->enabled) || !empty($conf->service->enabled)) && ($user->rights->produit->lire || $user->rights->service->lire)) { +if ((isModEnabled("product") || !empty($conf->service->enabled)) && ($user->rights->produit->lire || $user->rights->service->lire)) { $max = 15; $sql = "SELECT p.rowid, p.label, p.price, p.ref, p.fk_product_type, p.tosell, p.tobuy, p.tobatch, p.fk_price_expression,"; $sql .= " p.entity,"; @@ -408,7 +408,7 @@ if ((!empty($conf->product->enabled) || !empty($conf->service->enabled)) && ($us // Also method used for counting must provide the 2 possible methods like done by all other reports into menu "accountancy - report - turnover": // "commitment engagment" method and "cash accounting" method if (!empty($conf->global->MAIN_SHOW_PRODUCT_ACTIVITY_TRIM)) { - if (!empty($conf->product->enabled)) { + if (isModEnabled("product")) { activitytrim(0); } if (!empty($conf->service->enabled)) { diff --git a/htdocs/product/list.php b/htdocs/product/list.php index 4cc79472ada..3299d8afcf1 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -206,23 +206,23 @@ $arrayfields = array( //'pfp.ref_fourn'=>array('label'=>$langs->trans("RefSupplier"), 'checked'=>1, 'enabled'=>(! empty($conf->barcode->enabled))), 'thumbnail'=>array('label'=>'Photo', 'checked'=>0, 'position'=>10), 'p.label'=>array('label'=>"Label", 'checked'=>1, 'position'=>10), - 'p.fk_product_type'=>array('label'=>"Type", 'checked'=>0, 'enabled'=>(!empty($conf->product->enabled) && !empty($conf->service->enabled)), 'position'=>11), + 'p.fk_product_type'=>array('label'=>"Type", 'checked'=>0, 'enabled'=>(isModEnabled("product") && !empty($conf->service->enabled)), 'position'=>11), 'p.barcode'=>array('label'=>"Gencod", 'checked'=>1, 'enabled'=>(isModEnabled('barcode')), 'position'=>12), 'p.duration'=>array('label'=>"Duration", 'checked'=>($contextpage != 'productlist'), 'enabled'=>(!empty($conf->service->enabled) && (string) $type == '1'), 'position'=>13), - 'p.finished'=>array('label'=>"Nature", 'checked'=>0, 'enabled'=>(!empty($conf->product->enabled) && $type != '1'), 'position'=>19), - 'p.weight'=>array('label'=>'Weight', 'checked'=>0, 'enabled'=>(!empty($conf->product->enabled) && $type != '1'), 'position'=>20), - 'p.weight_units'=>array('label'=>'WeightUnits', 'checked'=>0, 'enabled'=>(!empty($conf->product->enabled) && $type != '1'), 'position'=>21), - 'p.length'=>array('label'=>'Length', 'checked'=>0, 'enabled'=>(!empty($conf->product->enabled) && empty($conf->global->PRODUCT_DISABLE_SIZE) && $type != '1'), 'position'=>22), - 'p.length_units'=>array('label'=>'LengthUnits', 'checked'=>0, 'enabled'=>(!empty($conf->product->enabled) && empty($conf->global->PRODUCT_DISABLE_SIZE) && $type != '1'), 'position'=>23), - 'p.width'=>array('label'=>'Width', 'checked'=>0, 'enabled'=>(!empty($conf->product->enabled) && empty($conf->global->PRODUCT_DISABLE_SIZE) && $type != '1'), 'position'=>24), - 'p.width_units'=>array('label'=>'WidthUnits', 'checked'=>0, 'enabled'=>(!empty($conf->product->enabled) && empty($conf->global->PRODUCT_DISABLE_SIZE) && $type != '1'), 'position'=>25), - 'p.height'=>array('label'=>'Height', 'checked'=>0, 'enabled'=>(!empty($conf->product->enabled) && empty($conf->global->PRODUCT_DISABLE_SIZE) && $type != '1'), 'position'=>26), - 'p.height_units'=>array('label'=>'HeightUnits', 'checked'=>0, 'enabled'=>(!empty($conf->product->enabled) && empty($conf->global->PRODUCT_DISABLE_SIZE) && $type != '1'), 'position'=>27), - 'p.surface'=>array('label'=>'Surface', 'checked'=>0, 'enabled'=>(!empty($conf->product->enabled) && empty($conf->global->PRODUCT_DISABLE_SURFACE) && $type != '1'), 'position'=>28), - 'p.surface_units'=>array('label'=>'SurfaceUnits', 'checked'=>0, 'enabled'=>(!empty($conf->product->enabled) && empty($conf->global->PRODUCT_DISABLE_SURFACE) && $type != '1'), 'position'=>29), - 'p.volume'=>array('label'=>'Volume', 'checked'=>0, 'enabled'=>(!empty($conf->product->enabled) && empty($conf->global->PRODUCT_DISABLE_VOLUME) && $type != '1'), 'position'=>30), - 'p.volume_units'=>array('label'=>'VolumeUnits', 'checked'=>0, 'enabled'=>(!empty($conf->product->enabled) && empty($conf->global->PRODUCT_DISABLE_VOLUME) && $type != '1'), 'position'=>31), - 'cu.label'=>array('label'=>"DefaultUnitToShow", 'checked'=>0, 'enabled'=>(!empty($conf->product->enabled) && !empty($conf->global->PRODUCT_USE_UNITS)), 'position'=>32), + 'p.finished'=>array('label'=>"Nature", 'checked'=>0, 'enabled'=>(isModEnabled("product") && $type != '1'), 'position'=>19), + 'p.weight'=>array('label'=>'Weight', 'checked'=>0, 'enabled'=>(isModEnabled("product") && $type != '1'), 'position'=>20), + 'p.weight_units'=>array('label'=>'WeightUnits', 'checked'=>0, 'enabled'=>(isModEnabled("product") && $type != '1'), 'position'=>21), + 'p.length'=>array('label'=>'Length', 'checked'=>0, 'enabled'=>(isModEnabled("product") && empty($conf->global->PRODUCT_DISABLE_SIZE) && $type != '1'), 'position'=>22), + 'p.length_units'=>array('label'=>'LengthUnits', 'checked'=>0, 'enabled'=>(isModEnabled("product") && empty($conf->global->PRODUCT_DISABLE_SIZE) && $type != '1'), 'position'=>23), + 'p.width'=>array('label'=>'Width', 'checked'=>0, 'enabled'=>(isModEnabled("product") && empty($conf->global->PRODUCT_DISABLE_SIZE) && $type != '1'), 'position'=>24), + 'p.width_units'=>array('label'=>'WidthUnits', 'checked'=>0, 'enabled'=>(isModEnabled("product") && empty($conf->global->PRODUCT_DISABLE_SIZE) && $type != '1'), 'position'=>25), + 'p.height'=>array('label'=>'Height', 'checked'=>0, 'enabled'=>(isModEnabled("product") && empty($conf->global->PRODUCT_DISABLE_SIZE) && $type != '1'), 'position'=>26), + 'p.height_units'=>array('label'=>'HeightUnits', 'checked'=>0, 'enabled'=>(isModEnabled("product") && empty($conf->global->PRODUCT_DISABLE_SIZE) && $type != '1'), 'position'=>27), + 'p.surface'=>array('label'=>'Surface', 'checked'=>0, 'enabled'=>(isModEnabled("product") && empty($conf->global->PRODUCT_DISABLE_SURFACE) && $type != '1'), 'position'=>28), + 'p.surface_units'=>array('label'=>'SurfaceUnits', 'checked'=>0, 'enabled'=>(isModEnabled("product") && empty($conf->global->PRODUCT_DISABLE_SURFACE) && $type != '1'), 'position'=>29), + 'p.volume'=>array('label'=>'Volume', 'checked'=>0, 'enabled'=>(isModEnabled("product") && empty($conf->global->PRODUCT_DISABLE_VOLUME) && $type != '1'), 'position'=>30), + 'p.volume_units'=>array('label'=>'VolumeUnits', 'checked'=>0, 'enabled'=>(isModEnabled("product") && empty($conf->global->PRODUCT_DISABLE_VOLUME) && $type != '1'), 'position'=>31), + 'cu.label'=>array('label'=>"DefaultUnitToShow", 'checked'=>0, 'enabled'=>(isModEnabled("product") && !empty($conf->global->PRODUCT_USE_UNITS)), 'position'=>32), 'p.sellprice'=>array('label'=>"SellingPrice", 'checked'=>1, 'enabled'=>empty($conf->global->PRODUIT_MULTIPRICES), 'position'=>40), 'p.tva_tx'=>array('label'=>"VATRate", 'checked'=>0, 'enabled'=>empty($conf->global->PRODUIT_MULTIPRICES), 'position'=>41), 'p.minbuyprice'=>array('label'=>"BuyingPriceMinShort", 'checked'=>1, 'enabled'=>(!empty($user->rights->fournisseur->lire)), 'position'=>42), diff --git a/htdocs/product/price.php b/htdocs/product/price.php index b129a1ff4e5..6acdafabcef 100644 --- a/htdocs/product/price.php +++ b/htdocs/product/price.php @@ -887,7 +887,7 @@ if (!empty($conf->global->PRODUIT_MULTIPRICES) || !empty($conf->global->PRODUIT_ $soc->fetch($socid); // Type - if (!empty($conf->product->enabled) && !empty($conf->service->enabled)) { + if (isModEnabled("product") && !empty($conf->service->enabled)) { $typeformat = 'select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service"); print '
'; print (empty($conf->global->PRODUCT_DENY_CHANGE_PRODUCT_TYPE)) ? $form->editfieldkey("Type", 'fk_product_type', $object->type, $object, 0, $typeformat) : $langs->trans('Type'); @@ -971,7 +971,7 @@ if (!empty($conf->global->PRODUIT_MULTIPRICES) || !empty($conf->global->PRODUIT_ } else { if (!empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL)) { // using this option is a bug. kept for backward compatibility // Type - if (!empty($conf->product->enabled) && !empty($conf->service->enabled)) { + if (isModEnabled("product") && !empty($conf->service->enabled)) { $typeformat = 'select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service"); print '
'; print (empty($conf->global->PRODUCT_DENY_CHANGE_PRODUCT_TYPE)) ? $form->editfieldkey("Type", 'fk_product_type', $object->type, $object, 0, $typeformat) : $langs->trans('Type'); @@ -986,7 +986,7 @@ if (!empty($conf->global->PRODUIT_MULTIPRICES) || !empty($conf->global->PRODUIT_ print '
'; print (empty($conf->global->PRODUCT_DENY_CHANGE_PRODUCT_TYPE)) ? $form->editfieldkey("Type", 'fk_product_type', $object->type, $object, 0, $typeformat) : $langs->trans('Type'); diff --git a/htdocs/product/stock/product.php b/htdocs/product/stock/product.php index a0f3e9fa599..2d9ec85303d 100644 --- a/htdocs/product/stock/product.php +++ b/htdocs/product/stock/product.php @@ -622,7 +622,7 @@ if ($id > 0 || $ref) { print ''; // Type - if (!empty($conf->product->enabled) && !empty($conf->service->enabled)) { + if (isModEnabled("product") && !empty($conf->service->enabled)) { $typeformat = 'select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service"); print ''; @@ -1362,7 +1362,7 @@ if ($action == 'create') { $objectsrc = new Commande($db); $objectsrc->fetch($object->$typeobject->id); } - if ($typeobject == 'propal' && $object->$typeobject->id && !empty($conf->propal->enabled)) { + if ($typeobject == 'propal' && $object->$typeobject->id && isModEnabled("propal")) { $objectsrc = new Propal($db); $objectsrc->fetch($object->$typeobject->id); } @@ -1435,7 +1435,7 @@ if ($action == 'create') { print "\n"; print ''; } - if ($typeobject == 'propal' && $object->$typeobject->id && !empty($conf->propal->enabled)) { + if ($typeobject == 'propal' && $object->$typeobject->id && isModEnabled("propal")) { print ''; print '\n"; print ''; } - if ($typeobject == 'CommandeFournisseur' && $object->$typeobject->id && !empty($conf->propal->enabled)) { + if ($typeobject == 'CommandeFournisseur' && $object->$typeobject->id && isModEnabled("propal")) { print ''; print '\n"; print ''; } - if ($typeobject == 'propal' && $object->$typeobject->id && !empty($conf->propal->enabled)) { + if ($typeobject == 'propal' && $object->$typeobject->id && isModEnabled("propal")) { print ''."\n"; // Date payment // Bank - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print ''; // Number - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { // Number print ''; // Default Bank Account - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print '
'; print (empty($conf->global->PRODUCT_DENY_CHANGE_PRODUCT_TYPE)) ? $form->editfieldkey("Type", 'fk_product_type', $object->type, $object, 0, $typeformat) : $langs->trans('Type'); @@ -776,7 +776,7 @@ if ($id > 0 || $ref) { } // Number of product from customer order already sent (partial shipping) - if (!empty($conf->expedition->enabled)) { + if (isModEnabled("expedition")) { require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php'; $filterShipmentStatus = ''; if (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT)) { diff --git a/htdocs/product/stock/replenish.php b/htdocs/product/stock/replenish.php index c8d10444711..b89554a18f7 100644 --- a/htdocs/product/stock/replenish.php +++ b/htdocs/product/stock/replenish.php @@ -423,7 +423,7 @@ if ($usevirtualstock) { $sqlCommandesCli = '0'; } - if (!empty($conf->expedition->enabled)) { + if (isModEnabled("expedition")) { $sqlExpeditionsCli = "(SELECT ".$db->ifsql("SUM(ed2.qty) IS NULL", "0", "SUM(ed2.qty)")." as qty"; // We need the ifsql because if result is 0 for product p.rowid, we must return 0 and not NULL $sqlExpeditionsCli .= " FROM ".MAIN_DB_PREFIX."expedition as e2,"; $sqlExpeditionsCli .= " ".MAIN_DB_PREFIX."expeditiondet as ed2,"; diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index 95c3a533d1f..95abbfa8f47 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -1344,7 +1344,7 @@ if ($action == 'create' && $user->rights->projet->creer) { print''.$langs->trans("Create").''; print ''.img_object($langs->trans("ShowOrder"), 'order').' '.$objectsrc->ref; } - if ($origin == 'propal' && !empty($conf->propal->enabled)) { + if ($origin == 'propal' && isModEnabled("propal")) { print $langs->trans("RefProposal").''.img_object($langs->trans("ShowProposal"), 'propal').' '.$objectsrc->ref; } print '
'; print $langs->trans("RefProposal").''; @@ -1443,7 +1443,7 @@ if ($action == 'create') { print "
'; print $langs->trans("SupplierOrder").''; diff --git a/htdocs/reception/class/reception.class.php b/htdocs/reception/class/reception.class.php index 7244fdcb60b..ceb71624292 100644 --- a/htdocs/reception/class/reception.class.php +++ b/htdocs/reception/class/reception.class.php @@ -35,7 +35,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; require_once DOL_DOCUMENT_ROOT."/core/class/commonobjectline.class.php"; require_once DOL_DOCUMENT_ROOT.'/core/class/commonincoterm.class.php'; -if (!empty($conf->propal->enabled)) { +if (isModEnabled("propal")) { require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php'; } if (!empty($conf->commande->enabled)) { diff --git a/htdocs/reception/contact.php b/htdocs/reception/contact.php index 4e04bdd2926..83f84d787f8 100644 --- a/htdocs/reception/contact.php +++ b/htdocs/reception/contact.php @@ -202,7 +202,7 @@ if ($id > 0 || !empty($ref)) { print "
'; $objectsrc = new Propal($db); $objectsrc->fetch($object->$typeobject->id); diff --git a/htdocs/reception/note.php b/htdocs/reception/note.php index 46e10002d76..fadf222aa3e 100644 --- a/htdocs/reception/note.php +++ b/htdocs/reception/note.php @@ -55,7 +55,7 @@ if ($id > 0 || !empty($ref)) { $objectsrc = new Commande($db); $objectsrc->fetch($object->$typeobject->id); } - if ($typeobject == 'propal' && $object->$typeobject->id && !empty($conf->propal->enabled)) { + if ($typeobject == 'propal' && $object->$typeobject->id && isModEnabled("propal")) { $objectsrc = new Propal($db); $objectsrc->fetch($object->$typeobject->id); } diff --git a/htdocs/resource/element_resource.php b/htdocs/resource/element_resource.php index 09c7befc664..ab85041a650 100644 --- a/htdocs/resource/element_resource.php +++ b/htdocs/resource/element_resource.php @@ -33,7 +33,7 @@ if (!empty($conf->project->enabled)) { require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php'; } -if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { +if (isModEnabled("product") || !empty($conf->service->enabled)) { require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; } diff --git a/htdocs/salaries/card.php b/htdocs/salaries/card.php index 7d57575dacd..ce2ef50150d 100644 --- a/htdocs/salaries/card.php +++ b/htdocs/salaries/card.php @@ -260,7 +260,7 @@ if ($action == 'add' && empty($cancel)) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Amount")), null, 'errors'); $error++; } - if (!empty($conf->banque->enabled) && !empty($auto_create_paiement) && !$object->accountid > 0) { + if (isModEnabled("banque") && !empty($auto_create_paiement) && !$object->accountid > 0) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("BankAccount")), null, 'errors'); $error++; } @@ -583,7 +583,7 @@ if ($action == 'create') { print '
'; print $form->editfieldkey('BankAccount', 'selectaccountid', '', $object, 0, 'string', '', 1).''; print img_picto('', 'bank_account', 'class="paddingrighonly"'); @@ -610,7 +610,7 @@ if ($action == 'create') { print '
'; print ''; print ''; print ''; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print ''; } print ''; @@ -972,7 +972,7 @@ if ($id) { print '\n"; $labeltype = $langs->trans("PaymentType".$objp->type_code) != ("PaymentType".$objp->type_code) ? $langs->trans("PaymentType".$objp->type_code) : $objp->paiement_type; print "\n"; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $bankaccountstatic->id = $objp->baid; $bankaccountstatic->ref = $objp->baref; $bankaccountstatic->label = $objp->baref; diff --git a/htdocs/salaries/class/paymentsalary.class.php b/htdocs/salaries/class/paymentsalary.class.php index 3a6ade39c6a..1a716cba31d 100644 --- a/htdocs/salaries/class/paymentsalary.class.php +++ b/htdocs/salaries/class/paymentsalary.class.php @@ -493,7 +493,7 @@ class PaymentSalary extends CommonObject $error = 0; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { include_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; $acc = new Account($this->db); diff --git a/htdocs/salaries/class/salary.class.php b/htdocs/salaries/class/salary.class.php index 968320ce394..8949313ecb0 100644 --- a/htdocs/salaries/class/salary.class.php +++ b/htdocs/salaries/class/salary.class.php @@ -372,12 +372,12 @@ class Salary extends CommonObject $this->error = $langs->trans("ErrorFieldRequired", $langs->transnoentities("Amount")); return -5; } - /* if (!empty($conf->banque->enabled) && (empty($this->accountid) || $this->accountid <= 0)) + /* if (isModEnabled("banque") && (empty($this->accountid) || $this->accountid <= 0)) { $this->error = $langs->trans("ErrorFieldRequired", $langs->transnoentities("Account")); return -6; } - if (!empty($conf->banque->enabled) && (empty($this->type_payment) || $this->type_payment <= 0)) + if (isModEnabled("banque") && (empty($this->type_payment) || $this->type_payment <= 0)) { $this->error = $langs->trans("ErrorFieldRequired", $langs->transnoentities("PaymentMode")); return -7; diff --git a/htdocs/salaries/list.php b/htdocs/salaries/list.php index af58d7b53f7..82a6199407e 100644 --- a/htdocs/salaries/list.php +++ b/htdocs/salaries/list.php @@ -438,7 +438,7 @@ $form->select_types_paiements($search_type_id, 'search_type_id', '', 0, 1, 1, 16 print ''; // Bank account -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { print ''; @@ -476,7 +476,7 @@ print_liste_field_titre("DateStart", $_SERVER["PHP_SELF"], "s.datesp,s.rowid", " print_liste_field_titre("DateEnd", $_SERVER["PHP_SELF"], "s.dateep,s.rowid", "", $param, 'align="center"', $sortfield, $sortorder); print_liste_field_titre("Employee", $_SERVER["PHP_SELF"], "u.lastname", "", $param, "", $sortfield, $sortorder); print_liste_field_titre("DefaultPaymentMode", $_SERVER["PHP_SELF"], "type", "", $param, 'class="left"', $sortfield, $sortorder); -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { print_liste_field_titre("DefaultBankAccount", $_SERVER["PHP_SELF"], "ba.label", "", $param, "", $sortfield, $sortorder); } print_liste_field_titre("Amount", $_SERVER["PHP_SELF"], "s.amount", "", $param, 'class="right"', $sortfield, $sortorder); @@ -577,7 +577,7 @@ while ($i < ($limit ? min($num, $limit) : $num)) { } // Account - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { print ''; } diff --git a/htdocs/salaries/paiement_salary.php b/htdocs/salaries/paiement_salary.php index cfca26efca4..8c885385a7f 100644 --- a/htdocs/salaries/paiement_salary.php +++ b/htdocs/salaries/paiement_salary.php @@ -77,7 +77,7 @@ if ($action == 'add_payment' || ($action == 'confirm_paiement' && $confirm == 'y $error++; $action = 'create'; } - if (!empty($conf->banque->enabled) && !(GETPOST("accountid", 'int') > 0)) { + if (isModEnabled("banque") && !(GETPOST("accountid", 'int') > 0)) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("AccountToDebit")), null, 'errors'); $error++; $action = 'create'; diff --git a/htdocs/salaries/payment_salary/card.php b/htdocs/salaries/payment_salary/card.php index b3234e39490..f5e8d465378 100644 --- a/htdocs/salaries/payment_salary/card.php +++ b/htdocs/salaries/payment_salary/card.php @@ -31,7 +31,7 @@ require_once DOL_DOCUMENT_ROOT.'/salaries/class/salary.class.php'; require_once DOL_DOCUMENT_ROOT.'/salaries/class/paymentsalary.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/modules/facture/modules_facture.php'; -if (!empty($conf->banque->enabled)) require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; +if (isModEnabled("banque")) require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; // Load translation files required by the page $langs->loadLangs(array('bills', 'banks', 'companies', 'salaries')); @@ -152,7 +152,7 @@ print ''; // Bank account -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { if ($object->bank_account) { $bankline = new AccountLine($db); $bankline->fetch($object->bank_line); diff --git a/htdocs/salaries/payments.php b/htdocs/salaries/payments.php index 54a8589677d..e7a1e02e1e7 100644 --- a/htdocs/salaries/payments.php +++ b/htdocs/salaries/payments.php @@ -448,7 +448,7 @@ print ''; // Chq number print ''; -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { // Bank transaction print ''; print ''; -if (!empty($conf->expedition->enabled)) { +if (isModEnabled("expedition")) { if (getDolGlobalInt('MAIN_FEATURES_LEVEL') > 0) { // Visible on experimental only because seems to not be implemented everywhere (only on proposal) print ''; print ''; diff --git a/htdocs/societe/consumption.php b/htdocs/societe/consumption.php index 62bcbed5ff1..b7f66ea8ba2 100644 --- a/htdocs/societe/consumption.php +++ b/htdocs/societe/consumption.php @@ -162,7 +162,7 @@ if ($object->client) { $obj = $db->fetch_object($resql); $nbFactsClient = $obj->nb; $thirdTypeArray['customer'] = $langs->trans("customer"); - if (!empty($conf->propal->enabled) && $user->rights->propal->lire) { + if (isModEnabled("propal") && $user->rights->propal->lire) { $elementTypeArray['propal'] = $langs->transnoentitiesnoconv('Proposals'); } if (!empty($conf->commande->enabled) && $user->rights->commande->lire) { diff --git a/htdocs/societe/paymentmodes.php b/htdocs/societe/paymentmodes.php index 9e4c0e91137..2c2c125530b 100644 --- a/htdocs/societe/paymentmodes.php +++ b/htdocs/societe/paymentmodes.php @@ -779,7 +779,7 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' $obj = $db->fetch_object($resql); $nbFactsClient = $obj->nb; $thirdTypeArray['customer'] = $langs->trans("customer"); - if (!empty($conf->propal->enabled) && $user->rights->propal->lire) { + if (isModEnabled("propal") && $user->rights->propal->lire) { $elementTypeArray['propal'] = $langs->transnoentitiesnoconv('Proposals'); } if (!empty($conf->commande->enabled) && $user->rights->commande->lire) { diff --git a/htdocs/supplier_proposal/card.php b/htdocs/supplier_proposal/card.php index 3ef3e2bd737..7f09f66c065 100644 --- a/htdocs/supplier_proposal/card.php +++ b/htdocs/supplier_proposal/card.php @@ -1276,14 +1276,14 @@ if ($action == 'create') { print ''; // Bank Account - if (!empty($conf->global->BANK_ASK_PAYMENT_BANK_DURING_PROPOSAL) && !empty($conf->banque->enabled)) { + if (!empty($conf->global->BANK_ASK_PAYMENT_BANK_DURING_PROPOSAL) && isModEnabled("banque")) { print ''; } // Shipping Method - if (!empty($conf->expedition->enabled)) { + if (isModEnabled("expedition")) { print ''; @@ -1747,7 +1747,7 @@ if ($action == 'create') { print ''; }*/ - if (!empty($conf->global->BANK_ASK_PAYMENT_BANK_DURING_PROPOSAL) && !empty($conf->banque->enabled)) { + if (!empty($conf->global->BANK_ASK_PAYMENT_BANK_DURING_PROPOSAL) && isModEnabled("banque")) { // Bank Account print ''; print ''; // Company / Contact - if (!empty($conf->societe->enabled)) { + if (isModEnabled("societe")) { print ''; print '
'; print $langs->trans('DefaultBankAccount'); @@ -922,7 +922,7 @@ if ($id) { print '
'; $nbcols = 3; - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { $nbcols++; } @@ -956,7 +956,7 @@ if ($id) { print '
'.$langs->trans("RefPayment").''.$langs->trans("Date").''.$langs->trans("Type").''.$langs->trans('BankAccount').''.$langs->trans("Amount").''.dol_print_date($db->jdate($objp->dp), 'day')."".$labeltype.' '.$objp->num_payment."'; $form->select_comptes($search_account, 'search_account', 0, '', 1); print ''; if ($obj->fk_account > 0) { //$accountstatic->fetch($obj->fk_bank); @@ -663,7 +663,7 @@ if ($num == 0) { } }*/ $colspan = 9; - if (!empty($conf->banque->enabled)) { $colspan++; } + if (isModEnabled("banque")) { $colspan++; } print '
'.$langs->trans("NoRecordFound").'
'.$langs->trans('Amount').''.price($object-> print '
'.$langs->trans('Note').''.nl2br($object->note).'
'; print ''; @@ -489,7 +489,7 @@ print_liste_field_titre("DatePayment", $_SERVER["PHP_SELF"], "s.datep,s.rowid", print_liste_field_titre("Employee", $_SERVER["PHP_SELF"], "u.rowid", "", $param, "", $sortfield, $sortorder); print_liste_field_titre("PaymentMode", $_SERVER["PHP_SELF"], "pst.code", "", $param, 'class="left"', $sortfield, $sortorder); print_liste_field_titre("Numero", $_SERVER["PHP_SELF"], "s.num_payment", "", $param, '', $sortfield, $sortorder, '', 'ChequeOrTransferNumber'); -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { print_liste_field_titre("BankTransactionLine", $_SERVER["PHP_SELF"], "s.fk_bank", "", $param, '', $sortfield, $sortorder); print_liste_field_titre("BankAccount", $_SERVER["PHP_SELF"], "ba.label", "", $param, "", $sortfield, $sortorder); } @@ -604,7 +604,7 @@ while ($i < ($limit ? min($num, $limit) : $num)) { } // Account - if (!empty($conf->banque->enabled)) { + if (isModEnabled("banque")) { // Bank transaction print ''; $accountlinestatic->id = $obj->fk_bank; diff --git a/htdocs/societe/admin/societe.php b/htdocs/societe/admin/societe.php index e924f714843..40f92007f38 100644 --- a/htdocs/societe/admin/societe.php +++ b/htdocs/societe/admin/societe.php @@ -853,7 +853,7 @@ if (!empty($conf->global->CONTACT_SHOW_EMAIL_PHONE_TOWN_SELECTLIST)) { print '
'.$langs->trans("AskForPreferredShippingMethod").'
'.$langs->trans('BankAccount').''; $form->select_comptes(GETPOST('fk_account') > 0 ? GETPOST('fk_account', 'int') : $fk_account, 'fk_account', 0, '', 1); print '
'.$langs->trans('SendingMethod').''; print $form->selectShippingMethod(GETPOST('shipping_method_id') > 0 ? GETPOST('shipping_method_id', 'int') : $shipping_method_id, 'shipping_method_id', '', 1); print '
'; print ''; $atleastonefound = 0; -if (!empty($conf->banque->enabled)) { +if (isModEnabled("banque")) { print ''; print ''; print '
'; diff --git a/htdocs/takepos/admin/terminal.php b/htdocs/takepos/admin/terminal.php index 0bfe4ebd080..2ac8607fe33 100644 --- a/htdocs/takepos/admin/terminal.php +++ b/htdocs/takepos/admin/terminal.php @@ -161,7 +161,7 @@ print $form->select_company($conf->global->{'CASHDESK_ID_THIRDPARTY'.$terminalto print '
'.$langs->trans("CashDeskBankAccountForSell").''; print img_picto('', 'bank_account', 'class="pictofixedwidth"'); @@ -453,7 +453,7 @@ print '
'; print ''; -if ($atleastonefound == 0 && !empty($conf->banque->enabled)) { +if ($atleastonefound == 0 && isModEnabled("banque")) { print info_admin($langs->trans("AtLeastOneDefaultBankAccountMandatory"), 0, 0, 'error'); } diff --git a/htdocs/takepos/index.php b/htdocs/takepos/index.php index 58dd98ce512..8f2bbc94fc0 100644 --- a/htdocs/takepos/index.php +++ b/htdocs/takepos/index.php @@ -1134,7 +1134,7 @@ if (isset($_SESSION["takeposterminal"]) && $_SESSION["takeposterminal"]) { } } - if (empty($paiementsModes) && !empty($conf->banque->enabled)) { + if (empty($paiementsModes) && isModEnabled("banque")) { $langs->load('errors'); setEventMessages($langs->trans("ErrorModuleSetupNotComplete", $langs->transnoentitiesnoconv("TakePOS")), null, 'errors'); setEventMessages($langs->trans("ProblemIsInSetupOfTerminal", $_SESSION["takeposterminal"]), null, 'errors'); diff --git a/htdocs/takepos/invoice.php b/htdocs/takepos/invoice.php index cbd3d5349f9..07e84f4dea3 100644 --- a/htdocs/takepos/invoice.php +++ b/htdocs/takepos/invoice.php @@ -185,7 +185,7 @@ if (empty($reshook)) { } } - if ($bankaccount <= 0 && $pay != "delayed" && !empty($conf->banque->enabled)) { + if ($bankaccount <= 0 && $pay != "delayed" && isModEnabled("banque")) { $errormsg = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("BankAccount")); $error++; } diff --git a/htdocs/ticket/agenda.php b/htdocs/ticket/agenda.php index 72c19c217b3..2f919aa436d 100644 --- a/htdocs/ticket/agenda.php +++ b/htdocs/ticket/agenda.php @@ -170,7 +170,7 @@ if (!empty($object->origin_email)) { } // Thirdparty -if (!empty($conf->societe->enabled)) { +if (isModEnabled("societe")) { $morehtmlref .= '
'.$langs->trans('ThirdParty'); /*if ($action != 'editcustomer' && $object->fk_statut < 8 && !$user->socid && $user->rights->ticket->write) { $morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('Edit'), 1) . ''; diff --git a/htdocs/ticket/card.php b/htdocs/ticket/card.php index 3427d377703..d33a37343bd 100755 --- a/htdocs/ticket/card.php +++ b/htdocs/ticket/card.php @@ -952,7 +952,7 @@ if ($action == 'create' || $action == 'presend') { } // Thirdparty - if (!empty($conf->societe->enabled)) { + if (isModEnabled("societe")) { $morehtmlref .= '
'.$langs->trans('ThirdParty').' '; if ($action != 'editcustomer' && $object->status < 8 && !$user->socid && $user->rights->ticket->write) { $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('Edit'), 0).' : '; diff --git a/htdocs/ticket/contact.php b/htdocs/ticket/contact.php index d32ab88eb1c..1ee1ef163bb 100644 --- a/htdocs/ticket/contact.php +++ b/htdocs/ticket/contact.php @@ -210,7 +210,7 @@ if ($id > 0 || !empty($track_id) || !empty($ref)) { } // Thirdparty - if (!empty($conf->societe->enabled)) { + if (isModEnabled("societe")) { $morehtmlref .= '
'.$langs->trans('ThirdParty'); /*if ($action != 'editcustomer' && $object->fk_statut < 8 && !$user->socid && $user->rights->ticket->write) { $morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('Edit'), 1) . ''; diff --git a/htdocs/ticket/document.php b/htdocs/ticket/document.php index 234c5e92918..1fe4356ea6a 100644 --- a/htdocs/ticket/document.php +++ b/htdocs/ticket/document.php @@ -145,7 +145,7 @@ if ($object->id) { } // Thirdparty - if (!empty($conf->societe->enabled)) { + if (isModEnabled("societe")) { $morehtmlref .= '
'.$langs->trans('ThirdParty'); /*if ($action != 'editcustomer' && $object->fk_statut < 8 && !$user->socid && $user->rights->ticket->write) { $morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('Edit'), 1) . ''; diff --git a/htdocs/ticket/messaging.php b/htdocs/ticket/messaging.php index df829a010ec..edb289925b1 100644 --- a/htdocs/ticket/messaging.php +++ b/htdocs/ticket/messaging.php @@ -171,7 +171,7 @@ if ($object->fk_user_create > 0) { } // Thirdparty -if (!empty($conf->societe->enabled)) { +if (isModEnabled("societe")) { $morehtmlref .= '
'.$langs->trans('ThirdParty'); /*if ($action != 'editcustomer' && $object->fk_statut < 8 && !$user->socid && $user->rights->ticket->write) { $morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('Edit'), 1) . ''; diff --git a/htdocs/user/card.php b/htdocs/user/card.php index 70ee971eee8..5b64ad6225f 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -1674,7 +1674,7 @@ if ($action == 'create' || $action == 'adduserldap') { include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php'; // Company / Contact - if (!empty($conf->societe->enabled)) { + if (isModEnabled("societe")) { print '
'.$langs->trans("LinkToCompanyContact").''; $s = ''; @@ -2606,7 +2606,7 @@ if ($action == 'create' || $action == 'adduserldap') { print '
'.$langs->trans("LinkToCompanyContact").''; if ($object->socid > 0) { diff --git a/htdocs/user/param_ihm.php b/htdocs/user/param_ihm.php index 6a5eea96490..0043252c409 100644 --- a/htdocs/user/param_ihm.php +++ b/htdocs/user/param_ihm.php @@ -186,7 +186,7 @@ llxHeader('', $title, $help_url); // List of possible landing pages $tmparray = array('index.php'=>'Dashboard'); -if (!empty($conf->societe->enabled)) { +if (isModEnabled("societe")) { $tmparray['societe/index.php?mainmenu=companies&leftmenu='] = 'ThirdPartiesArea'; } if (!empty($conf->project->enabled)) { @@ -195,10 +195,10 @@ if (!empty($conf->project->enabled)) { if (!empty($conf->holiday->enabled) || !empty($conf->expensereport->enabled)) { $tmparray['hrm/index.php?mainmenu=hrm&leftmenu='] = 'HRMArea'; // TODO Complete list with first level of menus } -if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { +if (isModEnabled("product") || !empty($conf->service->enabled)) { $tmparray['product/index.php?mainmenu=products&leftmenu='] = 'ProductsAndServicesArea'; } -if (!empty($conf->propal->enabled) || !empty($conf->commande->enabled) || !empty($conf->ficheinter->enabled) || !empty($conf->contrat->enabled)) { +if (isModEnabled("propal") || !empty($conf->commande->enabled) || !empty($conf->ficheinter->enabled) || !empty($conf->contrat->enabled)) { $tmparray['comm/index.php?mainmenu=commercial&leftmenu='] = 'CommercialArea'; } if (!empty($conf->comptabilite->enabled) || !empty($conf->accounting->enabled)) { diff --git a/htdocs/user/perms.php b/htdocs/user/perms.php index ef00c90d6cb..b9c840c6cb7 100644 --- a/htdocs/user/perms.php +++ b/htdocs/user/perms.php @@ -353,7 +353,7 @@ if ($result) { } // Special cases - if (!empty($conf->reception->enabled)) { + if (isModEnabled("reception")) { // The 2 permissions in fournisseur modules are replaced by permissions into reception module if ($obj->module == 'fournisseur' && $obj->perms == 'commande' && $obj->subperms == 'receptionner') { $i++; @@ -420,7 +420,7 @@ if ($result) { } // Special cases - if (!empty($conf->reception->enabled)) { + if (isModEnabled("reception")) { // The 2 permission in fournisseur modules has been replaced by permissions into reception module if ($obj->module == 'fournisseur' && $obj->perms == 'commande' && $obj->subperms == 'receptionner') { $i++; diff --git a/htdocs/variants/combinations.php b/htdocs/variants/combinations.php index f01e674c44a..b95a19e70f7 100644 --- a/htdocs/variants/combinations.php +++ b/htdocs/variants/combinations.php @@ -395,7 +395,7 @@ if (!empty($id) || !empty($ref)) { print ''; // Type - if (!empty($conf->product->enabled) && !empty($conf->service->enabled)) { + if (isModEnabled("product") && !empty($conf->service->enabled)) { $typeformat = 'select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service"); print '\n"; - if (isModEnabled("product") || !empty($conf->service->enabled)) { + if (isModEnabled("product") || isModEnabled("service")) { print ''; print ''; } - if (!empty($conf->service->enabled)) { + if (isModEnabled("service")) { print ''; print ''; print ''; @@ -285,7 +285,7 @@ class FormMargin print ''; } - if (isModEnabled("product") && !empty($conf->service->enabled)) { + if (isModEnabled("product") && isModEnabled("service")) { print ''; print ''; print ''; diff --git a/htdocs/core/class/html.formsetup.class.php b/htdocs/core/class/html.formsetup.class.php index 67d07cb6992..c2183653686 100644 --- a/htdocs/core/class/html.formsetup.class.php +++ b/htdocs/core/class/html.formsetup.class.php @@ -851,7 +851,7 @@ class FormSetupItem } elseif ($this->type == 'securekey') { $out.= $this->generateInputFieldSecureKey(); } elseif ($this->type == 'product') { - if (isModEnabled("product") || !empty($conf->service->enabled)) { + if (isModEnabled("product") || isModEnabled("service")) { $selected = (empty($this->fieldValue) ? '' : $this->fieldValue); $out.= $this->form->select_produits($selected, $this->confKey, '', 0, 0, 1, 2, '', 0, array(), 0, '1', 0, $this->cssClass, 0, '', null, 1); } diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index ce33ed2553b..d306990daaa 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -2923,7 +2923,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, } if (isModEnabled("product")) { $original_file = $conf->product->multidir_output[$entity].'/'.$original_file; - } elseif (!empty($conf->service->enabled)) { + } elseif (isModEnabled("service")) { $original_file = $conf->service->multidir_output[$entity].'/'.$original_file; } } elseif ($modulepart == 'product_batch' || $modulepart == 'produitlot') { diff --git a/htdocs/core/lib/product.lib.php b/htdocs/core/lib/product.lib.php index c6ddf3b756d..be12e5c81d1 100644 --- a/htdocs/core/lib/product.lib.php +++ b/htdocs/core/lib/product.lib.php @@ -174,7 +174,7 @@ function product_prepare_head($object) if (isModEnabled("product") && ($object->type == Product::TYPE_PRODUCT)) { $upload_dir = $conf->product->multidir_output[$object->entity].'/'.dol_sanitizeFileName($object->ref); } - if (!empty($conf->service->enabled) && ($object->type == Product::TYPE_SERVICE)) { + if (isModEnabled("service") && ($object->type == Product::TYPE_SERVICE)) { $upload_dir = $conf->service->multidir_output[$object->entity].'/'.dol_sanitizeFileName($object->ref); } $nbFiles = count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$')); @@ -182,7 +182,7 @@ function product_prepare_head($object) if (isModEnabled("product") && ($object->type == Product::TYPE_PRODUCT)) { $upload_dir = $conf->product->multidir_output[$object->entity].'/'.get_exdir($object->id, 2, 0, 0, $object, 'product').$object->id.'/photos'; } - if (!empty($conf->service->enabled) && ($object->type == Product::TYPE_SERVICE)) { + if (isModEnabled("service") && ($object->type == Product::TYPE_SERVICE)) { $upload_dir = $conf->service->multidir_output[$object->entity].'/'.get_exdir($object->id, 2, 0, 0, $object, 'product').$object->id.'/photos'; } $nbFiles += count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$')); diff --git a/htdocs/core/modules/DolibarrModules.class.php b/htdocs/core/modules/DolibarrModules.class.php index e7fbb0420fe..2076c6a348e 100644 --- a/htdocs/core/modules/DolibarrModules.class.php +++ b/htdocs/core/modules/DolibarrModules.class.php @@ -1368,7 +1368,7 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it // For the moment, we manage this with hard coded exception //print "Remove box ".$file.'
'; if ($file == 'box_graph_product_distribution.php') { - if (isModEnabled("product") || !empty($conf->service->enabled)) { + if (isModEnabled("product") || isModEnabled("service")) { dol_syslog("We discard deleting module ".$file." because another module still active requires it."); continue; } diff --git a/htdocs/core/modules/modCategorie.class.php b/htdocs/core/modules/modCategorie.class.php index bee6f95f00d..eb9c4fe8779 100644 --- a/htdocs/core/modules/modCategorie.class.php +++ b/htdocs/core/modules/modCategorie.class.php @@ -127,7 +127,7 @@ class modCategorie extends DolibarrModules $this->export_permission[$r] = array(array("categorie", "lire")); $typeexample = ""; - if (isModEnabled("product") || !empty($conf->service->enabled)) { + if (isModEnabled("product") || isModEnabled("service")) { $typeexample .= ($typeexample ? " / " : "")."0=Product-Service"; } if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { diff --git a/htdocs/core/modules/propale/doc/pdf_azur.modules.php b/htdocs/core/modules/propale/doc/pdf_azur.modules.php index 91cc9010f18..bb6389a2e67 100644 --- a/htdocs/core/modules/propale/doc/pdf_azur.modules.php +++ b/htdocs/core/modules/propale/doc/pdf_azur.modules.php @@ -817,13 +817,13 @@ class pdf_azur extends ModelePDFPropales if (!empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) { if (isModEnabled("product")) { $filetomerge_dir = $conf->product->multidir_output[$entity_product_file].'/'.get_exdir($product->id, 2, 0, 0, $product, 'product').$product->id."/photos"; - } elseif (!empty($conf->service->enabled)) { + } elseif (isModEnabled("service")) { $filetomerge_dir = $conf->service->multidir_output[$entity_product_file].'/'.get_exdir($product->id, 2, 0, 0, $product, 'product').$product->id."/photos"; } } else { if (isModEnabled("product")) { $filetomerge_dir = $conf->product->multidir_output[$entity_product_file].'/'.get_exdir(0, 0, 0, 0, $product, 'product'); - } elseif (!empty($conf->service->enabled)) { + } elseif (isModEnabled("service")) { $filetomerge_dir = $conf->service->multidir_output[$entity_product_file].'/'.get_exdir(0, 0, 0, 0, $product, 'product'); } } diff --git a/htdocs/core/modules/propale/doc/pdf_cyan.modules.php b/htdocs/core/modules/propale/doc/pdf_cyan.modules.php index b8e002196a9..7be7170edb2 100644 --- a/htdocs/core/modules/propale/doc/pdf_cyan.modules.php +++ b/htdocs/core/modules/propale/doc/pdf_cyan.modules.php @@ -942,13 +942,13 @@ class pdf_cyan extends ModelePDFPropales if (!empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) { if (isModEnabled("product")) { $filetomerge_dir = $conf->product->multidir_output[$entity_product_file].'/'.get_exdir($product->id, 2, 0, 0, $product, 'product').$product->id."/photos"; - } elseif (!empty($conf->service->enabled)) { + } elseif (isModEnabled("service")) { $filetomerge_dir = $conf->service->multidir_output[$entity_product_file].'/'.get_exdir($product->id, 2, 0, 0, $product, 'product').$product->id."/photos"; } } else { if (isModEnabled("product")) { $filetomerge_dir = $conf->product->multidir_output[$entity_product_file].'/'.get_exdir(0, 0, 0, 0, $product, 'product'); - } elseif (!empty($conf->service->enabled)) { + } elseif (isModEnabled("service")) { $filetomerge_dir = $conf->service->multidir_output[$entity_product_file].'/'.get_exdir(0, 0, 0, 0, $product, 'product'); } } diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index c641cdf68de..cb38d7a3546 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -193,7 +193,7 @@ if ($nolinesbefore) { // Free line echo ''; // Show radio free line - if ($forceall >= 0 && (isModEnabled("product") || !empty($conf->service->enabled))) { + if ($forceall >= 0 && (isModEnabled("product") || isModEnabled("service"))) { echo ''; } // Predefined product/service - if (isModEnabled("product") || !empty($conf->service->enabled)) { + if (isModEnabled("product") || isModEnabled("service")) { if ($forceall >= 0 && $freelines) { echo '
'; } else { @@ -232,7 +232,7 @@ if ($nolinesbefore) { if (empty($senderissupplier)) { if (isModEnabled("product") && empty($conf->service->enabled)) { $labelforradio = $langs->trans('PredefinedProductsToSell'); - } elseif ((empty($conf->product->enabled) && !empty($conf->service->enabled)) || ($object->element == 'contrat' && empty($conf->global->CONTRACT_SUPPORT_PRODUCTS))) { + } elseif ((empty($conf->product->enabled) && isModEnabled("service")) || ($object->element == 'contrat' && empty($conf->global->CONTRACT_SUPPORT_PRODUCTS))) { $labelforradio = $langs->trans('PredefinedServicesToSell'); } else { $labelforradio = $langs->trans('PredefinedProductsAndServicesToSell'); @@ -240,7 +240,7 @@ if ($nolinesbefore) { } else { if (isModEnabled("product") && empty($conf->service->enabled)) { $labelforradio = $langs->trans('PredefinedProductsToPurchase'); - } elseif (empty($conf->product->enabled) && !empty($conf->service->enabled)) { + } elseif (empty($conf->product->enabled) && isModEnabled("service")) { $labelforradio = $langs->trans('PredefinedServicesToPurchase'); } else { $labelforradio = $langs->trans('PredefinedProductsAndServicesToPurchase'); @@ -336,7 +336,7 @@ if ($nolinesbefore) { print $hookmanager->resPrint; } } - if (isModEnabled("product") || !empty($conf->service->enabled)) { + if (isModEnabled("product") || isModEnabled("service")) { echo '
'; if (!empty($conf->variants->enabled)) { echo '
'; @@ -356,7 +356,7 @@ if ($nolinesbefore) { $doleditor = new DolEditor('dp_desc', GETPOST('dp_desc', 'restricthtml'), '', (empty($conf->global->MAIN_DOLEDITOR_HEIGHT) ? 100 : $conf->global->MAIN_DOLEDITOR_HEIGHT), $toolbarname, '', false, true, $enabled, $nbrows, '98%'); $doleditor->Create(); // Show autofill date for recurring invoices - if (!empty($conf->service->enabled) && ($object->element == 'facturerec' || $object->element == 'invoice_supplier_rec')) { + if (isModEnabled("service") && ($object->element == 'facturerec' || $object->element == 'invoice_supplier_rec')) { echo '

'; echo $langs->trans('AutoFillDateFrom').' '; if (!empty($conf->global->INVOICE_REC_DATE_TO_YES)) { @@ -446,7 +446,7 @@ if ($nolinesbefore) { ?>
service->enabled) || ($object->element == 'contrat')) && $dateSelector && GETPOST('type') != '0') { // We show date field if required +if ((isModEnabled("service") || ($object->element == 'contrat')) && $dateSelector && GETPOST('type') != '0') { // We show date field if required print ''."\n"; if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER)) { print ''; diff --git a/htdocs/core/tpl/objectline_edit.tpl.php b/htdocs/core/tpl/objectline_edit.tpl.php index 83e6ff2da7c..21e82d306a8 100644 --- a/htdocs/core/tpl/objectline_edit.tpl.php +++ b/htdocs/core/tpl/objectline_edit.tpl.php @@ -176,7 +176,7 @@ $coldisplay++; } // Show autofill date for recuring invoices - if (!empty($conf->service->enabled) && $line->product_type == 1 && ($line->element == 'facturedetrec' || $line->element == 'invoice_supplier_det_rec')) { + if (isModEnabled("service") && $line->product_type == 1 && ($line->element == 'facturedetrec' || $line->element == 'invoice_supplier_det_rec')) { if ($line->element == 'invoice_supplier_det_rec') { $line->date_start_fill = $line->date_start; $line->date_end_fill = $line->date_end; @@ -290,7 +290,7 @@ $coldisplay++; ?> -service->enabled) && $line->product_type == 1 && $dateSelector) { ?> +product_type == 1 && $dateSelector) { ?> global->MAIN_VIEW_LINE_NUMBER)) { ?> diff --git a/htdocs/delivery/card.php b/htdocs/delivery/card.php index 667ab889547..ac2aaa9b4e9 100644 --- a/htdocs/delivery/card.php +++ b/htdocs/delivery/card.php @@ -34,7 +34,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/sendings.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; -if (isModEnabled("product") || !empty($conf->service->enabled)) { +if (isModEnabled("product") || isModEnabled("service")) { require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; } if (!empty($conf->expedition_bon->enabled)) { diff --git a/htdocs/ecm/index_auto.php b/htdocs/ecm/index_auto.php index ffc1d1b7dd7..c488ff901bd 100644 --- a/htdocs/ecm/index_auto.php +++ b/htdocs/ecm/index_auto.php @@ -309,9 +309,9 @@ llxHeader($moreheadcss.$moreheadjs, $langs->trans("ECMArea"), '', '', '', '', $m $rowspan = 0; $sectionauto = array(); if (!empty($conf->global->ECM_AUTO_TREE_ENABLED)) { - if (isModEnabled("product") || !empty($conf->service->enabled)) { + if (isModEnabled("product") || isModEnabled("service")) { $langs->load("products"); - $rowspan++; $sectionauto[] = array('position'=>10, 'level'=>1, 'module'=>'product', 'test'=>(isModEnabled("product") || !empty($conf->service->enabled)), 'label'=>$langs->trans("ProductsAndServices"), 'desc'=>$langs->trans("ECMDocsByProducts")); + $rowspan++; $sectionauto[] = array('position'=>10, 'level'=>1, 'module'=>'product', 'test'=>(isModEnabled("product") || isModEnabled("service")), 'label'=>$langs->trans("ProductsAndServices"), 'desc'=>$langs->trans("ECMDocsByProducts")); } if (isModEnabled("societe")) { $rowspan++; $sectionauto[] = array('position'=>20, 'level'=>1, 'module'=>'company', 'test'=>$conf->societe->enabled, 'label'=>$langs->trans("ThirdParties"), 'desc'=>$langs->trans("ECMDocsBy", $langs->transnoentitiesnoconv("ThirdParties"))); diff --git a/htdocs/ecm/search.php b/htdocs/ecm/search.php index f52ea3233ab..4ada152d9ce 100644 --- a/htdocs/ecm/search.php +++ b/htdocs/ecm/search.php @@ -113,8 +113,8 @@ $userstatic = new User($db); // Ajout rubriques automatiques $rowspan = 0; $sectionauto = array(); -if (isModEnabled("product") || !empty($conf->service->enabled)) { - $langs->load("products"); $rowspan++; $sectionauto[] = array('level'=>1, 'module'=>'product', 'test'=>(isModEnabled("product") || !empty($conf->service->enabled)), 'label'=>$langs->trans("ProductsAndServices"), 'desc'=>$langs->trans("ECMDocsByProducts")); +if (isModEnabled("product") || isModEnabled("service")) { + $langs->load("products"); $rowspan++; $sectionauto[] = array('level'=>1, 'module'=>'product', 'test'=>(isModEnabled("product") || isModEnabled("service")), 'label'=>$langs->trans("ProductsAndServices"), 'desc'=>$langs->trans("ECMDocsByProducts")); } if (isModEnabled("societe")) { $rowspan++; $sectionauto[] = array('level'=>1, 'module'=>'company', 'test'=>$conf->societe->enabled, 'label'=>$langs->trans("ThirdParties"), 'desc'=>$langs->trans("ECMDocsBy", $langs->transnoentitiesnoconv("ThirdParties"))); diff --git a/htdocs/expedition/card.php b/htdocs/expedition/card.php index 30806231916..62e8b4337d3 100644 --- a/htdocs/expedition/card.php +++ b/htdocs/expedition/card.php @@ -47,7 +47,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php'; require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; -if (isModEnabled("product") || !empty($conf->service->enabled)) { +if (isModEnabled("product") || isModEnabled("service")) { require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; } if (isModEnabled("propal")) { diff --git a/htdocs/expedition/shipment.php b/htdocs/expedition/shipment.php index c42ae6ec296..0be623ab6bf 100644 --- a/htdocs/expedition/shipment.php +++ b/htdocs/expedition/shipment.php @@ -43,7 +43,7 @@ if (!empty($conf->stock->enabled)) { if (isModEnabled("propal")) { require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php'; } -if (isModEnabled("product") || !empty($conf->service->enabled)) { +if (isModEnabled("product") || isModEnabled("service")) { require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; } diff --git a/htdocs/fourn/card.php b/htdocs/fourn/card.php index 2f44253579a..ba72cd352be 100644 --- a/htdocs/fourn/card.php +++ b/htdocs/fourn/card.php @@ -514,7 +514,7 @@ if ($object->id > 0) { /* * List of products */ - if (isModEnabled("product") || !empty($conf->service->enabled)) { + if (isModEnabled("product") || isModEnabled("service")) { $langs->load("products"); //Query from product/liste.php $sql = 'SELECT p.rowid, p.ref, p.label, p.fk_product_type, p.entity, p.tosell as status, p.tobuy as status_buy, p.tobatch as status_batch,'; diff --git a/htdocs/intracommreport/list.php b/htdocs/intracommreport/list.php index 1478dbea83f..2c47ab3c7a2 100644 --- a/htdocs/intracommreport/list.php +++ b/htdocs/intracommreport/list.php @@ -121,7 +121,7 @@ $isInEEC = isInEEC($mysoc); $arrayfields = array( 'i.ref' => array('label'=>$langs->trans("Ref"), 'checked'=>1), 'i.label' => array('label'=>$langs->trans("Label"), 'checked'=>1), - 'i.fk_product_type'=>array('label'=>$langs->trans("Type"), 'checked'=>0, 'enabled'=>(!empty($conf->produit->enabled) && !empty($conf->service->enabled))), + 'i.fk_product_type'=>array('label'=>$langs->trans("Type"), 'checked'=>0, 'enabled'=>(!empty($conf->produit->enabled) && isModEnabled("service"))), ); /* // Extra fields diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 23699875474..9f709a86e47 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -2521,7 +2521,7 @@ function printDropdownQuickadd() "title" => "NewService@products", "name" => "Service@products", "picto" => "object_service", - "activation" => !empty($conf->service->enabled) && $user->hasRight("service", "write"), // vs hooking + "activation" => isModEnabled("service") && $user->hasRight("service", "write"), // vs hooking "position" => 110, ), array( diff --git a/htdocs/product/card.php b/htdocs/product/card.php index ed921208624..761fe2a148f 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -138,7 +138,7 @@ if ($id > 0 || !empty($ref)) { } if (isModEnabled("product")) { $upload_dir = $conf->product->multidir_output[$object->entity].'/'.get_exdir(0, 0, 0, 0, $object, 'product').dol_sanitizeFileName($object->ref); - } elseif (!empty($conf->service->enabled)) { + } elseif (isModEnabled("service")) { $upload_dir = $conf->service->multidir_output[$object->entity].'/'.get_exdir(0, 0, 0, 0, $object, 'product').dol_sanitizeFileName($object->ref); } @@ -2298,7 +2298,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print '
'; print (empty($conf->global->PRODUCT_DENY_CHANGE_PRODUCT_TYPE)) ? $form->editfieldkey("Type", 'fk_product_type', $object->type, $object, $usercancreate, $typeformat) : $langs->trans('Type'); diff --git a/htdocs/webservices/admin/index.php b/htdocs/webservices/admin/index.php index 8ae62d1bf3c..d688c16b870 100644 --- a/htdocs/webservices/admin/index.php +++ b/htdocs/webservices/admin/index.php @@ -100,11 +100,11 @@ print '

'; // Webservices list $webservices = array( 'user' => '', - 'thirdparty' => '!empty($conf->societe->enabled)', - 'contact' => '!empty($conf->societe->enabled)', - 'productorservice' => '(!empty($conf->product->enabled) || !empty($conf->service->enabled))', + 'thirdparty' => 'isModEnabled("societe")', + 'contact' => 'isModEnabled("societe")', + 'productorservice' => '(isModEnabled("product") || !empty($conf->service->enabled))', 'order' => '!empty($conf->commande->enabled)', - 'invoice' => '!empty($conf->facture->enabled)', + 'invoice' => 'isModEnabled("facture")', 'supplier_invoice' => '!empty($conf->fournisseur->enabled)', 'actioncomm' => '!empty($conf->agenda->enabled)', 'category' => '!empty($conf->categorie->enabled)', From 582f6b196e8c972fc7e11d83b41244bcbb46abe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20France?= Date: Tue, 23 Aug 2022 20:02:37 +0200 Subject: [PATCH 769/826] use isModEnabled --- htdocs/adherents/admin/member.php | 4 ++-- htdocs/adherents/class/adherent.class.php | 2 +- htdocs/admin/eventorganization.php | 2 +- htdocs/admin/fckeditor.php | 2 +- htdocs/admin/hrm.php | 2 +- htdocs/admin/webhook.php | 2 +- htdocs/asset/admin/setup.php | 2 +- htdocs/bom/tpl/objectline_create.tpl.php | 2 +- htdocs/comm/propal/card.php | 2 +- htdocs/core/boxes/box_produits.php | 2 +- htdocs/core/boxes/box_produits_alerte_stock.php | 2 +- htdocs/core/class/html.form.class.php | 8 ++++---- htdocs/core/class/html.formbarcode.class.php | 2 +- htdocs/core/class/html.formmargin.class.php | 4 ++-- htdocs/core/class/html.formsetup.class.php | 2 +- htdocs/core/lib/files.lib.php | 2 +- htdocs/core/lib/product.lib.php | 4 ++-- htdocs/core/modules/DolibarrModules.class.php | 2 +- htdocs/core/modules/modCategorie.class.php | 2 +- .../modules/propale/doc/pdf_azur.modules.php | 4 ++-- .../modules/propale/doc/pdf_cyan.modules.php | 4 ++-- htdocs/core/tpl/objectline_create.tpl.php | 16 ++++++++-------- htdocs/core/tpl/objectline_edit.tpl.php | 6 +++--- htdocs/delivery/card.php | 2 +- htdocs/ecm/index_auto.php | 4 ++-- htdocs/ecm/search.php | 4 ++-- htdocs/expedition/card.php | 2 +- htdocs/expedition/shipment.php | 2 +- htdocs/fourn/card.php | 2 +- htdocs/intracommreport/list.php | 2 +- htdocs/main.inc.php | 2 +- htdocs/product/card.php | 4 ++-- htdocs/product/composition/card.php | 2 +- htdocs/product/document.php | 2 +- htdocs/product/fournisseurs.php | 2 +- htdocs/product/index.php | 10 +++++----- htdocs/product/list.php | 4 ++-- htdocs/product/price.php | 6 +++--- htdocs/product/reassort.php | 6 +++--- htdocs/product/reassortlot.php | 6 +++--- htdocs/product/stock/product.php | 2 +- htdocs/product/stock/replenish.php | 6 +++--- htdocs/reception/card.php | 2 +- htdocs/resource/element_resource.php | 2 +- htdocs/takepos/admin/setup.php | 2 +- htdocs/user/param_ihm.php | 2 +- htdocs/variants/combinations.php | 2 +- htdocs/webservices/admin/index.php | 2 +- 48 files changed, 81 insertions(+), 81 deletions(-) diff --git a/htdocs/adherents/admin/member.php b/htdocs/adherents/admin/member.php index 12ce3973c32..2ffed8b8d97 100644 --- a/htdocs/adherents/admin/member.php +++ b/htdocs/adherents/admin/member.php @@ -111,7 +111,7 @@ if ($action == 'set_default') { if (isModEnabled('facture')) { $res4 = dolibarr_set_const($db, 'ADHERENT_VAT_FOR_SUBSCRIPTIONS', GETPOST('ADHERENT_VAT_FOR_SUBSCRIPTIONS', 'alpha'), 'chaine', 0, '', $conf->entity); $res5 = dolibarr_set_const($db, 'ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS', GETPOST('ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS', 'alpha'), 'chaine', 0, '', $conf->entity); - if (isModEnabled("product") || !empty($conf->service->enabled)) { + if (isModEnabled("product") || isModEnabled("service")) { $res6 = dolibarr_set_const($db, 'ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS', GETPOST('ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS', 'alpha'), 'chaine', 0, '', $conf->entity); } } @@ -269,7 +269,7 @@ if (isModEnabled('facture')) { } print "
'.$langs->trans("ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS").''; $selected = (empty($conf->global->ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS) ? '' : $conf->global->ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS); diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 185213db838..1f93e87f1ab 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -1773,7 +1773,7 @@ class Adherent extends CommonObject if (!$error) { // Add line to draft invoice $idprodsubscription = 0; - if (!empty($conf->global->ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS) && (isModEnabled("product") || !empty($conf->service->enabled))) { + if (!empty($conf->global->ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS) && (isModEnabled("product") || isModEnabled("service"))) { $idprodsubscription = $conf->global->ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS; } diff --git a/htdocs/admin/eventorganization.php b/htdocs/admin/eventorganization.php index afeaa98d77e..40c86d79e13 100644 --- a/htdocs/admin/eventorganization.php +++ b/htdocs/admin/eventorganization.php @@ -278,7 +278,7 @@ if ($action == 'edit') { include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; print dolJSToSetRandomPassword($constname, 'generate_token'.$constname); } elseif ($val['type'] == 'product') { - if (isModEnabled("product") || !empty($conf->service->enabled)) { + if (isModEnabled("product") || isModEnabled("service")) { $selected = (empty($conf->global->$constname) ? '' : $conf->global->$constname); $form->select_produits($selected, $constname, '', 0); } diff --git a/htdocs/admin/fckeditor.php b/htdocs/admin/fckeditor.php index c74645439bd..25386388020 100644 --- a/htdocs/admin/fckeditor.php +++ b/htdocs/admin/fckeditor.php @@ -62,7 +62,7 @@ $conditions = array( 'NOTE_PUBLIC' => 1, 'NOTE_PRIVATE' => 1, 'SOCIETE' => 1, - 'PRODUCTDESC' => (isModEnabled("product") || !empty($conf->service->enabled)), + 'PRODUCTDESC' => (isModEnabled("product") || isModEnabled("service")), 'DETAILS' => (isModEnabled('facture') || isModEnabled("propal") || !empty($conf->commande->enabled) || !empty($conf->supplier_proposal->enabled) || (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)), 'USERSIGN' => 1, 'MAILING' => !empty($conf->mailing->enabled), diff --git a/htdocs/admin/hrm.php b/htdocs/admin/hrm.php index 2f90d6e9a77..3bc1e3a12d4 100644 --- a/htdocs/admin/hrm.php +++ b/htdocs/admin/hrm.php @@ -545,7 +545,7 @@ if ($action == 'edit') { include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; print dolJSToSetRandomPassword($constname, 'generate_token'.$constname); } elseif ($val['type'] == 'product') { - if (isModEnabled("product") || !empty($conf->service->enabled)) { + if (isModEnabled("product") || isModEnabled("service")) { $selected = (empty($conf->global->$constname) ? '' : $conf->global->$constname); $form->select_produits($selected, $constname, '', 0); } diff --git a/htdocs/admin/webhook.php b/htdocs/admin/webhook.php index 4527df95d89..b589eac4079 100644 --- a/htdocs/admin/webhook.php +++ b/htdocs/admin/webhook.php @@ -343,7 +343,7 @@ if ($action == 'edit') { include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; print dolJSToSetRandomPassword($constname, 'generate_token'.$constname); } elseif ($val['type'] == 'product') { - if (isModEnabled("product") || !empty($conf->service->enabled)) { + if (isModEnabled("product") || isModEnabled("service")) { $selected = (empty($conf->global->$constname) ? '' : $conf->global->$constname); $form->select_produits($selected, $constname, '', 0); } diff --git a/htdocs/asset/admin/setup.php b/htdocs/asset/admin/setup.php index 64025c9b18a..4f8f06ca160 100644 --- a/htdocs/asset/admin/setup.php +++ b/htdocs/asset/admin/setup.php @@ -524,7 +524,7 @@ if ($action == 'edit') { include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; print dolJSToSetRandomPassword($constname, 'generate_token'.$constname); } elseif ($val['type'] == 'product') { - if (isModEnabled("product") || !empty($conf->service->enabled)) { + if (isModEnabled("product") || isModEnabled("service")) { $selected = (empty($conf->global->$constname) ? '' : $conf->global->$constname); $form->select_produits($selected, $constname, '', 0); } diff --git a/htdocs/bom/tpl/objectline_create.tpl.php b/htdocs/bom/tpl/objectline_create.tpl.php index cd29623af8c..e895d534fac 100644 --- a/htdocs/bom/tpl/objectline_create.tpl.php +++ b/htdocs/bom/tpl/objectline_create.tpl.php @@ -87,7 +87,7 @@ $coldisplay++; print ''; // Predefined product/service -if (isModEnabled("product") || !empty($conf->service->enabled)) { +if (isModEnabled("product") || isModEnabled("service")) { if (!empty($conf->global->BOM_SUB_BOM)) { print $langs->trans("Product"); } diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index c88ffdad6eb..52fc2a296e4 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -2814,7 +2814,7 @@ if ($action == 'create') { } // Create an intervention - if (!empty($conf->service->enabled) && !empty($conf->ficheinter->enabled) && $object->statut == Propal::STATUS_SIGNED) { + if (isModEnabled("service") && !empty($conf->ficheinter->enabled) && $object->statut == Propal::STATUS_SIGNED) { if ($usercancreateintervention) { $langs->load("interventions"); print ''.$langs->trans("AddIntervention").''; diff --git a/htdocs/core/boxes/box_produits.php b/htdocs/core/boxes/box_produits.php index ed4dea21cc1..7a9518d345e 100644 --- a/htdocs/core/boxes/box_produits.php +++ b/htdocs/core/boxes/box_produits.php @@ -62,7 +62,7 @@ class box_produits extends ModeleBoxes $this->db = $db; $listofmodulesforexternal = explode(',', $conf->global->MAIN_MODULES_FOR_EXTERNAL); - $tmpentry = array('enabled'=>(isModEnabled("product") || !empty($conf->service->enabled)), 'perms'=>(!empty($user->rights->produit->lire) || !empty($user->rights->service->lire)), 'module'=>'product|service'); + $tmpentry = array('enabled'=>(isModEnabled("product") || isModEnabled("service")), 'perms'=>(!empty($user->rights->produit->lire) || !empty($user->rights->service->lire)), 'module'=>'product|service'); $showmode = isVisibleToUserType(($user->socid > 0 ? 1 : 0), $tmpentry, $listofmodulesforexternal); $this->hidden = ($showmode != 1); } diff --git a/htdocs/core/boxes/box_produits_alerte_stock.php b/htdocs/core/boxes/box_produits_alerte_stock.php index 16370917dbd..203d42c7eed 100644 --- a/htdocs/core/boxes/box_produits_alerte_stock.php +++ b/htdocs/core/boxes/box_produits_alerte_stock.php @@ -64,7 +64,7 @@ class box_produits_alerte_stock extends ModeleBoxes $this->db = $db; $listofmodulesforexternal = explode(',', $conf->global->MAIN_MODULES_FOR_EXTERNAL); - $tmpentry = array('enabled'=>((isModEnabled("product") || !empty($conf->service->enabled)) && !empty($conf->stock->enabled)), 'perms'=>!empty($user->rights->stock->lire), 'module'=>'product|service|stock'); + $tmpentry = array('enabled'=>((isModEnabled("product") || isModEnabled("service")) && !empty($conf->stock->enabled)), 'perms'=>!empty($user->rights->stock->lire), 'module'=>'product|service|stock'); $showmode = isVisibleToUserType(($user->socid > 0 ? 1 : 0), $tmpentry, $listofmodulesforexternal); $this->hidden = ($showmode != 1); } diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index b6da0e8822e..6755bd29c14 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -1104,7 +1104,7 @@ class Form global $langs, $conf; // If product & services are enabled or both disabled. - if ($forceall == 1 || (empty($forceall) && isModEnabled("product") && !empty($conf->service->enabled)) + if ($forceall == 1 || (empty($forceall) && isModEnabled("product") && isModEnabled("service")) || (empty($forceall) && empty($conf->product->enabled) && empty($conf->service->enabled))) { if (empty($hidetext)) { print $langs->trans("Type").': '; @@ -1134,7 +1134,7 @@ class Form print ajax_combobox('select_'.$htmlname); //if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"),1); } - if ((empty($forceall) && empty($conf->product->enabled) && !empty($conf->service->enabled)) || $forceall == 3) { + if ((empty($forceall) && empty($conf->product->enabled) && isModEnabled("service")) || $forceall == 3) { print $langs->trans("Service"); print ''; } @@ -2278,10 +2278,10 @@ class Form $ajaxoptions = array(); } - if (strval($filtertype) === '' && (isModEnabled("product") || !empty($conf->service->enabled))) { + if (strval($filtertype) === '' && (isModEnabled("product") || isModEnabled("service"))) { if (isModEnabled("product") && empty($conf->service->enabled)) { $filtertype = '0'; - } elseif (empty($conf->product->enabled) && !empty($conf->service->enabled)) { + } elseif (empty($conf->product->enabled) && isModEnabled("service")) { $filtertype = '1'; } } diff --git a/htdocs/core/class/html.formbarcode.class.php b/htdocs/core/class/html.formbarcode.class.php index def8be3cd40..9b2b9082a53 100644 --- a/htdocs/core/class/html.formbarcode.class.php +++ b/htdocs/core/class/html.formbarcode.class.php @@ -80,7 +80,7 @@ class FormBarCode } // We check if barcode is already selected by default - if (((isModEnabled("product") || !empty($conf->service->enabled)) && $conf->global->PRODUIT_DEFAULT_BARCODE_TYPE == $code_id) || + if (((isModEnabled("product") || isModEnabled("service")) && $conf->global->PRODUIT_DEFAULT_BARCODE_TYPE == $code_id) || (isModEnabled("societe") && $conf->global->GENBARCODE_BARCODETYPE_THIRDPARTY == $code_id)) { $disable = 'disabled'; } diff --git a/htdocs/core/class/html.formmargin.class.php b/htdocs/core/class/html.formmargin.class.php index 8f6c911a095..38ec91ff143 100644 --- a/htdocs/core/class/html.formmargin.class.php +++ b/htdocs/core/class/html.formmargin.class.php @@ -270,7 +270,7 @@ class FormMargin print '
' . $langs->trans('MarginOnServices') . '' . price($marginInfo['pv_services']) . '
' . $langs->trans('TotalMargin') . '' . price($marginInfo['pv_total']) . ' - service->enabled)) { ?> + @@ -471,7 +471,7 @@ if ($nolinesbefore) {
- service->enabled)) { ?> + @@ -330,7 +330,7 @@ $coldisplay++;
'; // Type - if (isModEnabled("product") && !empty($conf->service->enabled)) { + if (isModEnabled("product") && isModEnabled("service")) { $typeformat = 'select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service"); print '
'; print (empty($conf->global->PRODUCT_DENY_CHANGE_PRODUCT_TYPE)) ? $form->editfieldkey("Type", 'fk_product_type', $object->type, $object, $usercancreate, $typeformat) : $langs->trans('Type'); diff --git a/htdocs/product/composition/card.php b/htdocs/product/composition/card.php index 613ff2c3ca8..e6a3b3171bc 100644 --- a/htdocs/product/composition/card.php +++ b/htdocs/product/composition/card.php @@ -231,7 +231,7 @@ if ($id > 0 || !empty($ref)) { print ''; // Type - if (isModEnabled("product") && !empty($conf->service->enabled)) { + if (isModEnabled("product") && isModEnabled("service")) { $typeformat = 'select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service"); print '
'; print (empty($conf->global->PRODUCT_DENY_CHANGE_PRODUCT_TYPE)) ? $form->editfieldkey("Type", 'fk_product_type', $object->type, $object, $usercancreate, $typeformat) : $langs->trans('Type'); diff --git a/htdocs/product/document.php b/htdocs/product/document.php index b396041af83..d83a684a308 100644 --- a/htdocs/product/document.php +++ b/htdocs/product/document.php @@ -81,7 +81,7 @@ if ($id > 0 || !empty($ref)) { if (isModEnabled("product")) { $upload_dir = $conf->product->multidir_output[$object->entity].'/'.get_exdir(0, 0, 0, 1, $object, 'product'); - } elseif (!empty($conf->service->enabled)) { + } elseif (isModEnabled("service")) { $upload_dir = $conf->service->multidir_output[$object->entity].'/'.get_exdir(0, 0, 0, 1, $object, 'product'); } diff --git a/htdocs/product/fournisseurs.php b/htdocs/product/fournisseurs.php index f5ee4cbf1c4..55cbbf8e34a 100644 --- a/htdocs/product/fournisseurs.php +++ b/htdocs/product/fournisseurs.php @@ -397,7 +397,7 @@ if ($id > 0 || $ref) { print ''; // Type - if (isModEnabled("product") && !empty($conf->service->enabled)) { + if (isModEnabled("product") && isModEnabled("service")) { $typeformat = 'select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service"); print ''; } else { // Type - if (isModEnabled("product") && !empty($conf->service->enabled)) { + if (isModEnabled("product") && isModEnabled("service")) { $typeformat = 'select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service"); print ''; // Duration - if (!empty($conf->service->enabled) && $type == 1) { + if (isModEnabled("service") && $type == 1) { print ''; @@ -400,7 +400,7 @@ if ($resql) { print ""; print_liste_field_titre("Ref", $_SERVER["PHP_SELF"], "p.ref", '', $param, "", $sortfield, $sortorder); print_liste_field_titre("Label", $_SERVER["PHP_SELF"], "p.label", '', $param, "", $sortfield, $sortorder); - if (!empty($conf->service->enabled) && $type == 1) { + if (isModEnabled("service") && $type == 1) { print_liste_field_titre("Duration", $_SERVER["PHP_SELF"], "p.duration", '', $param, "", $sortfield, $sortorder, 'center '); } print_liste_field_titre("StockLimit", $_SERVER["PHP_SELF"], "p.seuil_stock_alerte", '', $param, "", $sortfield, $sortorder, 'right '); @@ -445,7 +445,7 @@ if ($resql) { print ''; print ''; - if (!empty($conf->service->enabled) && $type == 1) { + if (isModEnabled("service") && $type == 1) { print ''; print ''; -if (!empty($conf->service->enabled) && $type == 1) { +if (isModEnabled("service") && $type == 1) { print ''; @@ -564,7 +564,7 @@ $totalarray['nbfield'] = 0; print ''; print_liste_field_titre("Ref", $_SERVER["PHP_SELF"], "p.ref", '', $param, "", $sortfield, $sortorder); print_liste_field_titre("Label", $_SERVER["PHP_SELF"], "p.label", '', $param, "", $sortfield, $sortorder); -if (!empty($conf->service->enabled) && $type == 1) { +if (isModEnabled("service") && $type == 1) { print_liste_field_titre("Duration", $_SERVER["PHP_SELF"], "p.duration", '', $param, "", $sortfield, $sortorder, 'center '); } print_liste_field_titre("Warehouse", $_SERVER["PHP_SELF"], "e.ref", '', $param, "", $sortfield, $sortorder); @@ -648,7 +648,7 @@ while ($i < $imaxinloop) { // Label print ''; - if (!empty($conf->service->enabled) && $type == 1) { + if (isModEnabled("service") && $type == 1) { print '
'; print (empty($conf->global->PRODUCT_DENY_CHANGE_PRODUCT_TYPE)) ? $form->editfieldkey("Type", 'fk_product_type', $object->type, $object, 0, $typeformat) : $langs->trans('Type'); diff --git a/htdocs/product/index.php b/htdocs/product/index.php index 540d685ca7e..f2b29926b21 100644 --- a/htdocs/product/index.php +++ b/htdocs/product/index.php @@ -90,7 +90,7 @@ print '
'; if (!empty($conf->global->MAIN_SEARCH_FORM_ON_HOME_AREAS)) { // This may be useless due to the global search combo // Search contract - if ((isModEnabled("product") || !empty($conf->service->enabled)) && ($user->rights->produit->lire || $user->rights->service->lire)) { + if ((isModEnabled("product") || isModEnabled("service")) && ($user->rights->produit->lire || $user->rights->service->lire)) { $listofsearchfields['search_product'] = array('text'=>'ProductOrService'); } @@ -123,7 +123,7 @@ if (!empty($conf->global->MAIN_SEARCH_FORM_ON_HOME_AREAS)) { // This may be /* * Number of products and/or services */ -if ((isModEnabled("product") || !empty($conf->service->enabled)) && ($user->rights->produit->lire || $user->rights->service->lire)) { +if ((isModEnabled("product") || isModEnabled("service")) && ($user->rights->produit->lire || $user->rights->service->lire)) { $prodser = array(); $prodser[0][0] = $prodser[0][1] = $prodser[0][2] = $prodser[0][3] = 0; $prodser[0]['sell'] = 0; @@ -190,7 +190,7 @@ if ((isModEnabled("product") || !empty($conf->service->enabled)) && ($user->righ $dataseries[] = array($langs->transnoentitiesnoconv("ProductsOnPurchase"), round($SommeB)); $dataseries[] = array($langs->transnoentitiesnoconv("ProductsNotOnSell"), round($SommeC)); } - if (!empty($conf->service->enabled)) { + if (isModEnabled("service")) { $dataseries[] = array($langs->transnoentitiesnoconv("ServicesOnSale"), round($SommeD)); $dataseries[] = array($langs->transnoentitiesnoconv("ServicesOnPurchase"), round($SommeE)); $dataseries[] = array($langs->transnoentitiesnoconv("ServicesNotOnSell"), round($SommeF)); @@ -281,7 +281,7 @@ print '
'; /* * Latest modified products */ -if ((isModEnabled("product") || !empty($conf->service->enabled)) && ($user->rights->produit->lire || $user->rights->service->lire)) { +if ((isModEnabled("product") || isModEnabled("service")) && ($user->rights->produit->lire || $user->rights->service->lire)) { $max = 15; $sql = "SELECT p.rowid, p.label, p.price, p.ref, p.fk_product_type, p.tosell, p.tobuy, p.tobatch, p.fk_price_expression,"; $sql .= " p.entity,"; @@ -411,7 +411,7 @@ if (!empty($conf->global->MAIN_SHOW_PRODUCT_ACTIVITY_TRIM)) { if (isModEnabled("product")) { activitytrim(0); } - if (!empty($conf->service->enabled)) { + if (isModEnabled("service")) { activitytrim(1); } } diff --git a/htdocs/product/list.php b/htdocs/product/list.php index 3299d8afcf1..043a6bc3db8 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -206,9 +206,9 @@ $arrayfields = array( //'pfp.ref_fourn'=>array('label'=>$langs->trans("RefSupplier"), 'checked'=>1, 'enabled'=>(! empty($conf->barcode->enabled))), 'thumbnail'=>array('label'=>'Photo', 'checked'=>0, 'position'=>10), 'p.label'=>array('label'=>"Label", 'checked'=>1, 'position'=>10), - 'p.fk_product_type'=>array('label'=>"Type", 'checked'=>0, 'enabled'=>(isModEnabled("product") && !empty($conf->service->enabled)), 'position'=>11), + 'p.fk_product_type'=>array('label'=>"Type", 'checked'=>0, 'enabled'=>(isModEnabled("product") && isModEnabled("service")), 'position'=>11), 'p.barcode'=>array('label'=>"Gencod", 'checked'=>1, 'enabled'=>(isModEnabled('barcode')), 'position'=>12), - 'p.duration'=>array('label'=>"Duration", 'checked'=>($contextpage != 'productlist'), 'enabled'=>(!empty($conf->service->enabled) && (string) $type == '1'), 'position'=>13), + 'p.duration'=>array('label'=>"Duration", 'checked'=>($contextpage != 'productlist'), 'enabled'=>(isModEnabled("service") && (string) $type == '1'), 'position'=>13), 'p.finished'=>array('label'=>"Nature", 'checked'=>0, 'enabled'=>(isModEnabled("product") && $type != '1'), 'position'=>19), 'p.weight'=>array('label'=>'Weight', 'checked'=>0, 'enabled'=>(isModEnabled("product") && $type != '1'), 'position'=>20), 'p.weight_units'=>array('label'=>'WeightUnits', 'checked'=>0, 'enabled'=>(isModEnabled("product") && $type != '1'), 'position'=>21), diff --git a/htdocs/product/price.php b/htdocs/product/price.php index 6acdafabcef..341b8a56e62 100644 --- a/htdocs/product/price.php +++ b/htdocs/product/price.php @@ -887,7 +887,7 @@ if (!empty($conf->global->PRODUIT_MULTIPRICES) || !empty($conf->global->PRODUIT_ $soc->fetch($socid); // Type - if (isModEnabled("product") && !empty($conf->service->enabled)) { + if (isModEnabled("product") && isModEnabled("service")) { $typeformat = 'select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service"); print '
'; print (empty($conf->global->PRODUCT_DENY_CHANGE_PRODUCT_TYPE)) ? $form->editfieldkey("Type", 'fk_product_type', $object->type, $object, 0, $typeformat) : $langs->trans('Type'); @@ -971,7 +971,7 @@ if (!empty($conf->global->PRODUIT_MULTIPRICES) || !empty($conf->global->PRODUIT_ } else { if (!empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL)) { // using this option is a bug. kept for backward compatibility // Type - if (isModEnabled("product") && !empty($conf->service->enabled)) { + if (isModEnabled("product") && isModEnabled("service")) { $typeformat = 'select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service"); print '
'; print (empty($conf->global->PRODUCT_DENY_CHANGE_PRODUCT_TYPE)) ? $form->editfieldkey("Type", 'fk_product_type', $object->type, $object, 0, $typeformat) : $langs->trans('Type'); @@ -986,7 +986,7 @@ if (!empty($conf->global->PRODUIT_MULTIPRICES) || !empty($conf->global->PRODUIT_ print '
'; print (empty($conf->global->PRODUCT_DENY_CHANGE_PRODUCT_TYPE)) ? $form->editfieldkey("Type", 'fk_product_type', $object->type, $object, 0, $typeformat) : $langs->trans('Type'); diff --git a/htdocs/product/reassort.php b/htdocs/product/reassort.php index f6065c9f744..10e70545af6 100644 --- a/htdocs/product/reassort.php +++ b/htdocs/product/reassort.php @@ -369,7 +369,7 @@ if ($resql) { print ''; print ''; print ' '; print '
'.$product->label.''; if (preg_match('/([0-9]+)y/i', $objp->duration, $regs)) { print $regs[1].' '.$langs->trans("DurationYear"); diff --git a/htdocs/product/reassortlot.php b/htdocs/product/reassortlot.php index 690d3f3f261..a39dc246772 100644 --- a/htdocs/product/reassortlot.php +++ b/htdocs/product/reassortlot.php @@ -511,7 +511,7 @@ print ''; print ''; print ''; print ' '; print '
'.$objp->label.''; if (preg_match('/([0-9]+)y/i', $objp->duration, $regs)) { print $regs[1].' '.$langs->trans("DurationYear"); diff --git a/htdocs/product/stock/product.php b/htdocs/product/stock/product.php index 2d9ec85303d..59ab97873da 100644 --- a/htdocs/product/stock/product.php +++ b/htdocs/product/stock/product.php @@ -622,7 +622,7 @@ if ($id > 0 || $ref) { print ''; // Type - if (isModEnabled("product") && !empty($conf->service->enabled)) { + if (isModEnabled("product") && isModEnabled("service")) { $typeformat = 'select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service"); print ''; print ''; print ''; print ''; -if (!empty($conf->service->enabled) && $type == 1) { +if (isModEnabled("service") && $type == 1) { print ''; } print ''; @@ -769,7 +769,7 @@ print ''; print_liste_field_titre('', $_SERVER["PHP_SELF"], ''); print_liste_field_titre('Ref', $_SERVER["PHP_SELF"], 'p.ref', $param, '', '', $sortfield, $sortorder); print_liste_field_titre('Label', $_SERVER["PHP_SELF"], 'p.label', $param, '', '', $sortfield, $sortorder); -if (!empty($conf->service->enabled) && $type == 1) { +if (isModEnabled("service") && $type == 1) { print_liste_field_titre('Duration', $_SERVER["PHP_SELF"], 'p.duration', $param, '', '', $sortfield, $sortorder, 'center '); } print_liste_field_titre('DesiredStock', $_SERVER["PHP_SELF"], 'p.desiredstock', $param, '', '', $sortfield, $sortorder, 'right '); @@ -899,7 +899,7 @@ while ($i < ($limit ? min($num, $limit) : $num)) { print ''; // TODO Remove this and make a fetch to get description when creating order instead of a GETPOST print ''; - if (!empty($conf->service->enabled) && $type == 1) { + if (isModEnabled("service") && $type == 1) { $regs = array(); if (preg_match('/([0-9]+)y/i', $objp->duration, $regs)) { $duration = $regs[1].' '.$langs->trans('DurationYear'); diff --git a/htdocs/reception/card.php b/htdocs/reception/card.php index 564ffbf899c..6fc1fd51349 100644 --- a/htdocs/reception/card.php +++ b/htdocs/reception/card.php @@ -44,7 +44,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php'; -if (isModEnabled("product") || !empty($conf->service->enabled)) { +if (isModEnabled("product") || isModEnabled("service")) { require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; } if (isModEnabled("propal")) { diff --git a/htdocs/resource/element_resource.php b/htdocs/resource/element_resource.php index ab85041a650..b4f76a93ae3 100644 --- a/htdocs/resource/element_resource.php +++ b/htdocs/resource/element_resource.php @@ -33,7 +33,7 @@ if (!empty($conf->project->enabled)) { require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php'; } -if (isModEnabled("product") || !empty($conf->service->enabled)) { +if (isModEnabled("product") || isModEnabled("service")) { require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; } diff --git a/htdocs/takepos/admin/setup.php b/htdocs/takepos/admin/setup.php index a21bf3de219..13c3b6ae80e 100644 --- a/htdocs/takepos/admin/setup.php +++ b/htdocs/takepos/admin/setup.php @@ -263,7 +263,7 @@ print '\n"; // Services -if (!empty($conf->service->enabled)) { +if (isModEnabled("service")) { print ''; } // Supplier orders - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->commande->lire) || (!empty($conf->supplier_order->enabled) && $user->rights->supplier_order->lire)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->commande->lire) || (isModEnabled("supplier_order") && $user->rights->supplier_order->lire)) { $nblines++; $ret = $product->load_stats_commande_fournisseur($socid); if ($ret < 0) { @@ -488,7 +488,7 @@ function show_stats_for_company($product, $socid) print ''; } // Supplier invoices - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->facture->lire) || (!empty($conf->supplier_invoice->enabled) && $user->rights->supplier_invoice->lire)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->facture->lire) || (isModEnabled("supplier_invoice") && $user->rights->supplier_invoice->lire)) { $nblines++; $ret = $product->load_stats_facture_fournisseur($socid); if ($ret < 0) { diff --git a/htdocs/core/lib/project.lib.php b/htdocs/core/lib/project.lib.php index 14dbbe81c70..8e514a505bf 100644 --- a/htdocs/core/lib/project.lib.php +++ b/htdocs/core/lib/project.lib.php @@ -124,7 +124,7 @@ function project_prepare_head(Project $project, $moreparam = '') $h++; } - if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) + if (((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) || isModEnabled("propal") || !empty($conf->commande->enabled) || isModEnabled('facture') || !empty($conf->contrat->enabled) || !empty($conf->ficheinter->enabled) || !empty($conf->agenda->enabled) || !empty($conf->deplacement->enabled) || !empty($conf->stock->enabled)) { @@ -153,10 +153,10 @@ function project_prepare_head(Project $project, $moreparam = '') if (!empty($conf->supplier_proposal->enabled)) { $nbElements += $project->getElementCount('proposal_supplier', 'supplier_proposal'); } - if (!empty($conf->supplier_order->enabled)) { + if (isModEnabled("supplier_order")) { $nbElements += $project->getElementCount('order_supplier', 'commande_fournisseur'); } - if (!empty($conf->supplier_invoice->enabled)) { + if (isModEnabled("supplier_invoice")) { $nbElements += $project->getElementCount('invoice_supplier', 'facture_fourn'); } if (!empty($conf->contrat->enabled)) { diff --git a/htdocs/core/menus/init_menu_auguria.sql b/htdocs/core/menus/init_menu_auguria.sql index 96625dd1f95..0580c6c8cc0 100644 --- a/htdocs/core/menus/init_menu_auguria.sql +++ b/htdocs/core/menus/init_menu_auguria.sql @@ -12,7 +12,7 @@ delete from llx_menu where menu_handler=__HANDLER__ and entity=__ENTITY__; -- Top-Menu -- old: (module, enabled, rowid, ...) insert into llx_menu (rowid, module, enabled, menu_handler, type, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ( 1__+MAX_llx_menu__, '', '1', __HANDLER__, 'top', 'home', '', 0, '/index.php?mainmenu=home&leftmenu=', 'Home', -1, '', '', '', 2, 10, __ENTITY__); -insert into llx_menu (rowid, module, enabled, menu_handler, type, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ( 2__+MAX_llx_menu__, 'societe|fournisseur|supplier_order|supplier_invoice', '($conf->societe->enabled && (empty($conf->global->SOCIETE_DISABLE_PROSPECTS) || empty($conf->global->SOCIETE_DISABLE_CUSTOMERS) || !empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || $conf->supplier_order->enabled || $conf->supplier_invoice->enabled))', __HANDLER__, 'top', 'companies', '', 0, '/societe/index.php?mainmenu=companies&leftmenu=', 'ThirdParties', -1, 'companies', '$user->rights->societe->lire || $user->rights->societe->contact->lire', '', 2, 20, __ENTITY__); +insert into llx_menu (rowid, module, enabled, menu_handler, type, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ( 2__+MAX_llx_menu__, 'societe|fournisseur|supplier_order|supplier_invoice', '($conf->societe->enabled && (empty($conf->global->SOCIETE_DISABLE_PROSPECTS) || empty($conf->global->SOCIETE_DISABLE_CUSTOMERS) || isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || $conf->supplier_order->enabled || $conf->supplier_invoice->enabled))', __HANDLER__, 'top', 'companies', '', 0, '/societe/index.php?mainmenu=companies&leftmenu=', 'ThirdParties', -1, 'companies', '$user->rights->societe->lire || $user->rights->societe->contact->lire', '', 2, 20, __ENTITY__); insert into llx_menu (rowid, module, enabled, menu_handler, type, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ( 3__+MAX_llx_menu__, 'product|service', '$conf->product->enabled || $conf->service->enabled', __HANDLER__, 'top', 'products', '', 0, '/product/index.php?mainmenu=products&leftmenu=', 'ProductsPipeServices', -1, 'products', '$user->rights->produit->lire||$user->rights->service->lire', '', 0, 30, __ENTITY__); insert into llx_menu (rowid, module, enabled, menu_handler, type, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ( 16__+MAX_llx_menu__, 'bom|mrp', '$conf->bom->enabled || $conf->mrp->enabled', __HANDLER__, 'top', 'mrp', '', 0, '/mrp/index.php?mainmenu=mrp&leftmenu=', 'MRP', -1, 'mrp', '$user->rights->bom->read||$user->rights->mrp->read', '', 0, 31, __ENTITY__); insert into llx_menu (rowid, module, enabled, menu_handler, type, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ( 7__+MAX_llx_menu__, 'projet', '$conf->project->enabled', __HANDLER__, 'top', 'project', '', 0, '/projet/index.php?mainmenu=project&leftmenu=', 'Projects', -1, 'projects', '$user->rights->projet->lire', '', 2, 32, __ENTITY__); @@ -86,8 +86,8 @@ insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, left insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled', __HANDLER__, 'left', 500__+MAX_llx_menu__, 'companies', 'thirdparties', 2__+MAX_llx_menu__, '/societe/index.php?mainmenu=companies&leftmenu=thirdparties', 'ThirdParty', 0, 'companies', '$user->rights->societe->lire', '', 2, 0, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled', __HANDLER__, 'left', 501__+MAX_llx_menu__, 'companies', '', 500__+MAX_llx_menu__, '/societe/card.php?mainmenu=companies&action=create', 'MenuNewThirdParty', 1, 'companies', '$user->rights->societe->creer', '', 2, 0, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled', __HANDLER__, 'left', 502__+MAX_llx_menu__, 'companies', '', 500__+MAX_llx_menu__, '/societe/list.php?mainmenu=companies&leftmenu=thirdparties', 'List', 1, 'companies', '$user->rights->societe->lire', '', 2, 0, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled && (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled))', __HANDLER__, 'left', 503__+MAX_llx_menu__, 'companies', '', 500__+MAX_llx_menu__, '/societe/list.php?mainmenu=companies&type=f&leftmenu=suppliers', 'ListSuppliersShort', 1, 'suppliers', '$user->rights->societe->lire && $user->rights->fournisseur->lire', '', 2, 5, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled && (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled))', __HANDLER__, 'left', 504__+MAX_llx_menu__, 'companies', '', 503__+MAX_llx_menu__, '/societe/card.php?mainmenu=companies&leftmenu=supplier&action=create&type=f', 'NewSupplier', 2, 'suppliers', '$user->rights->societe->creer', '', 2, 0, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled && (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice"))', __HANDLER__, 'left', 503__+MAX_llx_menu__, 'companies', '', 500__+MAX_llx_menu__, '/societe/list.php?mainmenu=companies&type=f&leftmenu=suppliers', 'ListSuppliersShort', 1, 'suppliers', '$user->rights->societe->lire && $user->rights->fournisseur->lire', '', 2, 5, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled && (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice"))', __HANDLER__, 'left', 504__+MAX_llx_menu__, 'companies', '', 503__+MAX_llx_menu__, '/societe/card.php?mainmenu=companies&leftmenu=supplier&action=create&type=f', 'NewSupplier', 2, 'suppliers', '$user->rights->societe->creer', '', 2, 0, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled', __HANDLER__, 'left', 506__+MAX_llx_menu__, 'companies', '', 500__+MAX_llx_menu__, '/societe/list.php?mainmenu=companies&type=p&leftmenu=prospects', 'ListProspectsShort', 1, 'companies', '$user->rights->societe->lire', '', 2, 3, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled', __HANDLER__, 'left', 507__+MAX_llx_menu__, 'companies', '', 506__+MAX_llx_menu__, '/societe/card.php?mainmenu=companies&leftmenu=prospects&action=create&type=p', 'MenuNewProspect', 2, 'companies', '$user->rights->societe->creer', '', 2, 0, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled', __HANDLER__, 'left', 509__+MAX_llx_menu__, 'companies', '', 500__+MAX_llx_menu__, '/societe/list.php?mainmenu=companies&type=c&leftmenu=customers', 'ListCustomersShort', 1, 'companies', '$user->rights->societe->lire', '', 2, 4, __ENTITY__); @@ -99,7 +99,7 @@ insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, left insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled', __HANDLER__, 'left', 602__+MAX_llx_menu__, 'companies', '', 600__+MAX_llx_menu__, '/contact/list.php?mainmenu=companies&leftmenu=contacts', 'List', 1, 'companies', '$user->rights->societe->lire', '', 2, 1, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled', __HANDLER__, 'left', 604__+MAX_llx_menu__, 'companies', '', 602__+MAX_llx_menu__, '/contact/list.php?mainmenu=companies&leftmenu=contacts&type=p', 'ThirdPartyProspects', 2, 'companies', '$user->rights->societe->contact->lire', '', 2, 1, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled', __HANDLER__, 'left', 605__+MAX_llx_menu__, 'companies', '', 602__+MAX_llx_menu__, '/contact/list.php?mainmenu=companies&leftmenu=contacts&type=c', 'ThirdPartyCustomers', 2, 'companies', '$user->rights->societe->contact->lire', '', 2, 2, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled && (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled))', __HANDLER__, 'left', 606__+MAX_llx_menu__, 'companies', '', 602__+MAX_llx_menu__, '/contact/list.php?mainmenu=companies&leftmenu=contacts&type=f', 'ThirdPartySuppliers', 2, 'companies', '$user->rights->societe->contact->lire', '', 2, 3, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled && (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice"))', __HANDLER__, 'left', 606__+MAX_llx_menu__, 'companies', '', 602__+MAX_llx_menu__, '/contact/list.php?mainmenu=companies&leftmenu=contacts&type=f', 'ThirdPartySuppliers', 2, 'companies', '$user->rights->societe->contact->lire', '', 2, 3, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled', __HANDLER__, 'left', 607__+MAX_llx_menu__, 'companies', '', 602__+MAX_llx_menu__, '/contact/list.php?mainmenu=companies&leftmenu=contacts&type=o', 'Others', 2, 'companies', '$user->rights->societe->contact->lire', '', 2, 4, __ENTITY__); -- Third parties - Category customer @@ -107,8 +107,8 @@ insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, left insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled && $conf->categorie->enabled', __HANDLER__, 'left', 651__+MAX_llx_menu__, 'companies', '', 650__+MAX_llx_menu__, '/categories/card.php?mainmenu=companies&action=create&type=1', 'NewCategory', 1, 'categories', '$user->rights->categorie->creer', '', 2, 0, __ENTITY__); -- Third parties - Category supplier -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '(!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) && $conf->categorie->enabled', __HANDLER__, 'left', 660__+MAX_llx_menu__, 'companies', 'cat', 2__+MAX_llx_menu__, '/categories/index.php?mainmenu=companies&leftmenu=cat&type=2', 'CustomersProspectsCategoriesShort', 0, 'categories', '$user->rights->categorie->lire', '', 2, 4, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '(!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) && $conf->categorie->enabled', __HANDLER__, 'left', 661__+MAX_llx_menu__, 'companies', '', 660__+MAX_llx_menu__, '/categories/card.php?mainmenu=companies&action=create&type=2', 'NewCategory', 1, 'categories', '$user->rights->categorie->creer', '', 2, 0, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '(isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) && $conf->categorie->enabled', __HANDLER__, 'left', 660__+MAX_llx_menu__, 'companies', 'cat', 2__+MAX_llx_menu__, '/categories/index.php?mainmenu=companies&leftmenu=cat&type=2', 'CustomersProspectsCategoriesShort', 0, 'categories', '$user->rights->categorie->lire', '', 2, 4, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '(isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) && $conf->categorie->enabled', __HANDLER__, 'left', 661__+MAX_llx_menu__, 'companies', '', 660__+MAX_llx_menu__, '/categories/card.php?mainmenu=companies&action=create&type=2', 'NewCategory', 1, 'categories', '$user->rights->categorie->creer', '', 2, 0, __ENTITY__); -- Third parties - Category contact insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled && $conf->categorie->enabled', __HANDLER__, 'left', 670__+MAX_llx_menu__, 'companies', 'cat', 2__+MAX_llx_menu__, '/categories/index.php?mainmenu=companies&leftmenu=cat&type=4', 'ContactCategoriesShort', 0, 'categories', '$user->rights->categorie->lire', '', 2, 3, __ENTITY__); @@ -257,7 +257,7 @@ insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, left insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->tax->enabled && $leftmenu=="tax_social"', __HANDLER__, 'left', 2251__+MAX_llx_menu__, 'billing', '', 2250__+MAX_llx_menu__, '/compta/sociales/card.php?mainmenu=billing&leftmenu=tax_social&action=create', 'MenuNewSocialContribution', 2, '', '$user->rights->tax->charges->creer', '', 0, 2, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->tax->enabled && $leftmenu=="tax_social"', __HANDLER__, 'left', 2252__+MAX_llx_menu__, 'billing', '', 2250__+MAX_llx_menu__, '/compta/sociales/payments.php?mainmenu=billing&leftmenu=tax_social', 'Payments', 2, '', '$user->rights->tax->charges->lire', '', 0, 3, __ENTITY__); --- VAT/TVA/IVA +-- VAT/TVA/IVA insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->tax->enabled && empty($conf->global->TAX_DISABLE_VAT_MENUS)', __HANDLER__, 'left', 2300__+MAX_llx_menu__, 'billing', 'tax_vat', 2200__+MAX_llx_menu__, '/compta/tva/list.php?mainmenu=billing&leftmenu=tax_vat', 'VAT', 1, 'companies', '$user->rights->tax->charges->lire', '', 0, 7, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->tax->enabled && empty($conf->global->TAX_DISABLE_VAT_MENUS) && $leftmenu=="tax_vat"', __HANDLER__, 'left', 2301__+MAX_llx_menu__, 'billing', '', 2300__+MAX_llx_menu__, '/compta/tva/card.php?mainmenu=billing&leftmenu=tax_vat&action=create', 'New', 2, 'companies', '$user->rights->tax->charges->creer', '', 0, 0, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->tax->enabled && empty($conf->global->TAX_DISABLE_VAT_MENUS) && $leftmenu=="tax_vat"', __HANDLER__, 'left', 2302__+MAX_llx_menu__, 'billing', '', 2300__+MAX_llx_menu__, '/compta/tva/list.php?mainmenu=billing&leftmenu=tax_vat', 'List', 2, 'companies', '$user->rights->tax->charges->lire', '', 0, 1, __ENTITY__); @@ -313,9 +313,9 @@ insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, left insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->accounting->enabled && $conf->facture->enabled && empty($conf->global->ACCOUNTING_DISABLE_BINDING_ON_SALES)', __HANDLER__, 'left', 2401__+MAX_llx_menu__, 'accountancy', 'accountancy_dispatch_customer', 2400__+MAX_llx_menu__, '/accountancy/customer/index.php?mainmenu=accountancy&leftmenu=accountancy_dispatch_customer', 'CustomersVentilation', 1, 'accountancy', '$user->rights->accounting->bind->write', '', 0, 2, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->accounting->enabled && $conf->facture->enabled && empty($conf->global->ACCOUNTING_DISABLE_BINDING_ON_SALES) && $leftmenu=="accountancy_dispatch_customer"', __HANDLER__, 'left', 2402__+MAX_llx_menu__, 'accountancy', '', 2401__+MAX_llx_menu__, '/accountancy/customer/list.php?mainmenu=accountancy', 'ToDispatch', 2, 'accountancy', '$user->rights->accounting->bind->write', '', 0, 3, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->accounting->enabled && $conf->facture->enabled && empty($conf->global->ACCOUNTING_DISABLE_BINDING_ON_SALES) && $leftmenu=="accountancy_dispatch_customer"', __HANDLER__, 'left', 2403__+MAX_llx_menu__, 'accountancy', '', 2401__+MAX_llx_menu__, '/accountancy/customer/lines.php?mainmenu=accountancy', 'Dispatched', 2, 'accountancy', '$user->rights->accounting->bind->write', '', 0, 4, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->accounting->enabled && (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_invoice->enabled)) && empty($conf->global->ACCOUNTING_DISABLE_BINDING_ON_PURCHASES)', __HANDLER__, 'left', 2410__+MAX_llx_menu__, 'accountancy', 'accountancy_dispatch_supplier', 2400__+MAX_llx_menu__, '/accountancy/supplier/index.php?mainmenu=accountancy&leftmenu=accountancy_dispatch_supplier', 'SuppliersVentilation', 1, 'accountancy', '$user->rights->accounting->bind->write', '', 0, 5, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->accounting->enabled && (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_invoice->enabled)) && empty($conf->global->ACCOUNTING_DISABLE_BINDING_ON_PURCHASES) && $leftmenu=="accountancy_dispatch_supplier"', __HANDLER__, 'left', 2411__+MAX_llx_menu__, 'accountancy', '', 2410__+MAX_llx_menu__, '/accountancy/supplier/list.php?mainmenu=accountancy', 'ToDispatch', 2, 'accountancy', '$user->rights->accounting->bind->write', '', 0, 6, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->accounting->enabled && (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_invoice->enabled)) && empty($conf->global->ACCOUNTING_DISABLE_BINDING_ON_PURCHASES) && $leftmenu=="accountancy_dispatch_supplier"', __HANDLER__, 'left', 2412__+MAX_llx_menu__, 'accountancy', '', 2410__+MAX_llx_menu__, '/accountancy/supplier/lines.php?mainmenu=accountancy', 'Dispatched', 2, 'accountancy', '$user->rights->accounting->bind->write', '', 0, 7, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->accounting->enabled && (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_invoice")) && empty($conf->global->ACCOUNTING_DISABLE_BINDING_ON_PURCHASES)', __HANDLER__, 'left', 2410__+MAX_llx_menu__, 'accountancy', 'accountancy_dispatch_supplier', 2400__+MAX_llx_menu__, '/accountancy/supplier/index.php?mainmenu=accountancy&leftmenu=accountancy_dispatch_supplier', 'SuppliersVentilation', 1, 'accountancy', '$user->rights->accounting->bind->write', '', 0, 5, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->accounting->enabled && (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_invoice")) && empty($conf->global->ACCOUNTING_DISABLE_BINDING_ON_PURCHASES) && $leftmenu=="accountancy_dispatch_supplier"', __HANDLER__, 'left', 2411__+MAX_llx_menu__, 'accountancy', '', 2410__+MAX_llx_menu__, '/accountancy/supplier/list.php?mainmenu=accountancy', 'ToDispatch', 2, 'accountancy', '$user->rights->accounting->bind->write', '', 0, 6, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->accounting->enabled && (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_invoice")) && empty($conf->global->ACCOUNTING_DISABLE_BINDING_ON_PURCHASES) && $leftmenu=="accountancy_dispatch_supplier"', __HANDLER__, 'left', 2412__+MAX_llx_menu__, 'accountancy', '', 2410__+MAX_llx_menu__, '/accountancy/supplier/lines.php?mainmenu=accountancy', 'Dispatched', 2, 'accountancy', '$user->rights->accounting->bind->write', '', 0, 7, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->accounting->enabled && $conf->expensereport->enabled && empty($conf->global->ACCOUNTING_DISABLE_BINDING_ON_EXPENSEREPORTS)', __HANDLER__, 'left', 2420__+MAX_llx_menu__, 'accountancy', 'accountancy_dispatch_expensereport', 2400__+MAX_llx_menu__, '/accountancy/expensereport/index.php?mainmenu=accountancy&leftmenu=accountancy_dispatch_expensereport', 'ExpenseReportsVentilation', 1, 'accountancy', '$user->rights->accounting->bind->write', '', 0, 5, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->accounting->enabled && $conf->expensereport->enabled && empty($conf->global->ACCOUNTING_DISABLE_BINDING_ON_EXPENSEREPORTS) && $leftmenu=="accountancy_dispatch_expensereport"', __HANDLER__, 'left', 2421__+MAX_llx_menu__, 'accountancy', '', 2420__+MAX_llx_menu__, '/accountancy/expensereport/list.php?mainmenu=accountancy', 'ToDispatch', 2, 'accountancy', '$user->rights->accounting->bind->write', '', 0, 6, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->accounting->enabled && $conf->expensereport->enabled && empty($conf->global->ACCOUNTING_DISABLE_BINDING_ON_EXPENSEREPORTS) && $leftmenu=="accountancy_dispatch_expensereport"', __HANDLER__, 'left', 2422__+MAX_llx_menu__, 'accountancy', '', 2420__+MAX_llx_menu__, '/accountancy/expensereport/lines.php?mainmenu=accountancy', 'Dispatched', 2, 'accountancy', '$user->rights->accounting->bind->write', '', 0, 7, __ENTITY__); diff --git a/htdocs/core/modules/modCategorie.class.php b/htdocs/core/modules/modCategorie.class.php index eb9c4fe8779..e70cdad999e 100644 --- a/htdocs/core/modules/modCategorie.class.php +++ b/htdocs/core/modules/modCategorie.class.php @@ -130,7 +130,7 @@ class modCategorie extends DolibarrModules if (isModEnabled("product") || isModEnabled("service")) { $typeexample .= ($typeexample ? " / " : "")."0=Product-Service"; } - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) { $typeexample .= ($typeexample ? "/" : "")."1=Supplier"; } if (isModEnabled("societe")) { @@ -203,7 +203,7 @@ class modCategorie extends DolibarrModules $this->export_code[$r] = $this->rights_class.'_1_'.Categorie::$MAP_ID_TO_CODE[1]; $this->export_label[$r] = 'CatSupList'; $this->export_icon[$r] = $this->picto; - $this->export_enabled[$r] = '!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)'; + $this->export_enabled[$r] = 'isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")'; $this->export_permission[$r] = array(array("categorie", "lire"), array("fournisseur", "lire")); $this->export_fields_array[$r] = array( 'cat.rowid'=>"CategId", 'cat.label'=>"Label", 'cat.description'=>"Description", 'cat.fk_parent'=>"ParentCategory", @@ -485,7 +485,7 @@ class modCategorie extends DolibarrModules } // 1 Suppliers - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) { $r++; $this->import_code[$r] = $this->rights_class.'_1_'.Categorie::$MAP_ID_TO_CODE[1]; $this->import_label[$r] = "CatSupLinks"; // Translation key diff --git a/htdocs/core/modules/modProduct.class.php b/htdocs/core/modules/modProduct.class.php index 090fdd59fa3..2b2d2f6cdcb 100644 --- a/htdocs/core/modules/modProduct.class.php +++ b/htdocs/core/modules/modProduct.class.php @@ -203,7 +203,7 @@ class modProduct extends DolibarrModules if (is_object($mysoc) && $usenpr) { $this->export_fields_array[$r]['p.recuperableonly'] = 'NPR'; } - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled) || !empty($conf->margin->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice") || !empty($conf->margin->enabled)) { $this->export_fields_array[$r] = array_merge($this->export_fields_array[$r], array('p.cost_price'=>'CostPrice')); } if (!empty($conf->stock->enabled)) { @@ -216,7 +216,7 @@ class modProduct extends DolibarrModules $keyforelement = 'product'; $keyforaliasextra = 'extra'; include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) { $this->export_fields_array[$r] = array_merge($this->export_fields_array[$r], array('s.nom'=>'Supplier', 'pf.ref_fourn'=>'SupplierRef', 'pf.quantity'=>'QtyMin', 'pf.remise_percent'=>'DiscountQtyMin', 'pf.unitprice'=>'BuyingPrice', 'pf.delivery_time_days'=>'NbDaysToDelivery')); } if (!empty($conf->global->EXPORTTOOL_CATEGORIES)) { @@ -250,7 +250,7 @@ class modProduct extends DolibarrModules if (isModEnabled('barcode')) { $this->export_TypeFields_array[$r] = array_merge($this->export_TypeFields_array[$r], array('p.barcode'=>'Text')); } - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) { $this->export_TypeFields_array[$r] = array_merge($this->export_TypeFields_array[$r], array('s.nom'=>'Text', 'pf.ref_fourn'=>'Text', 'pf.unitprice'=>'Numeric', 'pf.quantity'=>'Numeric', 'pf.remise_percent'=>'Numeric', 'pf.delivery_time_days'=>'Numeric')); } if (!empty($conf->global->MAIN_MULTILANGS)) { @@ -269,7 +269,7 @@ class modProduct extends DolibarrModules if (isModEnabled('barcode')) { $this->export_entities_array[$r] = array_merge($this->export_entities_array[$r], array('p.barcode'=>'product')); } - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) { $this->export_entities_array[$r] = array_merge($this->export_entities_array[$r], array('s.nom'=>'product_supplier_ref', 'pf.ref_fourn'=>'product_supplier_ref', 'pf.unitprice'=>'product_supplier_ref', 'pf.quantity'=>'product_supplier_ref', 'pf.remise_percent'=>'product_supplier_ref', 'pf.delivery_time_days'=>'product_supplier_ref')); } if (!empty($conf->global->MAIN_MULTILANGS)) { @@ -284,7 +284,7 @@ class modProduct extends DolibarrModules if (isModEnabled('barcode')) { $this->export_entities_array[$r] = array_merge($this->export_entities_array[$r], array('p.barcode'=>'product')); } - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) { $this->export_entities_array[$r] = array_merge($this->export_entities_array[$r], array('s.nom'=>'product_supplier_ref', 'pf.ref_fourn'=>'product_supplier_ref', 'pf.unitprice'=>'product_supplier_ref', 'pf.quantity'=>'product_supplier_ref', 'pf.remise_percent'=>'product_supplier_ref', 'pf.delivery_time_days'=>'product_supplier_ref')); } if (!empty($conf->global->MAIN_MULTILANGS)) { @@ -305,7 +305,7 @@ class modProduct extends DolibarrModules $this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_lang as l ON l.fk_product = p.rowid'; } $this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_extrafields as extra ON p.rowid = extra.fk_object'; - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) { $this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_fournisseur_price as pf ON pf.fk_product = p.rowid LEFT JOIN '.MAIN_DB_PREFIX.'societe s ON s.rowid = pf.fk_soc'; } if (!empty($conf->stock->enabled)) { @@ -617,7 +617,7 @@ class modProduct extends DolibarrModules )); } - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled) || !empty($conf->margin->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice") || !empty($conf->margin->enabled)) { $this->import_fields_array[$r] = array_merge($this->import_fields_array[$r], array('p.cost_price'=>'CostPrice')); } if (is_object($mysoc) && $usenpr) { @@ -710,7 +710,7 @@ class modProduct extends DolibarrModules 'p.desiredstock' => '' )); } - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled) || !empty($conf->margin->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice") || !empty($conf->margin->enabled)) { $import_sample = array_merge($import_sample, array('p.cost_price'=>'90')); } if (is_object($mysoc) && $usenpr) { @@ -749,7 +749,7 @@ class modProduct extends DolibarrModules $this->import_updatekeys_array[$r] = array_merge($this->import_updatekeys_array[$r], array('p.barcode'=>'BarCode')); //only show/allow barcode as update key if Barcode module enabled } - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) { // Import suppliers prices (note: this code is duplicated in module Service) $r++; $this->import_code[$r] = $this->rights_class.'_supplierprices'; diff --git a/htdocs/core/modules/modService.class.php b/htdocs/core/modules/modService.class.php index 8f4b697332b..dcea2a6f1af 100644 --- a/htdocs/core/modules/modService.class.php +++ b/htdocs/core/modules/modService.class.php @@ -168,7 +168,7 @@ class modService extends DolibarrModules if (is_object($mysoc) && $usenpr) { $this->export_fields_array[$r]['p.recuperableonly'] = 'NPR'; } - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled) || !empty($conf->margin->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice") || !empty($conf->margin->enabled)) { $this->export_fields_array[$r] = array_merge($this->export_fields_array[$r], array('p.cost_price'=>'CostPrice')); } if (!empty($conf->stock->enabled)) { @@ -181,7 +181,7 @@ class modService extends DolibarrModules $keyforelement = 'product'; $keyforaliasextra = 'extra'; include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) { $this->export_fields_array[$r] = array_merge($this->export_fields_array[$r], array('s.nom'=>'Supplier', 'pf.ref_fourn'=>'SupplierRef', 'pf.quantity'=>'QtyMin', 'pf.remise_percent'=>'DiscountQtyMin', 'pf.unitprice'=>'BuyingPrice', 'pf.delivery_time_days'=>'NbDaysToDelivery')); } if (!empty($conf->global->EXPORTTOOL_CATEGORIES)) { @@ -213,7 +213,7 @@ class modService extends DolibarrModules if (isModEnabled('barcode')) { $this->export_TypeFields_array[$r] = array_merge($this->export_TypeFields_array[$r], array('p.barcode'=>'Text')); } - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) { $this->export_TypeFields_array[$r] = array_merge($this->export_TypeFields_array[$r], array('s.nom'=>'Text', 'pf.ref_fourn'=>'Text', 'pf.unitprice'=>'Numeric', 'pf.quantity'=>'Numeric', 'pf.remise_percent'=>'Numeric', 'pf.delivery_time_days'=>'Numeric')); } if (!empty($conf->global->MAIN_MULTILANGS)) { @@ -232,7 +232,7 @@ class modService extends DolibarrModules if (isModEnabled('barcode')) { $this->export_entities_array[$r] = array_merge($this->export_entities_array[$r], array('p.barcode'=>'product')); } - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) { $this->export_entities_array[$r] = array_merge($this->export_entities_array[$r], array('s.nom'=>'product_supplier_ref', 'pf.ref_fourn'=>'product_supplier_ref', 'pf.unitprice'=>'product_supplier_ref', 'pf.quantity'=>'product_supplier_ref', 'pf.remise_percent'=>'product_supplier_ref', 'pf.delivery_time_days'=>'product_supplier_ref')); } if (!empty($conf->global->MAIN_MULTILANGS)) { @@ -247,7 +247,7 @@ class modService extends DolibarrModules if (isModEnabled('barcode')) { $this->export_entities_array[$r] = array_merge($this->export_entities_array[$r], array('p.barcode'=>'product')); } - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) { $this->export_entities_array[$r] = array_merge($this->export_entities_array[$r], array('s.nom'=>'product_supplier_ref', 'pf.ref_fourn'=>'product_supplier_ref', 'pf.unitprice'=>'product_supplier_ref', 'pf.quantity'=>'product_supplier_ref', 'pf.remise_percent'=>'product_supplier_ref', 'pf.delivery_time_days'=>'product_supplier_ref')); } if (!empty($conf->global->MAIN_MULTILANGS)) { @@ -268,7 +268,7 @@ class modService extends DolibarrModules $this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_lang as l ON l.fk_product = p.rowid'; } $this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_extrafields as extra ON p.rowid = extra.fk_object'; - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) { $this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_fournisseur_price as pf ON pf.fk_product = p.rowid LEFT JOIN '.MAIN_DB_PREFIX.'societe s ON s.rowid = pf.fk_soc'; } $this->export_sql_end[$r] .= ' WHERE p.fk_product_type = 1 AND p.entity IN ('.getEntity('product').')'; @@ -564,7 +564,7 @@ class modService extends DolibarrModules )); } - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled) || !empty($conf->margin->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice") || !empty($conf->margin->enabled)) { $this->import_fields_array[$r] = array_merge($this->import_fields_array[$r], array('p.cost_price'=>'CostPrice')); } if (is_object($mysoc) && $usenpr) { @@ -655,7 +655,7 @@ class modService extends DolibarrModules 'p.desiredstock' => '' )); } - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled) || !empty($conf->margin->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice") || !empty($conf->margin->enabled)) { $import_sample = array_merge($import_sample, array('p.cost_price'=>'90')); } if (is_object($mysoc) && $usenpr) { @@ -698,7 +698,7 @@ class modService extends DolibarrModules } if (empty($conf->product->enabled)) { // We enable next import templates only if module product not already enabled (to avoid duplicate entries) - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) { // Import suppliers prices (note: this code is duplicated in module Service) $r++; $this->import_code[$r] = $this->rights_class.'_supplierprices'; diff --git a/htdocs/core/modules/modSociete.class.php b/htdocs/core/modules/modSociete.class.php index 327262ce39f..ff5edd3eeb4 100644 --- a/htdocs/core/modules/modSociete.class.php +++ b/htdocs/core/modules/modSociete.class.php @@ -413,7 +413,7 @@ class modSociete extends DolibarrModules 't.libelle'=>"company", 's.entity'=>'company', ); // We define here only fields that use another picto - if (empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { + if (empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) { unset($this->export_fields_array[$r]['s.code_fournisseur']); unset($this->export_entities_array[$r]['s.code_fournisseur']); } diff --git a/htdocs/core/modules/project/doc/doc_generic_project_odt.modules.php b/htdocs/core/modules/project/doc/doc_generic_project_odt.modules.php index 4397faedb9c..420dfd61909 100644 --- a/htdocs/core/modules/project/doc/doc_generic_project_odt.modules.php +++ b/htdocs/core/modules/project/doc/doc_generic_project_odt.modules.php @@ -49,10 +49,10 @@ if (isModEnabled('facture')) { if (!empty($conf->commande->enabled)) { require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; } -if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_invoice->enabled)) { +if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_invoice")) { require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php'; } -if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) { +if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order")) { require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php'; } if (!empty($conf->contrat->enabled)) { @@ -971,13 +971,13 @@ class doc_generic_project_odt extends ModelePDFProjects 'title' => "ListSupplierOrdersAssociatedProject", 'table' => 'commande_fournisseur', 'class' => 'CommandeFournisseur', - 'test' => (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->commande->lire) || (!empty($conf->supplier_order->enabled) && $user->rights->supplier_order->lire) + 'test' => (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->commande->lire) || (isModEnabled("supplier_order") && $user->rights->supplier_order->lire) ), 'invoice_supplier' => array( 'title' => "ListSupplierInvoicesAssociatedProject", 'table' => 'facture_fourn', 'class' => 'FactureFournisseur', - 'test' => (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->facture->lire) || (!empty($conf->supplier_invoice->enabled) && $user->rights->supplier_invoice->lire) + 'test' => (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->facture->lire) || (isModEnabled("supplier_invoice") && $user->rights->supplier_invoice->lire) ), 'contract' => array( 'title' => "ListContractAssociatedProject", diff --git a/htdocs/core/modules/project/doc/pdf_beluga.modules.php b/htdocs/core/modules/project/doc/pdf_beluga.modules.php index fba5e02b098..1dc5b7bf3f9 100644 --- a/htdocs/core/modules/project/doc/pdf_beluga.modules.php +++ b/htdocs/core/modules/project/doc/pdf_beluga.modules.php @@ -407,7 +407,7 @@ class pdf_beluga extends ModelePDFProjects 'class'=>'CommandeFournisseur', 'table'=>'commande_fournisseur', 'datefieldname'=>'date_commande', - 'test'=>(!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->commande->lire) || (!empty($conf->supplier_order->enabled) && $user->rights->supplier_order->lire), + 'test'=>(isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->commande->lire) || (isModEnabled("supplier_order") && $user->rights->supplier_order->lire), 'lang'=>'orders'), 'invoice_supplier'=>array( 'name'=>"BillsSuppliers", @@ -416,7 +416,7 @@ class pdf_beluga extends ModelePDFProjects 'margin'=>'minus', 'table'=>'facture_fourn', 'datefieldname'=>'datef', - 'test'=>(!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->facture->lire) || (!empty($conf->supplier_invoice->enabled) && $user->rights->supplier_invoice->lire), + 'test'=>(isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->facture->lire) || (isModEnabled("supplier_invoice") && $user->rights->supplier_invoice->lire), 'lang'=>'bills'), 'contract'=>array( 'name'=>"Contracts", diff --git a/htdocs/core/modules/project/task/doc/doc_generic_task_odt.modules.php b/htdocs/core/modules/project/task/doc/doc_generic_task_odt.modules.php index cb3fc54fa46..8433aaa6331 100644 --- a/htdocs/core/modules/project/task/doc/doc_generic_task_odt.modules.php +++ b/htdocs/core/modules/project/task/doc/doc_generic_task_odt.modules.php @@ -50,10 +50,10 @@ if (isModEnabled('facture')) { if (!empty($conf->commande->enabled)) { require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; } -if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_invoice->enabled)) { +if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_invoice")) { require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php'; } -if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) { +if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order")) { require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php'; } if (!empty($conf->contrat->enabled)) { diff --git a/htdocs/core/modules/reception/doc/pdf_squille.modules.php b/htdocs/core/modules/reception/doc/pdf_squille.modules.php index 886168c28a6..050459d91d2 100644 --- a/htdocs/core/modules/reception/doc/pdf_squille.modules.php +++ b/htdocs/core/modules/reception/doc/pdf_squille.modules.php @@ -917,7 +917,7 @@ class pdf_squille extends ModelePdfReception $origin_id = $object->origin_id; // TODO move to external function - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) { // commonly $origin='commande' + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order")) { // commonly $origin='commande' $outputlangs->load('orders'); $classname = 'CommandeFournisseur'; diff --git a/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php b/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php index 20eb56d8b56..9a8414c7a69 100644 --- a/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php +++ b/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php @@ -200,7 +200,7 @@ class InterfaceWorkflowManager extends DolibarrTriggers // Firstly, we set to purchase order to "Billed" if WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER is set. // After we will set proposals - if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) && !empty($conf->global->WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER)) { + if (((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) && !empty($conf->global->WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER)) { $object->fetchObjectLinked('', 'order_supplier', $object->id, $object->element); if (!empty($object->linkedObjects)) { $totalonlinkedelements = 0; @@ -365,7 +365,7 @@ class InterfaceWorkflowManager extends DolibarrTriggers if (($action == 'RECEPTION_VALIDATE') || ($action == 'RECEPTION_CLOSED')) { dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); - if ((!empty($conf->fournisseur->enabled) || !empty($conf->supplier_order->enabled)) && isModEnabled("reception") && !empty($conf->workflow->enabled) && + if ((isModEnabled("fournisseur") || isModEnabled("supplier_order")) && isModEnabled("reception") && !empty($conf->workflow->enabled) && ( (!empty($conf->global->WORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION) && ($action == 'RECEPTION_VALIDATE')) || (!empty($conf->global->WORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED) && ($action == 'RECEPTION_CLOSED')) diff --git a/htdocs/ecm/index_auto.php b/htdocs/ecm/index_auto.php index c488ff901bd..4ffe606c79e 100644 --- a/htdocs/ecm/index_auto.php +++ b/htdocs/ecm/index_auto.php @@ -332,11 +332,11 @@ if (!empty($conf->global->ECM_AUTO_TREE_ENABLED)) { $langs->load("supplier_proposal"); $rowspan++; $sectionauto[] = array('position'=>70, 'level'=>1, 'module'=>'supplier_proposal', 'test'=>$conf->supplier_proposal->enabled, 'label'=>$langs->trans("SupplierProposals"), 'desc'=>$langs->trans("ECMDocsBy", $langs->transnoentitiesnoconv("SupplierProposals"))); } - if (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_order->enabled)) { - $rowspan++; $sectionauto[] = array('position'=>80, 'level'=>1, 'module'=>'order_supplier', 'test'=>(!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_order->enabled)), 'label'=>$langs->trans("SuppliersOrders"), 'desc'=>$langs->trans("ECMDocsBy", $langs->transnoentitiesnoconv("PurchaseOrders"))); + if (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_order")) { + $rowspan++; $sectionauto[] = array('position'=>80, 'level'=>1, 'module'=>'order_supplier', 'test'=>(isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_order")), 'label'=>$langs->trans("SuppliersOrders"), 'desc'=>$langs->trans("ECMDocsBy", $langs->transnoentitiesnoconv("PurchaseOrders"))); } - if (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_invoice->enabled)) { - $rowspan++; $sectionauto[] = array('position'=>90, 'level'=>1, 'module'=>'invoice_supplier', 'test'=>(!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_invoice->enabled)), 'label'=>$langs->trans("SuppliersInvoices"), 'desc'=>$langs->trans("ECMDocsBy", $langs->transnoentitiesnoconv("SupplierInvoices"))); + if (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_invoice")) { + $rowspan++; $sectionauto[] = array('position'=>90, 'level'=>1, 'module'=>'invoice_supplier', 'test'=>(isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_invoice")), 'label'=>$langs->trans("SuppliersInvoices"), 'desc'=>$langs->trans("ECMDocsBy", $langs->transnoentitiesnoconv("SupplierInvoices"))); } if (!empty($conf->tax->enabled)) { $langs->load("compta"); diff --git a/htdocs/ecm/search.php b/htdocs/ecm/search.php index 4ada152d9ce..d04983fff11 100644 --- a/htdocs/ecm/search.php +++ b/htdocs/ecm/search.php @@ -134,11 +134,11 @@ if (isModEnabled('facture')) { if (!empty($conf->supplier_proposal->enabled)) { $langs->load("supplier_proposal"); $rowspan++; $sectionauto[] = array('level'=>1, 'module'=>'supplier_proposal', 'test'=>$conf->supplier_proposal->enabled, 'label'=>$langs->trans("SupplierProposals"), 'desc'=>$langs->trans("ECMDocsBy", $langs->transnoentitiesnoconv("SupplierProposals"))); } -if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) { - $rowspan++; $sectionauto[] = array('level'=>1, 'module'=>'order_supplier', 'test'=>((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)), 'label'=>$langs->trans("SuppliersOrders"), 'desc'=>$langs->trans("ECMDocsBy", $langs->transnoentitiesnoconv("PurchaseOrders"))); +if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order")) { + $rowspan++; $sectionauto[] = array('level'=>1, 'module'=>'order_supplier', 'test'=>((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order")), 'label'=>$langs->trans("SuppliersOrders"), 'desc'=>$langs->trans("ECMDocsBy", $langs->transnoentitiesnoconv("PurchaseOrders"))); } -if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_invoice->enabled)) { - $rowspan++; $sectionauto[] = array('level'=>1, 'module'=>'invoice_supplier', 'test'=>((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_invoice->enabled)), 'label'=>$langs->trans("SuppliersInvoices"), 'desc'=>$langs->trans("ECMDocsBy", $langs->transnoentitiesnoconv("SupplierInvoices"))); +if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_invoice")) { + $rowspan++; $sectionauto[] = array('level'=>1, 'module'=>'invoice_supplier', 'test'=>((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_invoice")), 'label'=>$langs->trans("SuppliersInvoices"), 'desc'=>$langs->trans("ECMDocsBy", $langs->transnoentitiesnoconv("SupplierInvoices"))); } if (!empty($conf->tax->enabled)) { $langs->load("compta"); $rowspan++; $sectionauto[] = array('level'=>1, 'module'=>'tax', 'test'=>$conf->tax->enabled, 'label'=>$langs->trans("SocialContributions"), 'desc'=>$langs->trans("ECMDocsBy", $langs->transnoentitiesnoconv("SocialContributions"))); diff --git a/htdocs/fourn/card.php b/htdocs/fourn/card.php index ba72cd352be..7234e54e8f1 100644 --- a/htdocs/fourn/card.php +++ b/htdocs/fourn/card.php @@ -328,7 +328,7 @@ if ($object->id > 0) { print ''; print ''; - if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) && !empty($conf->global->ORDER_MANAGE_MIN_AMOUNT)) { + if (((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order")) && !empty($conf->global->ORDER_MANAGE_MIN_AMOUNT)) { print ''; print ''; } - if (((!empty($conf->fournisseur->enabled) && !empty($user->rights->fournisseur->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (!empty($conf->supplier_order->enabled) && !empty($user->rights->supplier_order->lire)) || (!empty($conf->supplier_invoice->enabled) && !empty($user->rights->supplier_invoice->lire))) && $object->fournisseur) { + if (((isModEnabled("fournisseur") && !empty($user->rights->fournisseur->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (isModEnabled("supplier_order") && !empty($user->rights->supplier_order->lire)) || (isModEnabled("supplier_invoice") && !empty($user->rights->supplier_invoice->lire))) && $object->fournisseur) { print ''; print ''; -if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { +if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) { print ''; print ''; print ''; - if ((!empty($conf->fournisseur->enabled) && !empty($user->rights->fournisseur->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (!empty($conf->supplier_order->enabled) && !empty($user->rights->supplier_order->lire)) || (!empty($conf->supplier_invoice->enabled) && !empty($user->rights->supplier_invoice->lire)) + if ((isModEnabled("fournisseur") && !empty($user->rights->fournisseur->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (isModEnabled("supplier_order") && !empty($user->rights->supplier_order->lire)) || (isModEnabled("supplier_invoice") && !empty($user->rights->supplier_invoice->lire)) || (!empty($conf->supplier_proposal->enabled) && !empty($user->rights->supplier_proposal->lire))) { // Supplier print ''; @@ -1485,11 +1485,11 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { } print '
'; print (empty($conf->global->PRODUCT_DENY_CHANGE_PRODUCT_TYPE)) ? $form->editfieldkey("Type", 'fk_product_type', $object->type, $object, 0, $typeformat) : $langs->trans('Type'); diff --git a/htdocs/product/stock/replenish.php b/htdocs/product/stock/replenish.php index b89554a18f7..91bb390e1f9 100644 --- a/htdocs/product/stock/replenish.php +++ b/htdocs/product/stock/replenish.php @@ -738,7 +738,7 @@ print '
  '.$form->textwithpicto($langs->trans('IncludeEmptyDesiredStock'), $langs->trans('IncludeProductWithUndefinedAlerts')).' 
'; print $langs->trans("CashdeskShowServices"); print ''; diff --git a/htdocs/user/param_ihm.php b/htdocs/user/param_ihm.php index 0043252c409..a00736fda44 100644 --- a/htdocs/user/param_ihm.php +++ b/htdocs/user/param_ihm.php @@ -195,7 +195,7 @@ if (!empty($conf->project->enabled)) { if (!empty($conf->holiday->enabled) || !empty($conf->expensereport->enabled)) { $tmparray['hrm/index.php?mainmenu=hrm&leftmenu='] = 'HRMArea'; // TODO Complete list with first level of menus } -if (isModEnabled("product") || !empty($conf->service->enabled)) { +if (isModEnabled("product") || isModEnabled("service")) { $tmparray['product/index.php?mainmenu=products&leftmenu='] = 'ProductsAndServicesArea'; } if (isModEnabled("propal") || !empty($conf->commande->enabled) || !empty($conf->ficheinter->enabled) || !empty($conf->contrat->enabled)) { diff --git a/htdocs/variants/combinations.php b/htdocs/variants/combinations.php index b95a19e70f7..fe058849899 100644 --- a/htdocs/variants/combinations.php +++ b/htdocs/variants/combinations.php @@ -395,7 +395,7 @@ if (!empty($id) || !empty($ref)) { print ''; // Type - if (isModEnabled("product") && !empty($conf->service->enabled)) { + if (isModEnabled("product") && isModEnabled("service")) { $typeformat = 'select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service"); print ''; print ''; print ''; print ''; print ''; print ''; print ''; diff --git a/htdocs/contact/consumption.php b/htdocs/contact/consumption.php index b7300c4ed78..c3cd54d890e 100644 --- a/htdocs/contact/consumption.php +++ b/htdocs/contact/consumption.php @@ -174,15 +174,15 @@ if (!empty($conf->ficheinter->enabled) && $user->rights->ficheinter->lire) { if ($object->thirdparty->fournisseur) { $thirdTypeArray['supplier'] = $langs->trans("supplier"); - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->facture->lire) || (!empty($conf->supplier_invoice->enabled) && $user->rights->supplier_invoice->lire)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->facture->lire) || (isModEnabled("supplier_invoice") && $user->rights->supplier_invoice->lire)) { $elementTypeArray['supplier_invoice'] = $langs->transnoentitiesnoconv('SuppliersInvoices'); } - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->commande->lire) || (!empty($conf->supplier_order->enabled) && $user->rights->supplier_order->lire)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->commande->lire) || (isModEnabled("supplier_order") && $user->rights->supplier_order->lire)) { $elementTypeArray['supplier_order'] = $langs->transnoentitiesnoconv('SuppliersOrders'); } // There no contact type for supplier proposals - // if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) && $user->rights->supplier_proposal->lire) $elementTypeArray['supplier_proposal']=$langs->transnoentitiesnoconv('SupplierProposals'); + // if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) && $user->rights->supplier_proposal->lire) $elementTypeArray['supplier_proposal']=$langs->transnoentitiesnoconv('SupplierProposals'); } print '
'; print (empty($conf->global->PRODUCT_DENY_CHANGE_PRODUCT_TYPE)) ? $form->editfieldkey("Type", 'fk_product_type', $object->type, $object, $usercancreate, $typeformat) : $langs->trans('Type'); diff --git a/htdocs/webservices/admin/index.php b/htdocs/webservices/admin/index.php index d688c16b870..2188a27c32a 100644 --- a/htdocs/webservices/admin/index.php +++ b/htdocs/webservices/admin/index.php @@ -102,7 +102,7 @@ $webservices = array( 'user' => '', 'thirdparty' => 'isModEnabled("societe")', 'contact' => 'isModEnabled("societe")', - 'productorservice' => '(isModEnabled("product") || !empty($conf->service->enabled))', + 'productorservice' => '(isModEnabled("product") || isModEnabled("service"))', 'order' => '!empty($conf->commande->enabled)', 'invoice' => 'isModEnabled("facture")', 'supplier_invoice' => '!empty($conf->fournisseur->enabled)', From 86a7a7c8bb407f87c815d97afb2f0a123b6c0b4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20France?= Date: Tue, 23 Aug 2022 20:05:09 +0200 Subject: [PATCH 770/826] use isModEnabled --- htdocs/admin/dict.php | 6 +++--- htdocs/admin/fckeditor.php | 2 +- htdocs/admin/mails_templates.php | 4 ++-- htdocs/admin/stock.php | 6 +++--- htdocs/admin/workflow.php | 10 +++++----- htdocs/blockedlog/class/blockedlog.class.php | 2 +- .../comm/action/class/cactioncomm.class.php | 4 ++-- htdocs/comm/index.php | 10 +++++----- htdocs/comm/propal/card.php | 2 +- htdocs/commande/card.php | 2 +- htdocs/commande/list.php | 4 ++-- htdocs/compta/accounting-files.php | 2 +- .../stats/supplier_turnover_by_thirdparty.php | 4 ++-- htdocs/contact/consumption.php | 6 +++--- htdocs/contact/list.php | 2 +- .../core/boxes/box_dolibarr_state_board.php | 6 +++--- htdocs/core/class/html.form.class.php | 4 ++-- htdocs/core/class/html.formcompany.class.php | 2 +- htdocs/core/lib/company.lib.php | 4 ++-- htdocs/core/lib/contact.lib.php | 2 +- htdocs/core/lib/invoice.lib.php | 2 +- htdocs/core/lib/product.lib.php | 6 +++--- htdocs/core/lib/project.lib.php | 6 +++--- htdocs/core/menus/init_menu_auguria.sql | 20 +++++++++---------- htdocs/core/modules/modCategorie.class.php | 6 +++--- htdocs/core/modules/modProduct.class.php | 18 ++++++++--------- htdocs/core/modules/modService.class.php | 18 ++++++++--------- htdocs/core/modules/modSociete.class.php | 2 +- .../doc/doc_generic_project_odt.modules.php | 8 ++++---- .../project/doc/pdf_beluga.modules.php | 4 ++-- .../task/doc/doc_generic_task_odt.modules.php | 4 ++-- .../reception/doc/pdf_squille.modules.php | 2 +- ...e_20_modWorkflow_WorkflowManager.class.php | 4 ++-- htdocs/ecm/index_auto.php | 8 ++++---- htdocs/ecm/search.php | 8 ++++---- htdocs/fourn/card.php | 6 +++--- .../class/fournisseur.commande.class.php | 2 +- htdocs/fourn/commande/card.php | 4 ++-- htdocs/fourn/commande/index.php | 2 +- htdocs/fourn/index.php | 4 ++-- htdocs/fourn/recap-fourn.php | 2 +- htdocs/main.inc.php | 4 ++-- htdocs/margin/tabs/thirdpartyMargins.php | 2 +- htdocs/product/admin/product.php | 2 +- htdocs/product/class/product.class.php | 6 +++--- htdocs/product/list.php | 2 +- htdocs/product/stock/product.php | 4 ++-- htdocs/product/stock/replenish.php | 2 +- htdocs/projet/card.php | 4 ++-- htdocs/projet/element.php | 4 ++-- htdocs/reception/card.php | 12 +++++------ htdocs/reception/contact.php | 4 ++-- .../canvas/actions_card_common.class.php | 2 +- htdocs/societe/card.php | 20 +++++++++---------- htdocs/societe/class/societe.class.php | 2 +- htdocs/societe/consumption.php | 4 ++-- htdocs/societe/list.php | 6 +++--- htdocs/societe/notify/card.php | 2 +- htdocs/supplier_proposal/card.php | 2 +- htdocs/webservices/admin/index.php | 2 +- 60 files changed, 153 insertions(+), 153 deletions(-) diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index 987ef05cb37..05f692be526 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -494,15 +494,15 @@ $tabcond[8] = isModEnabled("societe"); $tabcond[9] = true; $tabcond[10] = true; $tabcond[11] = (isModEnabled("societe")); -$tabcond[12] = (!empty($conf->commande->enabled) || isModEnabled("propal") || isModEnabled('facture') || (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_invoice->enabled) || !empty($conf->supplier_order->enabled)); -$tabcond[13] = (!empty($conf->commande->enabled) || isModEnabled("propal") || isModEnabled('facture') || (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_invoice->enabled) || !empty($conf->supplier_order->enabled)); +$tabcond[12] = (!empty($conf->commande->enabled) || isModEnabled("propal") || isModEnabled('facture') || (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_invoice") || isModEnabled("supplier_order")); +$tabcond[13] = (!empty($conf->commande->enabled) || isModEnabled("propal") || isModEnabled('facture') || (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_invoice") || isModEnabled("supplier_order")); $tabcond[14] = (isModEnabled("product") && (!empty($conf->ecotax->enabled) || !empty($conf->global->MAIN_SHOW_ECOTAX_DICTIONNARY))); $tabcond[15] = true; $tabcond[16] = (isModEnabled("societe") && empty($conf->global->SOCIETE_DISABLE_PROSPECTS)); $tabcond[17] = (!empty($conf->deplacement->enabled) || !empty($conf->expensereport->enabled)); $tabcond[18] = isModEnabled("expedition") || isModEnabled("reception"); $tabcond[19] = isModEnabled("societe"); -$tabcond[20] = (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled); +$tabcond[20] = (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order"); $tabcond[21] = isModEnabled("propal"); $tabcond[22] = (!empty($conf->commande->enabled) || isModEnabled("propal")); $tabcond[23] = true; diff --git a/htdocs/admin/fckeditor.php b/htdocs/admin/fckeditor.php index 25386388020..04048ac83db 100644 --- a/htdocs/admin/fckeditor.php +++ b/htdocs/admin/fckeditor.php @@ -63,7 +63,7 @@ $conditions = array( 'NOTE_PRIVATE' => 1, 'SOCIETE' => 1, 'PRODUCTDESC' => (isModEnabled("product") || isModEnabled("service")), - 'DETAILS' => (isModEnabled('facture') || isModEnabled("propal") || !empty($conf->commande->enabled) || !empty($conf->supplier_proposal->enabled) || (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)), + 'DETAILS' => (isModEnabled('facture') || isModEnabled("propal") || !empty($conf->commande->enabled) || !empty($conf->supplier_proposal->enabled) || (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")), 'USERSIGN' => 1, 'MAILING' => !empty($conf->mailing->enabled), 'MAIL' => (isModEnabled('facture') || isModEnabled("propal") || !empty($conf->commande->enabled)), diff --git a/htdocs/admin/mails_templates.php b/htdocs/admin/mails_templates.php index 95fd36d91d6..7f60b2260d7 100644 --- a/htdocs/admin/mails_templates.php +++ b/htdocs/admin/mails_templates.php @@ -212,10 +212,10 @@ if (!empty($conf->ficheinter->enabled)) { if (!empty($conf->supplier_proposal->enabled)) { $elementList['supplier_proposal_send'] = img_picto('', 'propal', 'class="pictofixedwidth"').dol_escape_htmltag($langs->trans('MailToSendSupplierRequestForQuotation')); } -if ((!empty($conf->fournisseur->enabled) && !empty($user->rights->fournisseur->commande->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (!empty($conf->supplier_order->enabled) && !empty($user->rights->supplier_order->lire))) { +if ((isModEnabled("fournisseur") && !empty($user->rights->fournisseur->commande->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (isModEnabled("supplier_order") && !empty($user->rights->supplier_order->lire))) { $elementList['order_supplier_send'] = img_picto('', 'order', 'class="pictofixedwidth"').dol_escape_htmltag($langs->trans('MailToSendSupplierOrder')); } -if ((!empty($conf->fournisseur->enabled) && !empty($user->rights->fournisseur->facture->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (!empty($conf->supplier_invoice->enabled) && !empty($user->rights->supplier_invoice->lire))) { +if ((isModEnabled("fournisseur") && !empty($user->rights->fournisseur->facture->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (isModEnabled("supplier_invoice") && !empty($user->rights->supplier_invoice->lire))) { $elementList['invoice_supplier_send'] = img_picto('', 'bill', 'class="pictofixedwidth"').dol_escape_htmltag($langs->trans('MailToSendSupplierInvoice')); } if (!empty($conf->contrat->enabled) && !empty($user->rights->contrat->lire)) { diff --git a/htdocs/admin/stock.php b/htdocs/admin/stock.php index cc025258587..ade62c29081 100644 --- a/htdocs/admin/stock.php +++ b/htdocs/admin/stock.php @@ -293,7 +293,7 @@ $found = 0; print '
'.$langs->trans("ReStockOnBill").''; -if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { +if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) { if ($conf->use_javascript_ajax) { print ajax_constantonoff('STOCK_CALCULATE_ON_SUPPLIER_BILL', array(), null, 0, 0, 0, 2, 1); } else { @@ -311,7 +311,7 @@ $found++; print '
'.$langs->trans("ReStockOnValidateOrder").''; -if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { +if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) { if ($conf->use_javascript_ajax) { print ajax_constantonoff('STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER', array(), null, 0, 0, 0, 2, 1); } else { @@ -356,7 +356,7 @@ if (isModEnabled("reception")) { print '
'.$langs->trans("ReStockOnDispatchOrder").''; - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order")) { if ($conf->use_javascript_ajax) { print ajax_constantonoff('STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER', array(), null, 0, 0, 0, 2, 1); } else { diff --git a/htdocs/admin/workflow.php b/htdocs/admin/workflow.php index 6540cd4e0fa..e1899b35a56 100644 --- a/htdocs/admin/workflow.php +++ b/htdocs/admin/workflow.php @@ -123,7 +123,7 @@ $workflowcodes = array( 'WORKFLOW_ORDER_CLASSIFY_BILLED_SUPPLIER_PROPOSAL'=>array( 'family'=>'classify_supplier_proposal', 'position'=>60, - 'enabled'=>(!empty($conf->supplier_proposal->enabled) && ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled))), + 'enabled'=>(!empty($conf->supplier_proposal->enabled) && ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice"))), 'picto'=>'supplier_proposal', 'warning'=>'' ), @@ -132,7 +132,7 @@ $workflowcodes = array( 'WORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION'=>array( 'family'=>'classify_supplier_order', 'position'=>63, - 'enabled'=>(!empty($conf->global->MAIN_FEATURES_LEVEL) && (isModEnabled("reception")) && ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || empty($conf->supplier_order->enabled))), + 'enabled'=>(!empty($conf->global->MAIN_FEATURES_LEVEL) && (isModEnabled("reception")) && ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || empty($conf->supplier_order->enabled))), 'picto'=>'supplier_order', 'warning'=>'' ), @@ -140,7 +140,7 @@ $workflowcodes = array( 'WORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED'=>array( 'family'=>'classify_supplier_order', 'position'=>64, - 'enabled'=>(!empty($conf->global->MAIN_FEATURES_LEVEL) && (isModEnabled("reception")) && ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || empty($conf->supplier_order->enabled))), + 'enabled'=>(!empty($conf->global->MAIN_FEATURES_LEVEL) && (isModEnabled("reception")) && ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || empty($conf->supplier_order->enabled))), 'picto'=>'supplier_order', 'warning'=>'' ), @@ -148,7 +148,7 @@ $workflowcodes = array( 'WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER'=>array( 'family'=>'classify_supplier_order', 'position'=>65, - 'enabled'=>((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)), + 'enabled'=>((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")), 'picto'=>'supplier_order', 'warning'=>'' ), @@ -157,7 +157,7 @@ $workflowcodes = array( 'WORKFLOW_BILL_ON_RECEPTION'=>array( 'family'=>'classify_reception', 'position'=>80, - 'enabled'=>(isModEnabled("reception") && ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled))), + 'enabled'=>(isModEnabled("reception") && ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice"))), 'picto'=>'reception' ), diff --git a/htdocs/blockedlog/class/blockedlog.class.php b/htdocs/blockedlog/class/blockedlog.class.php index d5b668d6c1a..3ab2b63ad3f 100644 --- a/htdocs/blockedlog/class/blockedlog.class.php +++ b/htdocs/blockedlog/class/blockedlog.class.php @@ -151,7 +151,7 @@ class BlockedLog } /* Supplier - if (!empty($conf->fournisseur->enabled)) { + if (isModEnabled("fournisseur")) { $this->trackedevents['BILL_SUPPLIER_VALIDATE']='BlockedLogSupplierBillValidate'; $this->trackedevents['BILL_SUPPLIER_DELETE']='BlockedLogSupplierBillDelete'; $this->trackedevents['BILL_SUPPLIER_SENTBYMAIL']='BlockedLogSupplierBillSentByEmail'; // Trigger key does not exists, we want just into array to list it as done diff --git a/htdocs/comm/action/class/cactioncomm.class.php b/htdocs/comm/action/class/cactioncomm.class.php index f6586a853d2..db9f28c7763 100644 --- a/htdocs/comm/action/class/cactioncomm.class.php +++ b/htdocs/comm/action/class/cactioncomm.class.php @@ -207,10 +207,10 @@ class CActionComm if ($obj->module == 'propal' && isModEnabled("propal") && !empty($user->rights->propale->lire)) { $qualified = 1; } - if ($obj->module == 'invoice_supplier' && ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && !empty($user->rights->fournisseur->facture->lire)) || (!empty($conf->rights->supplier_invoice->enabled) && !empty($user->rights->supplier_invoice->lire)))) { + if ($obj->module == 'invoice_supplier' && ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && !empty($user->rights->fournisseur->facture->lire)) || (!empty($conf->rights->supplier_invoice->enabled) && !empty($user->rights->supplier_invoice->lire)))) { $qualified = 1; } - if ($obj->module == 'order_supplier' && ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && !empty($user->rights->fournisseur->commande->lire)) || (empty($conf->rights->supplier_order->enabled) && !empty($user->rights->supplier_order->lire)))) { + if ($obj->module == 'order_supplier' && ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && !empty($user->rights->fournisseur->commande->lire)) || (empty($conf->rights->supplier_order->enabled) && !empty($user->rights->supplier_order->lire)))) { $qualified = 1; } if ($obj->module == 'shipping' && isModEnabled("expedition") && !empty($user->rights->expedition->lire)) { diff --git a/htdocs/comm/index.php b/htdocs/comm/index.php index 83766254f28..6f9cfac40a5 100644 --- a/htdocs/comm/index.php +++ b/htdocs/comm/index.php @@ -99,7 +99,7 @@ if (!empty($conf->supplier_proposal->enabled)) { if (!empty($conf->commande->enabled)) { $orderstatic = new Commande($db); } -if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) { +if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order")) { $supplierorderstatic = new CommandeFournisseur($db); } @@ -421,7 +421,7 @@ if (!empty($conf->commande->enabled) && $user->rights->commande->lire) { * Draft purchase orders */ -if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->commande->lire) || (!empty($conf->supplier_order->enabled) && $user->rights->supplier_order->lire)) { +if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->commande->lire) || (isModEnabled("supplier_order") && $user->rights->supplier_order->lire)) { $sql = "SELECT cf.rowid, cf.ref, cf.ref_supplier, cf.total_ht, cf.total_tva, cf.total_ttc, cf.fk_statut as status"; $sql .= ", s.rowid as socid, s.nom as name, s.name_alias"; $sql .= ", s.code_client, s.code_compta, s.client"; @@ -667,7 +667,7 @@ if (isModEnabled("societe") && $user->rights->societe->lire) { $s .= ''.dol_substr($langs->trans("Customer"), 0, 1).''; } /* - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) && $obj->fournisseur) + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) && $obj->fournisseur) { $s .= ''.dol_substr($langs->trans("Supplier"), 0, 1).''; }*/ @@ -698,7 +698,7 @@ if (isModEnabled("societe") && $user->rights->societe->lire) { /* * Last suppliers */ -if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) && $user->rights->societe->lire) { +if (((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) && $user->rights->societe->lire) { $sql = "SELECT s.rowid as socid, s.nom as name, s.name_alias"; $sql .= ", s.code_client, s.code_compta, s.client"; $sql .= ", s.code_fournisseur, s.code_compta_fournisseur, s.fournisseur"; @@ -763,7 +763,7 @@ if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_S { $s .= ''.dol_substr($langs->trans("Customer"), 0, 1).''; }*/ - if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) && $obj->fournisseur) { + if (((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) && $obj->fournisseur) { $s .= ''.dol_substr($langs->trans("Supplier"), 0, 1).''; } print $s; diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 52fc2a296e4..690ed50536c 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -2806,7 +2806,7 @@ if ($action == 'create') { // Create a purchase order if (!empty($conf->global->WORKFLOW_CAN_CREATE_PURCHASE_ORDER_FROM_PROPOSAL)) { - if ($object->statut == Propal::STATUS_SIGNED && ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled))) { + if ($object->statut == Propal::STATUS_SIGNED && ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order"))) { if ($usercancreatepurchaseorder) { print ''.$langs->trans("AddPurchaseOrder").''; } diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 2cdb14779ba..07344dae69a 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -2768,7 +2768,7 @@ if ($action == 'create' && $usercancreate) { // Create a purchase order if (!empty($conf->global->WORKFLOW_CAN_CREATE_PURCHASE_ORDER_FROM_SALE_ORDER)) { - if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) && $object->statut > Commande::STATUS_DRAFT && $object->statut < Commande::STATUS_CLOSED && $object->getNbOfServicesLines() > 0) { + if (((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order")) && $object->statut > Commande::STATUS_DRAFT && $object->statut < Commande::STATUS_CLOSED && $object->getNbOfServicesLines() > 0) { if ($usercancreatepurchaseorder) { print dolGetButtonAction('', $langs->trans('AddPurchaseOrder'), 'default', DOL_URL_ROOT.'/fourn/commande/card.php?action=create&origin='.$object->element.'&originid='.$object->id.'&socid='.$object->socid, ''); } diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index 4a7216e30d8..710d5fa1941 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -2394,7 +2394,7 @@ if ($resql) { } $stock_order = $generic_product->stats_commande['qty']; } - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order")) { if (empty($productstat_cache[$generic_commande->lines[$lig]->fk_product]['stats_order_supplier'])) { $generic_product->load_stats_commande_fournisseur(0, '3'); $productstat_cache[$generic_commande->lines[$lig]->fk_product]['stats_order_supplier'] = $generic_product->stats_commande_fournisseur['qty']; @@ -2415,7 +2415,7 @@ if ($resql) { } else { $text_info .= ''.$langs->trans('Available').' : '.$text_stock_reel.''; } - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order")) { $text_info .= ' '.$langs->trans('SupplierOrder').' : '.$stock_order_supplier; } $text_info .= ($reliquat != $generic_commande->lines[$lig]->qty ? ' ('.$langs->trans("QtyInOtherShipments").' '.($generic_commande->lines[$lig]->qty - $reliquat).')' : ''); diff --git a/htdocs/compta/accounting-files.php b/htdocs/compta/accounting-files.php index a3cb900befb..da49cecb745 100644 --- a/htdocs/compta/accounting-files.php +++ b/htdocs/compta/accounting-files.php @@ -134,7 +134,7 @@ $error = 0; $listofchoices = array( 'selectinvoices'=>array('label'=>'Invoices', 'lang'=>'bills', 'enabled' => isModEnabled('facture'), 'perms' => !empty($user->rights->facture->lire)), - 'selectsupplierinvoices'=>array('label'=>'BillsSuppliers', 'lang'=>'bills', 'enabled' => !empty($conf->supplier_invoice->enabled), 'perms' => !empty($user->rights->fournisseur->facture->lire)), + 'selectsupplierinvoices'=>array('label'=>'BillsSuppliers', 'lang'=>'bills', 'enabled' => isModEnabled("supplier_invoice"), 'perms' => !empty($user->rights->fournisseur->facture->lire)), 'selectexpensereports'=>array('label'=>'ExpenseReports', 'lang'=>'trips', 'enabled' => !empty($conf->expensereport->enabled), 'perms' => !empty($user->rights->expensereport->lire)), 'selectdonations'=>array('label'=>'Donations', 'lang'=>'donation', 'enabled' => !empty($conf->don->enabled), 'perms' => !empty($user->rights->don->lire)), 'selectsocialcontributions'=>array('label'=>'SocialContributions', 'enabled' => !empty($conf->tax->enabled), 'perms' => !empty($user->rights->tax->charges->lire)), diff --git a/htdocs/compta/stats/supplier_turnover_by_thirdparty.php b/htdocs/compta/stats/supplier_turnover_by_thirdparty.php index 0be2df11190..d13bcfbf349 100644 --- a/htdocs/compta/stats/supplier_turnover_by_thirdparty.php +++ b/htdocs/compta/stats/supplier_turnover_by_thirdparty.php @@ -590,10 +590,10 @@ if (count($amount)) { if (!empty($conf->supplier_proposal->enabled) && $key > 0) { print ' '.img_picto($langs->trans("ProposalStats"), "stats").' '; } - if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) && $key > 0) { + if (((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order")) && $key > 0) { print ' '.img_picto($langs->trans("OrderStats"), "stats").' '; } - if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_invoice->enabled)) && $key > 0) { + if (((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_invoice")) && $key > 0) { print ' '.img_picto($langs->trans("InvoiceStats"), "stats").' '; } print '
'; diff --git a/htdocs/contact/list.php b/htdocs/contact/list.php index a0091061adb..f5810db2b13 100644 --- a/htdocs/contact/list.php +++ b/htdocs/contact/list.php @@ -753,7 +753,7 @@ if (!empty($conf->categorie->enabled) && $user->rights->categorie->lire) { $moreforfilter .= ''; } - if (!empty($conf->fournisseur->enabled) && (empty($type) || $type == 'f')) { + if (isModEnabled("fournisseur") && (empty($type) || $type == 'f')) { $moreforfilter .= '
'; $tmptitle = $langs->trans('SuppliersCategoriesShort'); $moreforfilter .= img_picto($tmptitle, 'category', 'class="pictofixedwidth"'); diff --git a/htdocs/core/boxes/box_dolibarr_state_board.php b/htdocs/core/boxes/box_dolibarr_state_board.php index 83615c17fd3..a979e3e5a36 100644 --- a/htdocs/core/boxes/box_dolibarr_state_board.php +++ b/htdocs/core/boxes/box_dolibarr_state_board.php @@ -116,9 +116,9 @@ class box_dolibarr_state_board extends ModeleBoxes 'members' => isModEnabled('adherent') && $user->rights->adherent->lire, 'customers' => isModEnabled('societe') && $user->rights->societe->lire && empty($conf->global->SOCIETE_DISABLE_CUSTOMERS) && empty($conf->global->SOCIETE_DISABLE_CUSTOMERS_STATS), 'prospects' => isModEnabled('societe') && $user->rights->societe->lire && empty($conf->global->SOCIETE_DISABLE_PROSPECTS) && empty($conf->global->SOCIETE_DISABLE_PROSPECTS_STATS), - 'suppliers' => ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->lire) - || (!empty($conf->supplier_order->enabled) && $user->rights->supplier_order->lire) - || (!empty($conf->supplier_invoice->enabled) && $user->rights->supplier_invoice->lire) + 'suppliers' => ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->lire) + || (isModEnabled("supplier_order") && $user->rights->supplier_order->lire) + || (isModEnabled("supplier_invoice") && $user->rights->supplier_invoice->lire) ) && empty($conf->global->SOCIETE_DISABLE_SUPPLIERS_STATS), 'contacts' => isModEnabled('societe') && $user->hasRight('societe', 'contact', 'lire'), diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 6755bd29c14..02a7fdbc7bc 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -8721,12 +8721,12 @@ class Form 'label'=>'LinkToSupplierProposal', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, '' as ref_supplier, t.total_ht FROM ".$this->db->prefix()."societe as s, ".$this->db->prefix()."supplier_proposal as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$this->db->sanitize($listofidcompanytoscan).') AND t.entity IN ('.getEntity('supplier_proposal').')'), 'order_supplier'=>array( - 'enabled'=>(!empty($conf->supplier_order->enabled) ? $conf->supplier_order->enabled : 0), + 'enabled'=>(isModEnabled("supplier_order") ? $conf->supplier_order->enabled : 0), 'perms'=>1, 'label'=>'LinkToSupplierOrder', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_supplier, t.total_ht FROM ".$this->db->prefix()."societe as s, ".$this->db->prefix()."commande_fournisseur as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$this->db->sanitize($listofidcompanytoscan).') AND t.entity IN ('.getEntity('commande_fournisseur').')'), 'invoice_supplier'=>array( - 'enabled'=>(!empty($conf->supplier_invoice->enabled) ? $conf->supplier_invoice->enabled : 0), + 'enabled'=>(isModEnabled("supplier_invoice") ? $conf->supplier_invoice->enabled : 0), 'perms'=>1, 'label'=>'LinkToSupplierInvoice', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_supplier, t.total_ht FROM ".$this->db->prefix()."societe as s, ".$this->db->prefix()."facture_fourn as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$this->db->sanitize($listofidcompanytoscan).') AND t.entity IN ('.getEntity('facture_fourn').')'), 'ticket'=>array( diff --git a/htdocs/core/class/html.formcompany.class.php b/htdocs/core/class/html.formcompany.class.php index 2a900ea53a4..915a5083ce8 100644 --- a/htdocs/core/class/html.formcompany.class.php +++ b/htdocs/core/class/html.formcompany.class.php @@ -1059,7 +1059,7 @@ class FormCompany extends Form if (empty($conf->global->SOCIETE_DISABLE_CUSTOMERS)) { $out .= ''; } - if (!empty($conf->fournisseur->enabled)) { + if (isModEnabled("fournisseur")) { $out .= ''; } $out .= ''; diff --git a/htdocs/core/lib/company.lib.php b/htdocs/core/lib/company.lib.php index 908dacb870c..6ba3ca18094 100644 --- a/htdocs/core/lib/company.lib.php +++ b/htdocs/core/lib/company.lib.php @@ -128,7 +128,7 @@ function societe_prepare_head(Societe $object) } } $supplier_module_enabled = 0; - if ((isModEnabled('fournisseur') && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_proposal->enabled) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { + if ((isModEnabled('fournisseur') && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_proposal->enabled) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) { $supplier_module_enabled = 1; } if ($supplier_module_enabled == 1 && $object->fournisseur && !empty($user->rights->fournisseur->lire)) { @@ -179,7 +179,7 @@ function societe_prepare_head(Societe $object) } // Related items - if ((isModEnabled('commande') || isModEnabled('propal') || isModEnabled('facture') || isModEnabled('ficheinter') || (isModEnabled('fournisseur') && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) + if ((isModEnabled('commande') || isModEnabled('propal') || isModEnabled('facture') || isModEnabled('ficheinter') || (isModEnabled('fournisseur') && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) && empty($conf->global->THIRDPARTIES_DISABLE_RELATED_OBJECT_TAB)) { $head[$h][0] = DOL_URL_ROOT.'/societe/consumption.php?socid='.$object->id; $head[$h][1] = $langs->trans("Referers"); diff --git a/htdocs/core/lib/contact.lib.php b/htdocs/core/lib/contact.lib.php index f3b85233ca7..ad9c47f4c48 100644 --- a/htdocs/core/lib/contact.lib.php +++ b/htdocs/core/lib/contact.lib.php @@ -92,7 +92,7 @@ function contact_prepare_head(Contact $object) } // Related items - if (!empty($conf->commande->enabled) || isModEnabled("propal") || isModEnabled('facture') || !empty($conf->ficheinter->enabled) || (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { + if (!empty($conf->commande->enabled) || isModEnabled("propal") || isModEnabled('facture') || !empty($conf->ficheinter->enabled) || (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) { $head[$tab][0] = DOL_URL_ROOT.'/contact/consumption.php?id='.$object->id; $head[$tab][1] = $langs->trans("Referers"); $head[$tab][2] = 'consumption'; diff --git a/htdocs/core/lib/invoice.lib.php b/htdocs/core/lib/invoice.lib.php index 52daea0f150..9e60f20fd25 100644 --- a/htdocs/core/lib/invoice.lib.php +++ b/htdocs/core/lib/invoice.lib.php @@ -1072,7 +1072,7 @@ function getPurchaseInvoiceUnpaidOpenTable($maxCount = 500, $socid = 0) $result = ''; - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->facture->lire) || (!empty($conf->supplier_invoice->enabled) && $user->rights->supplier_invoice->lire)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->facture->lire) || (isModEnabled("supplier_invoice") && $user->rights->supplier_invoice->lire)) { $facstatic = new FactureFournisseur($db); $sql = "SELECT ff.rowid, ff.ref, ff.fk_statut as status, ff.type, ff.libelle as label, ff.total_ht, ff.total_tva, ff.total_ttc, ff.paye"; diff --git a/htdocs/core/lib/product.lib.php b/htdocs/core/lib/product.lib.php index be12e5c81d1..3a64ebb095a 100644 --- a/htdocs/core/lib/product.lib.php +++ b/htdocs/core/lib/product.lib.php @@ -58,7 +58,7 @@ function product_prepare_head($object) } if (!empty($object->status_buy) || (!empty($conf->margin->enabled) && !empty($object->status))) { // If margin is on and product on sell, we may need the cost price even if product os not on purchase - if ((((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) && $user->rights->fournisseur->lire) + if ((((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) && $user->rights->fournisseur->lire) || (!empty($conf->margin->enabled) && $user->rights->margin->liretous) ) { $head[$h][0] = DOL_URL_ROOT."/product/fournisseurs.php?id=".$object->id; @@ -431,7 +431,7 @@ function show_stats_for_company($product, $socid) print '
'; print $form->editfieldkey("OrderMinAmount", 'supplier_order_min_amount', $object->supplier_order_min_amount, $object, $user->rights->societe->creer); @@ -408,7 +408,7 @@ if ($object->id > 0) { } } - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order")) { // Box proposals $tmp = $object->getOutstandingOrders('supplier'); $outstandingOpened = $tmp['opened']; @@ -429,7 +429,7 @@ if ($object->id > 0) { } } - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_invoice->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_invoice")) { $warn = ''; $tmp = $object->getOutstandingBills('supplier'); $outstandingOpened = $tmp['opened']; diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index d4a0d587f68..d03bb8c2850 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -3367,7 +3367,7 @@ class CommandeFournisseur extends CommonOrder { global $conf, $langs; - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order")) { require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.dispatch.class.php'; $qtydelivered = array(); diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index 8e9c340b1df..c939c3433aa 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -2561,7 +2561,7 @@ if ($action == 'create') { } if (in_array($object->statut, array(3, 4, 5))) { - if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) && $usercanreceive) { + if (((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order")) && $usercanreceive) { print ''; } else { print ''; @@ -2587,7 +2587,7 @@ if ($action == 'create') { // Create bill //if (isModEnabled('facture')) //{ - if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_invoice->enabled)) && ($object->statut >= 2 && $object->statut != 7 && $object->billed != 1)) { // statut 2 means approved, 7 means canceled + if (((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_invoice")) && ($object->statut >= 2 && $object->statut != 7 && $object->billed != 1)) { // statut 2 means approved, 7 means canceled if ($user->rights->fournisseur->facture->creer || $user->rights->supplier_invoice->creer) { print ''.$langs->trans("CreateBill").''; } diff --git a/htdocs/fourn/commande/index.php b/htdocs/fourn/commande/index.php index 7d6b3b6936a..052876f0616 100644 --- a/htdocs/fourn/commande/index.php +++ b/htdocs/fourn/commande/index.php @@ -172,7 +172,7 @@ if ($resql) { * Draft orders */ -if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) { +if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order")) { $sql = "SELECT c.rowid, c.ref, s.nom as name, s.rowid as socid"; $sql .= " FROM ".MAIN_DB_PREFIX."commande_fournisseur as c"; $sql .= ", ".MAIN_DB_PREFIX."societe as s"; diff --git a/htdocs/fourn/index.php b/htdocs/fourn/index.php index 1dc3e963db7..68a6d663d8a 100644 --- a/htdocs/fourn/index.php +++ b/htdocs/fourn/index.php @@ -99,7 +99,7 @@ if ($resql) { // Draft orders -if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) { +if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order")) { $langs->load("orders"); $sql = "SELECT cf.rowid, cf.ref, cf.total_ttc,"; @@ -157,7 +157,7 @@ if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SU } // Draft invoices -if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_invoice->enabled)) && $user->rights->fournisseur->facture->lire) { +if (((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_invoice")) && $user->rights->fournisseur->facture->lire) { $sql = "SELECT ff.ref_supplier, ff.rowid, ff.total_ttc, ff.type"; $sql .= ", s.nom as name, s.rowid as socid"; $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as ff"; diff --git a/htdocs/fourn/recap-fourn.php b/htdocs/fourn/recap-fourn.php index 0e551d4e16d..b5489a3d8e0 100644 --- a/htdocs/fourn/recap-fourn.php +++ b/htdocs/fourn/recap-fourn.php @@ -63,7 +63,7 @@ if ($socid > 0) { dol_banner_tab($societe, 'socid', '', ($user->socid ? 0 : 1), 'rowid', 'nom'); print dol_get_fiche_end(); - if ((!empty($conf->fournisseur->enabled) && $user->rights->fournisseur->facture->lire && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (!empty($conf->supplier_invoice->enabled) && $user->rights->supplier_invoice->lire)) { + if ((isModEnabled("fournisseur") && $user->rights->fournisseur->facture->lire && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (isModEnabled("supplier_invoice") && $user->rights->supplier_invoice->lire)) { // Invoice list print load_fiche_titre($langs->trans("SupplierPreview")); diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 9f709a86e47..6a0fda06cb0 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -2497,7 +2497,7 @@ function printDropdownQuickadd() "title" => "NewSupplierOrderShort@orders", "name" => "SupplierOrder@orders", "picto" => "supplier_order", - "activation" => (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "commande", "write")) || (!empty($conf->supplier_order->enabled) && $user->hasRight("supplier_invoice", "write")), // vs hooking + "activation" => (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "commande", "write")) || (isModEnabled("supplier_order") && $user->hasRight("supplier_invoice", "write")), // vs hooking "position" => 80, ), array( @@ -2505,7 +2505,7 @@ function printDropdownQuickadd() "title" => "NewBill@bills", "name" => "SupplierBill@bills", "picto" => "supplier_invoice", - "activation" => (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "write")) || (!empty($conf->supplier_invoice->enabled) && $user->hasRight("supplier_invoice", "write")), // vs hooking + "activation" => (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "write")) || (isModEnabled("supplier_invoice") && $user->hasRight("supplier_invoice", "write")), // vs hooking "position" => 90, ), array( diff --git a/htdocs/margin/tabs/thirdpartyMargins.php b/htdocs/margin/tabs/thirdpartyMargins.php index c69c0443e28..363af100cbe 100644 --- a/htdocs/margin/tabs/thirdpartyMargins.php +++ b/htdocs/margin/tabs/thirdpartyMargins.php @@ -129,7 +129,7 @@ if ($socid > 0) { print '
'; print $langs->trans('SupplierCode').''; print showValueWithClipboardCPButton(dol_escape_htmltag($object->code_fournisseur)); diff --git a/htdocs/product/admin/product.php b/htdocs/product/admin/product.php index eeeaa094f29..6c3497c22ae 100644 --- a/htdocs/product/admin/product.php +++ b/htdocs/product/admin/product.php @@ -596,7 +596,7 @@ print $form->selectPriceBaseType($conf->global->PRODUCT_PRICE_BASE_TYPE, "price_ print '
'.$langs->trans("UseProductSupplierPackaging").''; diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index d6393ab139b..1a157ed9171 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -5477,7 +5477,7 @@ class Product extends CommonObject } $stock_sending_client = $this->stats_expedition['qty']; } - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order")) { $filterStatus = empty($conf->global->SUPPLIER_ORDER_STATUS_FOR_VIRTUAL_STOCK) ? '3,4' : $conf->global->SUPPLIER_ORDER_STATUS_FOR_VIRTUAL_STOCK; if (isset($includedraftpoforvirtual)) { $filterStatus = '0,1,2,'.$filterStatus; // 1,2 may have already been inside $filterStatus but it is better to have twice than missing $filterStatus does not include them @@ -5488,7 +5488,7 @@ class Product extends CommonObject } $stock_commande_fournisseur = $this->stats_commande_fournisseur['qty']; } - if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) && empty($conf->reception->enabled)) { + if (((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) && empty($conf->reception->enabled)) { // Case module reception is not used $filterStatus = '4'; if (isset($includedraftpoforvirtual)) { @@ -5500,7 +5500,7 @@ class Product extends CommonObject } $stock_reception_fournisseur = $this->stats_reception['qty']; } - if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) && isModEnabled("reception")) { + if (((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) && isModEnabled("reception")) { // Case module reception is used $filterStatus = '4'; if (isset($includedraftpoforvirtual)) { diff --git a/htdocs/product/list.php b/htdocs/product/list.php index 043a6bc3db8..7727eaf1787 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -1699,7 +1699,7 @@ if ($resql) { //print price($obj->minsellprice).' '.$langs->trans("HT"); if ($product_fourn->find_min_price_product_fournisseur($obj->rowid) > 0) { if ($product_fourn->product_fourn_price_id > 0) { - if ((!empty($conf->fournisseur->enabled) && !empty($user->rights->fournisseur->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (!empty($conf->supplier_order->enabled) && !empty($user->rights->supplier_order->lire)) || (!empty($conf->supplier_invoice->enabled) && !empty($user->rights->supplier_invoice->lire))) { + if ((isModEnabled("fournisseur") && !empty($user->rights->fournisseur->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (isModEnabled("supplier_order") && !empty($user->rights->supplier_order->lire)) || (isModEnabled("supplier_invoice") && !empty($user->rights->supplier_invoice->lire))) { $htmltext = $product_fourn->display_price_product_fournisseur(1, 1, 0, 1); print ''.$form->textwithpicto(price($product_fourn->fourn_unitprice * (1 - $product_fourn->fourn_remise_percent / 100) - $product_fourn->fourn_remise).' '.$langs->trans("HT"), $htmltext).''; } else { diff --git a/htdocs/product/stock/product.php b/htdocs/product/stock/product.php index 59ab97873da..51b12d4a6b1 100644 --- a/htdocs/product/stock/product.php +++ b/htdocs/product/stock/product.php @@ -794,7 +794,7 @@ if ($id > 0 || $ref) { } // Number of supplier order running - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) { if ($found) { $helpondiff .= '
'; } else { @@ -810,7 +810,7 @@ if ($id > 0 || $ref) { } // Number of product from supplier order already received (partial receipt) - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) { if ($found) { $helpondiff .= '
'; } else { diff --git a/htdocs/product/stock/replenish.php b/htdocs/product/stock/replenish.php index 91bb390e1f9..f2821eab8ce 100644 --- a/htdocs/product/stock/replenish.php +++ b/htdocs/product/stock/replenish.php @@ -438,7 +438,7 @@ if ($usevirtualstock) { $sqlExpeditionsCli = '0'; } - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order")) { $sqlCommandesFourn = "(SELECT ".$db->ifsql("SUM(cd3.qty) IS NULL", "0", "SUM(cd3.qty)")." as qty"; // We need the ifsql because if result is 0 for product p.rowid, we must return 0 and not NULL $sqlCommandesFourn .= " FROM ".MAIN_DB_PREFIX."commande_fournisseurdet as cd3,"; $sqlCommandesFourn .= " ".MAIN_DB_PREFIX."commande_fournisseur as c3"; diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index 95abbfa8f47..246ae6b7ba8 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -1360,11 +1360,11 @@ if ($action == 'create' && $user->rights->projet->creer) { $langs->load("supplier_proposal"); print dolGetButtonAction('', $langs->trans('AddSupplierProposal'), 'default', DOL_URL_ROOT.'/supplier_proposal/card.php?action=create&projectid='.$object->id.'&socid='.$object->socid, '', 1, array('isDropDown' => true)); } - if (!empty($conf->supplier_order->enabled) && ($user->rights->fournisseur->commande->creer || $user->rights->supplier_order->creer)) { + if (isModEnabled("supplier_order") && ($user->rights->fournisseur->commande->creer || $user->rights->supplier_order->creer)) { $langs->load("suppliers"); print dolGetButtonAction('', $langs->trans('AddSupplierOrder'), 'default', DOL_URL_ROOT.'/fourn/commande/card.php?action=create&projectid='.$object->id.'&socid='.$object->socid, '', 1, array('isDropDown' => true)); } - if (!empty($conf->supplier_invoice->enabled) && ($user->rights->fournisseur->facture->creer || $user->rights->supplier_invoice->creer)) { + if (isModEnabled("supplier_invoice") && ($user->rights->fournisseur->facture->creer || $user->rights->supplier_invoice->creer)) { $langs->load("suppliers"); print dolGetButtonAction('', $langs->trans('AddSupplierInvoice'), 'default', DOL_URL_ROOT.'/fourn/facture/card.php?action=create&projectid='.$object->id.'&socid='.$object->socid, '', 1, array('isDropDown' => true)); } diff --git a/htdocs/projet/element.php b/htdocs/projet/element.php index 586d1f9d23b..a96ba8c2819 100644 --- a/htdocs/projet/element.php +++ b/htdocs/projet/element.php @@ -52,10 +52,10 @@ if (!empty($conf->commande->enabled)) { if (!empty($conf->supplier_proposal->enabled)) { require_once DOL_DOCUMENT_ROOT.'/supplier_proposal/class/supplier_proposal.class.php'; } -if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_invoice->enabled)) { +if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_invoice")) { require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php'; } -if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) { +if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order")) { require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php'; } if (!empty($conf->contrat->enabled)) { diff --git a/htdocs/reception/card.php b/htdocs/reception/card.php index 6fc1fd51349..279dad1dfac 100644 --- a/htdocs/reception/card.php +++ b/htdocs/reception/card.php @@ -50,7 +50,7 @@ if (isModEnabled("product") || isModEnabled("service")) { if (isModEnabled("propal")) { require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php'; } -if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) { +if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order")) { require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php'; require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.dispatch.class.php'; } @@ -129,7 +129,7 @@ if ($id > 0 || !empty($ref)) { } // Linked documents - if ($origin == 'order_supplier' && $object->$typeobject->id && (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_order->enabled))) { + if ($origin == 'order_supplier' && $object->$typeobject->id && (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_order"))) { $origin_id = $object->$typeobject->id; $objectsrc = new CommandeFournisseur($db); $objectsrc->fetch($object->$typeobject->id); @@ -770,7 +770,7 @@ if ($action == 'create') { // Ref print '
'; - if ($origin == 'supplierorder' && ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled))) { + if ($origin == 'supplierorder' && ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order"))) { print $langs->trans("RefOrder").''.img_object($langs->trans("ShowOrder"), 'order').' '.$objectsrc->ref; } if ($origin == 'propal' && isModEnabled("propal")) { @@ -1366,7 +1366,7 @@ if ($action == 'create') { $objectsrc = new Propal($db); $objectsrc->fetch($object->$typeobject->id); } - if ($typeobject == 'CommandeFournisseur' && $object->$typeobject->id && ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled))) { + if ($typeobject == 'CommandeFournisseur' && $object->$typeobject->id && ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order"))) { $objectsrc = new CommandeFournisseur($db); $objectsrc->fetch($object->$typeobject->id); } @@ -2101,7 +2101,7 @@ if ($action == 'create') { } // Create bill - if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_invoice->enabled)) && ($object->statut == Reception::STATUS_VALIDATED || $object->statut == Reception::STATUS_CLOSED)) { + if (((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_invoice")) && ($object->statut == Reception::STATUS_VALIDATED || $object->statut == Reception::STATUS_CLOSED)) { if ($user->rights->fournisseur->facture->creer || $user->rights->supplier_invoice->creer) { // TODO show button only if (! empty($conf->global->WORKFLOW_BILL_ON_RECEPTION)) // If we do that, we must also make this option official. @@ -2115,7 +2115,7 @@ if ($action == 'create') { if ($user->rights->reception->creer && $object->statut > 0 && !$object->billed) { $label = "Close"; $paramaction = 'classifyclosed'; // = Transferred/Received // Label here should be "Close" or "ClassifyBilled" if we decided to make bill on receptions instead of orders - if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) && !empty($conf->global->WORKFLOW_BILL_ON_RECEPTION)) { // Quand l'option est on, il faut avoir le bouton en plus et non en remplacement du Close ? + if (((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order")) && !empty($conf->global->WORKFLOW_BILL_ON_RECEPTION)) { // Quand l'option est on, il faut avoir le bouton en plus et non en remplacement du Close ? $label = "ClassifyBilled"; $paramaction = 'classifybilled'; } diff --git a/htdocs/reception/contact.php b/htdocs/reception/contact.php index 83f84d787f8..5b10ac8bcb1 100644 --- a/htdocs/reception/contact.php +++ b/htdocs/reception/contact.php @@ -54,7 +54,7 @@ if ($id > 0 || !empty($ref)) { } // Linked documents - if ($origin == 'order_supplier' && $object->$typeobject->id && (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_order->enabled))) { + if ($origin == 'order_supplier' && $object->$typeobject->id && (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_order"))) { $objectsrc = new CommandeFournisseur($db); $objectsrc->fetch($object->$typeobject->id); } @@ -192,7 +192,7 @@ if ($id > 0 || !empty($ref)) { print ''; // Linked documents - if ($origin == 'order_supplier' && $object->$typeobject->id && (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_order->enabled))) { + if ($origin == 'order_supplier' && $object->$typeobject->id && (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_order"))) { print '
'; $objectsrc = new CommandeFournisseur($db); $objectsrc->fetch($object->$typeobject->id); diff --git a/htdocs/societe/canvas/actions_card_common.class.php b/htdocs/societe/canvas/actions_card_common.class.php index 4ef3d64a424..5a26946913c 100644 --- a/htdocs/societe/canvas/actions_card_common.class.php +++ b/htdocs/societe/canvas/actions_card_common.class.php @@ -186,7 +186,7 @@ abstract class ActionsCardCommon $s = $modCodeClient->getToolTip($langs, $this->object, 0); $this->tpl['help_customercode'] = $form->textwithpicto('', $s, 1); - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) { $this->tpl['supplier_enabled'] = 1; // Load object modCodeFournisseur diff --git a/htdocs/societe/card.php b/htdocs/societe/card.php index 69ba6443fe3..5d557d30a02 100644 --- a/htdocs/societe/card.php +++ b/htdocs/societe/card.php @@ -1049,7 +1049,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { $object->client = 1; } - if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) && (GETPOST("type") == 'f' || (GETPOST("type") == '' && !empty($conf->global->THIRDPARTY_SUPPLIER_BY_DEFAULT)))) { + if (((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) && (GETPOST("type") == 'f' || (GETPOST("type") == '' && !empty($conf->global->THIRDPARTY_SUPPLIER_BY_DEFAULT)))) { $object->fournisseur = 1; } @@ -1467,7 +1467,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print '
'; print '
'; - if ((!empty($conf->fournisseur->enabled) && !empty($user->rights->fournisseur->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (!empty($conf->supplier_order->enabled) && !empty($user->rights->supplier_order->lire)) || (!empty($conf->supplier_invoice->enabled) && !empty($user->rights->supplier_invoice->lire))) { + if ((isModEnabled("fournisseur") && !empty($user->rights->fournisseur->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (isModEnabled("supplier_order") && !empty($user->rights->supplier_order->lire)) || (isModEnabled("supplier_invoice") && !empty($user->rights->supplier_invoice->lire))) { print $form->editfieldkey('SupplierCode', 'supplier_code', '', $object, 0); } print ''; - if ((!empty($conf->fournisseur->enabled) && !empty($user->rights->fournisseur->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (!empty($conf->supplier_order->enabled) && !empty($user->rights->supplier_order->lire)) || (!empty($conf->supplier_invoice->enabled) && !empty($user->rights->supplier_invoice->lire))) { + if ((isModEnabled("fournisseur") && !empty($user->rights->fournisseur->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (isModEnabled("supplier_order") && !empty($user->rights->supplier_order->lire)) || (isModEnabled("supplier_invoice") && !empty($user->rights->supplier_invoice->lire))) { print ''; // Supplier - if (((!empty($conf->fournisseur->enabled) && !empty($user->rights->fournisseur->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (!empty($conf->supplier_order->enabled) && !empty($user->rights->supplier_order->lire)) || (!empty($conf->supplier_invoice->enabled) && !empty($user->rights->supplier_invoice->lire))) + if (((isModEnabled("fournisseur") && !empty($user->rights->fournisseur->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (isModEnabled("supplier_order") && !empty($user->rights->supplier_order->lire)) || (isModEnabled("supplier_invoice") && !empty($user->rights->supplier_invoice->lire))) || (!empty($conf->supplier_proposal->enabled) && !empty($user->rights->supplier_proposal->lire))) { print ''; print ''; @@ -2178,7 +2178,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print ''; } print ''; @@ -2469,7 +2469,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print ""; // Supplier - if ((!empty($conf->fournisseur->enabled) && !empty($user->rights->fournisseur->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (!empty($conf->supplier_order->enabled) && !empty($user->rights->supplier_order->lire)) || (!empty($conf->supplier_invoice->enabled) && !empty($user->rights->supplier_invoice->lire))) { + if ((isModEnabled("fournisseur") && !empty($user->rights->fournisseur->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (isModEnabled("supplier_order") && !empty($user->rights->supplier_order->lire)) || (isModEnabled("supplier_invoice") && !empty($user->rights->supplier_invoice->lire))) { print ''; print ''; print ''; } - if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) && $object->fournisseur && !empty($user->rights->fournisseur->lire)) { + if (((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) && $object->fournisseur && !empty($user->rights->fournisseur->lire)) { print ''; // Bank line - if (isModEnabled("banque") && ($conf->global->ADHERENT_BANK_USE || $object->fk_bank)) { + if (isModEnabled("banque") && (!empty($conf->global->ADHERENT_BANK_USE) || $object->fk_bank)) { print ''; // Bank line - if (isModEnabled("banque") && ($conf->global->ADHERENT_BANK_USE || $object->fk_bank)) { + if (isModEnabled("banque") && (!empty($conf->global->ADHERENT_BANK_USE) || $object->fk_bank)) { print ''; + // Desc $desc = (GETPOST('desc-'.$key) ? GETPOST('desc-'.$key) : $object->multilangs[$key]['description']); print ''; - + // Desc $desc = (GETPOST('desc-'.$key) ? GETPOST('desc-'.$key) : $object->multilangs[$key]['description']); print '
'; $tmpcode = $object->code_fournisseur; if (empty($tmpcode) && !empty($modCodeFournisseur->code_auto)) { @@ -1770,7 +1770,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { } // Supplier - if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { + if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) { print '
'.$form->editfieldkey('SuppliersCategoriesShort', 'suppcats', '', $object, 0).''; $cate_arbo = $form->select_all_categories(Categorie::TYPE_SUPPLIER, null, 'parent', null, null, 1); print img_picto('', 'category', 'class="pictofixedwidth"').$form->multiselectarray('suppcats', $cate_arbo, GETPOST('suppcats', 'array'), null, null, 'quatrevingtpercent widthcentpercentminusx', 0, 0); @@ -2167,7 +2167,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print '
'.$form->editfieldkey('Supplier', 'fournisseur', '', $object, 0, 'string', '', 1).'
'; - if ((!empty($conf->fournisseur->enabled) && !empty($user->rights->fournisseur->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (!empty($conf->supplier_order->enabled) && !empty($user->rights->supplier_order->lire)) || (!empty($conf->supplier_invoice->enabled) && !empty($user->rights->supplier_invoice->lire))) { + if ((isModEnabled("fournisseur") && !empty($user->rights->fournisseur->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (isModEnabled("supplier_order") && !empty($user->rights->supplier_order->lire)) || (isModEnabled("supplier_invoice") && !empty($user->rights->supplier_invoice->lire))) { print $form->editfieldkey('SupplierCode', 'supplier_code', '', $object, 0); } print '
'.$form->editfieldkey('SuppliersCategoriesShort', 'suppcats', '', $object, 0).''; $cate_arbo = $form->select_all_categories(Categorie::TYPE_SUPPLIER, null, null, null, null, 1); @@ -2674,7 +2674,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { } // Supplier code - if (((!empty($conf->fournisseur->enabled) && !empty($user->rights->fournisseur->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (!empty($conf->supplier_order->enabled) && !empty($user->rights->supplier_order->lire)) || (!empty($conf->supplier_invoice->enabled) && !empty($user->rights->supplier_invoice->lire))) && $object->fournisseur) { + if (((isModEnabled("fournisseur") && !empty($user->rights->fournisseur->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (isModEnabled("supplier_order") && !empty($user->rights->supplier_order->lire)) || (isModEnabled("supplier_invoice") && !empty($user->rights->supplier_invoice->lire))) && $object->fournisseur) { print '
'; print $langs->trans('SupplierCode').''; print showValueWithClipboardCPButton(dol_escape_htmltag($object->code_fournisseur)); @@ -2889,7 +2889,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { } // Supplier - if (((!empty($conf->fournisseur->enabled) && !empty($user->rights->fournisseur->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (!empty($conf->supplier_order->enabled) && !empty($user->rights->supplier_order->lire)) || (!empty($conf->supplier_invoice->enabled) && !empty($user->rights->supplier_invoice->lire))) && $object->fournisseur) { + if (((isModEnabled("fournisseur") && !empty($user->rights->fournisseur->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (isModEnabled("supplier_order") && !empty($user->rights->supplier_order->lire)) || (isModEnabled("supplier_invoice") && !empty($user->rights->supplier_invoice->lire))) && $object->fournisseur) { print '
'.$langs->trans("SuppliersCategoriesShort").''; print $form->showCategories($object->id, Categorie::TYPE_SUPPLIER, 1); diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 1c41b7ee186..cb20caca7ab 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -2808,7 +2808,7 @@ class Societe extends CommonObject } } if (empty($option) || preg_match('/supplier/', $option)) { - if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) && $this->fournisseur) { + if (((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) && $this->fournisseur) { $s .= '<'.$tag.' class="vendor-back" title="'.$langs->trans("Supplier").'" href="'.DOL_URL_ROOT.'/fourn/card.php?socid='.$this->id.'">'.dol_substr($langs->trans("Supplier"), 0, 1).''; } } diff --git a/htdocs/societe/consumption.php b/htdocs/societe/consumption.php index b7f66ea8ba2..03c78a0c07b 100644 --- a/htdocs/societe/consumption.php +++ b/htdocs/societe/consumption.php @@ -199,10 +199,10 @@ if ($object->fournisseur) { $obj = $db->fetch_object($resql); $nbCmdsFourn = $obj->nb; $thirdTypeArray['supplier'] = $langs->trans("supplier"); - if ((isModEnabled('fournisseur') && $user->rights->fournisseur->facture->lire && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (!empty($conf->supplier_invoice->enabled) && $user->rights->supplier_invoice->lire)) { + if ((isModEnabled('fournisseur') && $user->rights->fournisseur->facture->lire && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (isModEnabled("supplier_invoice") && $user->rights->supplier_invoice->lire)) { $elementTypeArray['supplier_invoice'] = $langs->transnoentitiesnoconv('SuppliersInvoices'); } - if ((isModEnabled('fournisseur') && $user->rights->fournisseur->commande->lire && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (!empty($conf->supplier_order->enabled) && $user->rights->supplier_order->lire)) { + if ((isModEnabled('fournisseur') && $user->rights->fournisseur->commande->lire && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (isModEnabled("supplier_order") && $user->rights->supplier_order->lire)) { $elementTypeArray['supplier_order'] = $langs->transnoentitiesnoconv('SuppliersOrders'); } if (isModEnabled('supplier_proposal') && $user->rights->supplier_proposal->lire) { diff --git a/htdocs/societe/list.php b/htdocs/societe/list.php index aad8d3edc3e..bf3ec6eb041 100644 --- a/htdocs/societe/list.php +++ b/htdocs/societe/list.php @@ -219,9 +219,9 @@ $arrayfields = array( 's.name_alias'=>array('label'=>"AliasNameShort", 'position'=>3, 'checked'=>1), 's.barcode'=>array('label'=>"Gencod", 'position'=>5, 'checked'=>1, 'enabled'=>(isModEnabled('barcode'))), 's.code_client'=>array('label'=>"CustomerCodeShort", 'position'=>10, 'checked'=>$checkedcustomercode), - 's.code_fournisseur'=>array('label'=>"SupplierCodeShort", 'position'=>11, 'checked'=>$checkedsuppliercode, 'enabled'=>((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled))), + 's.code_fournisseur'=>array('label'=>"SupplierCodeShort", 'position'=>11, 'checked'=>$checkedsuppliercode, 'enabled'=>((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice"))), 's.code_compta'=>array('label'=>"CustomerAccountancyCodeShort", 'position'=>13, 'checked'=>$checkedcustomeraccountcode), - 's.code_compta_fournisseur'=>array('label'=>"SupplierAccountancyCodeShort", 'position'=>14, 'checked'=>$checkedsupplieraccountcode, 'enabled'=>((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled))), + 's.code_compta_fournisseur'=>array('label'=>"SupplierAccountancyCodeShort", 'position'=>14, 'checked'=>$checkedsupplieraccountcode, 'enabled'=>((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice"))), 's.address'=>array('label'=>"Address", 'position'=>19, 'checked'=>0), 's.zip'=>array('label'=>"Zip", 'position'=>20, 'checked'=>1), 's.town'=>array('label'=>"Town", 'position'=>21, 'checked'=>0), @@ -980,7 +980,7 @@ if (empty($type) || $type == 'c' || $type == 'p') { } if (empty($type) || $type == 'f') { - if (!empty($conf->fournisseur->enabled) && !empty($conf->categorie->enabled) && $user->rights->categorie->lire) { + if (isModEnabled("fournisseur") && !empty($conf->categorie->enabled) && $user->rights->categorie->lire) { require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; $moreforfilter .= '
'; $tmptitle = $langs->trans('Categories'); diff --git a/htdocs/societe/notify/card.php b/htdocs/societe/notify/card.php index 8729ed3b46e..45c07c83b76 100644 --- a/htdocs/societe/notify/card.php +++ b/htdocs/societe/notify/card.php @@ -183,7 +183,7 @@ if ($result > 0) { print '
'; print $langs->trans('SupplierCode').''; print showValueWithClipboardCPButton(dol_escape_htmltag($object->code_fournisseur)); diff --git a/htdocs/supplier_proposal/card.php b/htdocs/supplier_proposal/card.php index 7f09f66c065..b3ea48aef44 100644 --- a/htdocs/supplier_proposal/card.php +++ b/htdocs/supplier_proposal/card.php @@ -1968,7 +1968,7 @@ if ($action == 'create') { } // Create an order - if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) && $object->statut == SupplierProposal::STATUS_SIGNED) { + if (((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order")) && $object->statut == SupplierProposal::STATUS_SIGNED) { if ($usercancreateorder) { print ''; } diff --git a/htdocs/webservices/admin/index.php b/htdocs/webservices/admin/index.php index 2188a27c32a..97b8a4768a0 100644 --- a/htdocs/webservices/admin/index.php +++ b/htdocs/webservices/admin/index.php @@ -105,7 +105,7 @@ $webservices = array( 'productorservice' => '(isModEnabled("product") || isModEnabled("service"))', 'order' => '!empty($conf->commande->enabled)', 'invoice' => 'isModEnabled("facture")', - 'supplier_invoice' => '!empty($conf->fournisseur->enabled)', + 'supplier_invoice' => 'isModEnabled("fournisseur")', 'actioncomm' => '!empty($conf->agenda->enabled)', 'category' => '!empty($conf->categorie->enabled)', 'project' => '!empty($conf->project->enabled)', From 286faf479a032506ea6f9bc5a3b41497e5d3a49c Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Tue, 23 Aug 2022 20:10:55 +0200 Subject: [PATCH 771/826] Update categorie.php --- htdocs/categories/admin/categorie.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/categories/admin/categorie.php b/htdocs/categories/admin/categorie.php index 02e6892b571..f7022477d97 100644 --- a/htdocs/categories/admin/categorie.php +++ b/htdocs/categories/admin/categorie.php @@ -67,7 +67,7 @@ if (preg_match('/del_([a-z0-9_\-]+)/i', $action, $reg)) { * View */ -$help_url = 'EN:Module Categories|FR:Module Catégories|ES:Módulo Categorías'; +$help_url = 'EN:Module Categories|FR:Module Catégories|ES:Módulo Categorías|DE:Modul_Kategorien'; $linkback = ''.$langs->trans("BackToModuleList").''; llxHeader('', $langs->trans("Categories"), $help_url); From c0a7c7c179a1478c0d8cf31fe7ea57666e330086 Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Tue, 23 Aug 2022 20:11:46 +0200 Subject: [PATCH 772/826] Update categorie_extrafields.php --- htdocs/categories/admin/categorie_extrafields.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/categories/admin/categorie_extrafields.php b/htdocs/categories/admin/categorie_extrafields.php index 7dbf31835ca..2a1879135d6 100644 --- a/htdocs/categories/admin/categorie_extrafields.php +++ b/htdocs/categories/admin/categorie_extrafields.php @@ -63,7 +63,7 @@ require DOL_DOCUMENT_ROOT.'/core/actions_extrafields.inc.php'; $textobject = $langs->transnoentitiesnoconv("Categories"); -$help_url = 'EN:Module Categories|FR:Module Catégories|ES:Módulo Categorías'; +$help_url = 'EN:Module Categories|FR:Module Catégories|ES:Módulo Categorías|DE:Modul_Kategorien'; llxHeader('', $langs->trans("Categories"), $help_url); From e78f9a56be9dd5322e14425f382376052c4cafd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20France?= Date: Tue, 23 Aug 2022 20:16:28 +0200 Subject: [PATCH 773/826] use isModEnabled --- htdocs/adherents/class/adherent.class.php | 4 +- htdocs/asset/class/asset.class.php | 8 ++-- htdocs/comm/propal/card.php | 8 ++-- htdocs/commande/card.php | 14 +++---- htdocs/compta/facture/card-rec.php | 8 ++-- htdocs/compta/facture/card.php | 32 +++++++-------- htdocs/compta/facture/class/facture.class.php | 4 +- htdocs/compta/paiement/cheque/card.php | 12 +++--- .../compta/paiement/class/paiement.class.php | 8 ++-- htdocs/contrat/card.php | 8 ++-- htdocs/core/actions_addupdatedelete.inc.php | 12 +++--- htdocs/core/actions_lineupdown.inc.php | 8 ++-- htdocs/core/actions_massactions.inc.php | 14 +++---- htdocs/core/actions_setnotes.inc.php | 4 +- htdocs/core/class/html.formticket.class.php | 4 +- htdocs/delivery/card.php | 4 +- htdocs/don/card.php | 8 ++-- htdocs/expedition/card.php | 4 +- htdocs/expensereport/card.php | 40 +++++++++---------- htdocs/fichinter/card.php | 28 ++++++------- .../fourn/class/fournisseur.facture.class.php | 4 +- htdocs/fourn/class/paiementfourn.class.php | 2 +- htdocs/fourn/commande/card.php | 20 +++++----- htdocs/fourn/facture/card.php | 24 +++++------ htdocs/mrp/mo_card.php | 4 +- htdocs/mrp/mo_production.php | 4 +- .../class/partnershiputils.class.php | 4 +- htdocs/partnership/partnership_card.php | 8 ++-- .../class/propalmergepdfproduct.class.php | 2 +- htdocs/product/stock/movement_list.php | 4 +- htdocs/reception/card.php | 16 ++++---- htdocs/supplier_proposal/card.php | 12 +++--- htdocs/ticket/card.php | 4 +- 33 files changed, 170 insertions(+), 170 deletions(-) diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 1f93e87f1ab..5ecf5069915 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -1865,10 +1865,10 @@ class Adherent extends CommonObject $outputlangs = $langs; $newlang = ''; $lang_id = GETPOST('lang_id'); - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && !empty($lang_id)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && !empty($lang_id)) { $newlang = $lang_id; } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $customer->default_lang; } if (!empty($newlang)) { diff --git a/htdocs/asset/class/asset.class.php b/htdocs/asset/class/asset.class.php index d144d95819b..16306e73441 100644 --- a/htdocs/asset/class/asset.class.php +++ b/htdocs/asset/class/asset.class.php @@ -1171,10 +1171,10 @@ class Asset extends CommonObject global $hidedetails, $hidedesc, $hideref; $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $this->thirdparty->default_lang; } if (!empty($newlang)) { @@ -1234,10 +1234,10 @@ class Asset extends CommonObject global $hidedetails, $hidedesc, $hideref; $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $this->thirdparty->default_lang; } if (!empty($newlang)) { diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 690ed50536c..226e9ef6389 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -324,8 +324,8 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) $newlang = GETPOST('lang_id', 'aZ09'); - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang; + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) $newlang = GETPOST('lang_id', 'aZ09'); + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) $newlang = $object->thirdparty->default_lang; if (!empty($newlang)) { $outputlangs = new Translate("", $conf); $outputlangs->setDefaultLang($newlang); @@ -624,10 +624,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 07344dae69a..b6e859689ec 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -220,10 +220,10 @@ if (empty($reshook)) { // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -583,7 +583,7 @@ if (empty($reshook)) { // Define output language $outputlangs = $langs; $newlang = GETPOST('lang_id', 'alpha'); - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -1142,10 +1142,10 @@ if (empty($reshook)) { // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -1310,10 +1310,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { diff --git a/htdocs/compta/facture/card-rec.php b/htdocs/compta/facture/card-rec.php index 18a935cedb4..1ee81c2a2a0 100644 --- a/htdocs/compta/facture/card-rec.php +++ b/htdocs/compta/facture/card-rec.php @@ -650,8 +650,8 @@ if (empty($reshook)) { // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang = GETPOST('lang_id','aZ09'); - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang; + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang = GETPOST('lang_id','aZ09'); + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) $newlang = $object->thirdparty->default_lang; if (! empty($newlang)) { $outputlangs = new Translate("", $conf); $outputlangs->setDefaultLang($newlang); @@ -857,9 +857,9 @@ if (empty($reshook)) { // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09')) + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang = GETPOST('lang_id','aZ09'); - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) $newlang = $object->thirdparty->default_lang; if (! empty($newlang)) { $outputlangs = new Translate("", $conf); diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index d505f3dd718..6ad9c545dee 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -272,10 +272,10 @@ if (empty($reshook)) { // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id')) { $newlang = GETPOST('lang_id'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -520,10 +520,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -604,10 +604,10 @@ if (empty($reshook)) { if (empty($error) && empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -659,10 +659,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -749,10 +749,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -1956,10 +1956,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE) && count($object->lines)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -2305,10 +2305,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -2555,10 +2555,10 @@ if (empty($reshook)) { // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 91b5df73a00..0d2840adb97 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -598,10 +598,10 @@ class Facture extends CommonInvoice $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && isset($this->thirdparty->default_lang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && isset($this->thirdparty->default_lang)) { $newlang = $this->thirdparty->default_lang; // for proposal, order, invoice, ... } - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && isset($this->default_lang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && isset($this->default_lang)) { $newlang = $this->default_lang; // for thirdparty } if (!empty($newlang)) { diff --git a/htdocs/compta/paiement/cheque/card.php b/htdocs/compta/paiement/cheque/card.php index f41ecd820ad..5409d3c381e 100644 --- a/htdocs/compta/paiement/cheque/card.php +++ b/htdocs/compta/paiement/cheque/card.php @@ -138,10 +138,10 @@ if ($action == 'create' && GETPOST("accountid", "int") > 0 && $user->rights->ban // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - //if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang=$object->client->default_lang; + //if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) $newlang=$object->client->default_lang; if (!empty($newlang)) { $outputlangs = new Translate("", $conf); $outputlangs->setDefaultLang($newlang); @@ -189,10 +189,10 @@ if ($action == 'confirm_validate' && $confirm == 'yes' && $user->rights->banque- // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - //if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang=$object->client->default_lang; + //if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) $newlang=$object->client->default_lang; if (!empty($newlang)) { $outputlangs = new Translate("", $conf); $outputlangs->setDefaultLang($newlang); @@ -231,10 +231,10 @@ if ($action == 'builddoc' && $user->rights->banque->cheque) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - //if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang=$object->client->default_lang; + //if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) $newlang=$object->client->default_lang; if (!empty($newlang)) { $outputlangs = new Translate("", $conf); $outputlangs->setDefaultLang($newlang); diff --git a/htdocs/compta/paiement/class/paiement.class.php b/htdocs/compta/paiement/class/paiement.class.php index 6f83f9ebc0b..6186083c211 100644 --- a/htdocs/compta/paiement/class/paiement.class.php +++ b/htdocs/compta/paiement/class/paiement.class.php @@ -8,7 +8,7 @@ * Copyright (C) 2015 Juanjo Menent * Copyright (C) 2018 Ferran Marcet * Copyright (C) 2018 Thibault FOUCART - * Copyright (C) 2018 Frédéric France + * Copyright (C) 2018-2022 Frédéric France * Copyright (C) 2020 Andreu Bisquerra Gaya * Copyright (C) 2021 OpenDsi * @@ -455,7 +455,7 @@ class Paiement extends CommonObject $newlang = ''; $outputlangs = $langs; - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $invoice->fetch_thirdparty(); $newlang = $invoice->thirdparty->default_lang; } @@ -464,8 +464,8 @@ class Paiement extends CommonObject $outputlangs->setDefaultLang($newlang); } - $hidedetails = ! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS) ? 1 : 0; - $hidedesc = ! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DESC) ? 1 : 0; + $hidedetails = !empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS) ? 1 : 0; + $hidedesc = !empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DESC) ? 1 : 0; $hideref = !empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF) ? 1 : 0; $ret = $invoice->fetch($facid); // Reload to get new records diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php index 8c2dbad409d..9b25e710d85 100644 --- a/htdocs/contrat/card.php +++ b/htdocs/contrat/card.php @@ -577,10 +577,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE) && !empty($conf->global->CONTRACT_ADDON_PDF)) { // No generation if default type not defined $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -754,10 +754,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { diff --git a/htdocs/core/actions_addupdatedelete.inc.php b/htdocs/core/actions_addupdatedelete.inc.php index 39dba81976f..c7dffe08691 100644 --- a/htdocs/core/actions_addupdatedelete.inc.php +++ b/htdocs/core/actions_addupdatedelete.inc.php @@ -366,10 +366,10 @@ if ($action == 'confirm_deleteline' && $confirm == 'yes' && !empty($permissionto // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && is_object($object->thirdparty)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && is_object($object->thirdparty)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -442,10 +442,10 @@ if ($action == 'confirm_close' && $confirm == 'yes' && $permissiontoadd) { if (method_exists($object, 'generateDocument')) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -486,10 +486,10 @@ if ($action == 'confirm_reopen' && $confirm == 'yes' && $permissiontoadd) { if (method_exists($object, 'generateDocument')) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { diff --git a/htdocs/core/actions_lineupdown.inc.php b/htdocs/core/actions_lineupdown.inc.php index 5aee952292b..d41f1f1932c 100644 --- a/htdocs/core/actions_lineupdown.inc.php +++ b/htdocs/core/actions_lineupdown.inc.php @@ -34,10 +34,10 @@ if ($action == 'up' && $permissiontoedit) { // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -59,10 +59,10 @@ if ($action == 'down' && $permissiontoedit) { // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index a66c9b895b7..3f74ba7fdb2 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -763,10 +763,10 @@ if (!$error && $massaction == "builddoc" && $permissiontoread && !GETPOST('butto // Define output language (Here it is not used because we do only merging existing PDF) $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - //elseif ($conf->global->MAIN_MULTILANGS && empty($newlang) && is_object($objecttmp->thirdparty)) { // On massaction, we can have several values for $objecttmp->thirdparty + //elseif (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && is_object($objecttmp->thirdparty)) { // On massaction, we can have several values for $objecttmp->thirdparty // $newlang = $objecttmp->thirdparty->default_lang; //} if (!empty($newlang)) { @@ -965,10 +965,10 @@ if (!$error && $massaction == 'validate' && $permissiontoadd) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $objecttmp->thirdparty->default_lang; } if (!empty($newlang)) { @@ -1116,13 +1116,13 @@ if (!$error && $massaction == 'generate_doc' && $permissiontoread) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && isset($objecttmp->thirdparty->default_lang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && isset($objecttmp->thirdparty->default_lang)) { $newlang = $objecttmp->thirdparty->default_lang; // for proposal, order, invoice, ... } - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && isset($objecttmp->default_lang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && isset($objecttmp->default_lang)) { $newlang = $objecttmp->default_lang; // for thirdparty } if (!empty($newlang)) { diff --git a/htdocs/core/actions_setnotes.inc.php b/htdocs/core/actions_setnotes.inc.php index 91e7f4a8aca..7595daf1093 100644 --- a/htdocs/core/actions_setnotes.inc.php +++ b/htdocs/core/actions_setnotes.inc.php @@ -45,10 +45,10 @@ if ($action == 'setnote_public' && !empty($permissionnote) && !GETPOST('cancel', if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { diff --git a/htdocs/core/class/html.formticket.class.php b/htdocs/core/class/html.formticket.class.php index 68cb3d1af84..83071830ae7 100644 --- a/htdocs/core/class/html.formticket.class.php +++ b/htdocs/core/class/html.formticket.class.php @@ -1259,7 +1259,7 @@ class FormTicket // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $this->param['langsmodels']; } if (!empty($newlang)) { @@ -1306,7 +1306,7 @@ class FormTicket // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $this->param['langsmodels']; } if (!empty($newlang)) { diff --git a/htdocs/delivery/card.php b/htdocs/delivery/card.php index ac2aaa9b4e9..0b216df80a1 100644 --- a/htdocs/delivery/card.php +++ b/htdocs/delivery/card.php @@ -142,10 +142,10 @@ if ($action == 'add') { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { diff --git a/htdocs/don/card.php b/htdocs/don/card.php index 8f7ea3be1df..a622167819e 100644 --- a/htdocs/don/card.php +++ b/htdocs/don/card.php @@ -119,10 +119,10 @@ if (empty($reshook)) { if (method_exists($object, 'generateDocument')) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -351,8 +351,8 @@ if (empty($reshook)) { // Define output language $outputlangs = $langs; $newlang=''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && ! empty($_REQUEST['lang_id'])) $newlang=$_REQUEST['lang_id']; - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang=$object->thirdparty->default_lang; + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && ! empty($_REQUEST['lang_id'])) $newlang=$_REQUEST['lang_id']; + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) $newlang=$object->thirdparty->default_lang; if (! empty($newlang)) { $outputlangs = new Translate("",$conf); diff --git a/htdocs/expedition/card.php b/htdocs/expedition/card.php index 62e8b4337d3..3a0a9869571 100644 --- a/htdocs/expedition/card.php +++ b/htdocs/expedition/card.php @@ -763,10 +763,10 @@ if (empty($reshook)) { // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php index 650457cbcc7..4110ba98e1b 100644 --- a/htdocs/expensereport/card.php +++ b/htdocs/expensereport/card.php @@ -383,10 +383,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -493,10 +493,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -603,10 +603,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -717,10 +717,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -831,10 +831,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -943,10 +943,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -982,10 +982,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -1011,10 +1011,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -1229,10 +1229,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -1321,10 +1321,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { diff --git a/htdocs/fichinter/card.php b/htdocs/fichinter/card.php index d3adde8c21a..e2d03790f78 100644 --- a/htdocs/fichinter/card.php +++ b/htdocs/fichinter/card.php @@ -173,10 +173,10 @@ if (empty($reshook)) { // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -198,10 +198,10 @@ if (empty($reshook)) { // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -516,10 +516,10 @@ if (empty($reshook)) { // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -612,10 +612,10 @@ if (empty($reshook)) { // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -645,10 +645,10 @@ if (empty($reshook)) { // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -665,10 +665,10 @@ if (empty($reshook)) { // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -687,10 +687,10 @@ if (empty($reshook)) { // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { diff --git a/htdocs/fourn/class/fournisseur.facture.class.php b/htdocs/fourn/class/fournisseur.facture.class.php index 2135c66dfee..830430f3730 100644 --- a/htdocs/fourn/class/fournisseur.facture.class.php +++ b/htdocs/fourn/class/fournisseur.facture.class.php @@ -504,10 +504,10 @@ class FactureFournisseur extends CommonInvoice $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && isset($this->thirdparty->default_lang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && isset($this->thirdparty->default_lang)) { $newlang = $this->thirdparty->default_lang; // for proposal, order, invoice, ... } - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && isset($this->default_lang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && isset($this->default_lang)) { $newlang = $this->default_lang; // for thirdparty } if (! empty($newlang)) { diff --git a/htdocs/fourn/class/paiementfourn.class.php b/htdocs/fourn/class/paiementfourn.class.php index 8fc181e18e0..386c34483de 100644 --- a/htdocs/fourn/class/paiementfourn.class.php +++ b/htdocs/fourn/class/paiementfourn.class.php @@ -349,7 +349,7 @@ class PaiementFourn extends Paiement if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $newlang = ''; $outputlangs = $langs; - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $invoice->thirdparty->default_lang; } if (!empty($newlang)) { diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index c939c3433aa..31312c17d5b 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -846,10 +846,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -884,10 +884,10 @@ if (empty($reshook)) { // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -926,10 +926,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -989,10 +989,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -1050,10 +1050,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index dbb20c72d77..ddf54ba0727 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -229,10 +229,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -273,9 +273,9 @@ if (empty($reshook)) { // Define output language /*$outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09')) + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang = GETPOST('lang_id','aZ09'); - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) $newlang = $object->thirdparty->default_lang; if (! empty($newlang)) { $outputlangs = new Translate("", $conf); @@ -342,10 +342,10 @@ if (empty($reshook)) { // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -501,10 +501,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -1648,10 +1648,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -1748,10 +1748,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { diff --git a/htdocs/mrp/mo_card.php b/htdocs/mrp/mo_card.php index 2c333ff616e..032f9a7961c 100644 --- a/htdocs/mrp/mo_card.php +++ b/htdocs/mrp/mo_card.php @@ -202,10 +202,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { diff --git a/htdocs/mrp/mo_production.php b/htdocs/mrp/mo_production.php index d6fc14b33ae..0f734df6ae9 100644 --- a/htdocs/mrp/mo_production.php +++ b/htdocs/mrp/mo_production.php @@ -396,10 +396,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { diff --git a/htdocs/partnership/class/partnershiputils.class.php b/htdocs/partnership/class/partnershiputils.class.php index 9ad2e5b7ca2..874059431e1 100644 --- a/htdocs/partnership/class/partnershiputils.class.php +++ b/htdocs/partnership/class/partnershiputils.class.php @@ -157,7 +157,7 @@ class PartnershipUtils // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) $newlang = GETPOST('lang_id', 'aZ09'); + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) $newlang = GETPOST('lang_id', 'aZ09'); if (!empty($newlang)) { $outputlangs = new Translate("", $conf); $outputlangs->setDefaultLang($newlang); @@ -323,7 +323,7 @@ class PartnershipUtils // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) $newlang = GETPOST('lang_id', 'aZ09'); + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) $newlang = GETPOST('lang_id', 'aZ09'); if (!empty($newlang)) { $outputlangs = new Translate("", $conf); $outputlangs->setDefaultLang($newlang); diff --git a/htdocs/partnership/partnership_card.php b/htdocs/partnership/partnership_card.php index 25f8b286fb5..fb826efcd91 100644 --- a/htdocs/partnership/partnership_card.php +++ b/htdocs/partnership/partnership_card.php @@ -129,10 +129,10 @@ if (empty($reshook)) { if (method_exists($object, 'generateDocument')) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -161,10 +161,10 @@ if (empty($reshook)) { if (method_exists($object, 'generateDocument')) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { diff --git a/htdocs/product/class/propalmergepdfproduct.class.php b/htdocs/product/class/propalmergepdfproduct.class.php index 00c492f91de..e69c75c7336 100644 --- a/htdocs/product/class/propalmergepdfproduct.class.php +++ b/htdocs/product/class/propalmergepdfproduct.class.php @@ -403,7 +403,7 @@ class Propalmergepdfproduct extends CommonObject $sql = "DELETE FROM ".$this->db->prefix()."propal_merge_pdf_product"; $sql .= " WHERE fk_product = ".((int) $product_id); - if ($conf->global->MAIN_MULTILANGS && !empty($lang_id)) { + if (!empty($conf->global->MAIN_MULTILANGS) && !empty($lang_id)) { $sql .= " AND lang = '".$this->db->escape($lang_id)."'"; } diff --git a/htdocs/product/stock/movement_list.php b/htdocs/product/stock/movement_list.php index ad7be8d674b..9f097e1c4e3 100644 --- a/htdocs/product/stock/movement_list.php +++ b/htdocs/product/stock/movement_list.php @@ -268,10 +268,10 @@ if (empty($reshook)) { // Define output language (Here it is not used because we do only merging existing PDF) $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - //elseif ($conf->global->MAIN_MULTILANGS && empty($newlang) && is_object($objecttmp->thirdparty)) { // On massaction, we can have several values for $objecttmp->thirdparty + //elseif (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && is_object($objecttmp->thirdparty)) { // On massaction, we can have several values for $objecttmp->thirdparty // $newlang = $objecttmp->thirdparty->default_lang; //} if (!empty($newlang)) { diff --git a/htdocs/reception/card.php b/htdocs/reception/card.php index 279dad1dfac..e548beca63c 100644 --- a/htdocs/reception/card.php +++ b/htdocs/reception/card.php @@ -198,10 +198,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -436,10 +436,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -531,10 +531,10 @@ if (empty($reshook)) { // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $reception->thirdparty->default_lang; } if (!empty($newlang)) { @@ -666,10 +666,10 @@ if (empty($reshook)) { // Define output language $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { diff --git a/htdocs/supplier_proposal/card.php b/htdocs/supplier_proposal/card.php index b3ea48aef44..e4c2efd2c72 100644 --- a/htdocs/supplier_proposal/card.php +++ b/htdocs/supplier_proposal/card.php @@ -221,10 +221,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -448,10 +448,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { @@ -841,10 +841,10 @@ if (empty($reshook)) { if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { diff --git a/htdocs/ticket/card.php b/htdocs/ticket/card.php index d33a37343bd..8b76f5968cb 100755 --- a/htdocs/ticket/card.php +++ b/htdocs/ticket/card.php @@ -1473,9 +1473,9 @@ if ($action == 'create' || $action == 'presend') { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); - } elseif ($conf->global->MAIN_MULTILANGS && empty($newlang) && is_object($object->thirdparty)) { + } elseif (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && is_object($object->thirdparty)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { From e94d7f10a31f9a50e456896b6bf795874561628b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20France?= Date: Tue, 23 Aug 2022 20:22:44 +0200 Subject: [PATCH 774/826] use isModEnabled --- htdocs/adherents/subscription/card.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/adherents/subscription/card.php b/htdocs/adherents/subscription/card.php index cd1c208e62c..439541dff05 100644 --- a/htdocs/adherents/subscription/card.php +++ b/htdocs/adherents/subscription/card.php @@ -229,7 +229,7 @@ if ($user->rights->adherent->cotisation->creer && $action == 'edit') { print '
'.$langs->trans("BankTransactionLine").''; if ($object->fk_bank) { $bankline = new AccountLine($db); @@ -325,7 +325,7 @@ if ($rowid && $action != 'edit') { print '
'.$langs->trans("Label").''.$object->note.'
'.$langs->trans("BankTransactionLine").''; if ($object->fk_bank) { $bankline = new AccountLine($db); From 9e013bf44f5b188c84a70b21857d42e38567fbb2 Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Tue, 23 Aug 2022 20:52:56 +0200 Subject: [PATCH 775/826] Update traduction.php --- htdocs/categories/traduction.php | 33 +++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/htdocs/categories/traduction.php b/htdocs/categories/traduction.php index 512f25a67e2..00ff32c6206 100644 --- a/htdocs/categories/traduction.php +++ b/htdocs/categories/traduction.php @@ -20,9 +20,9 @@ */ /** - * \file htdocs/product/traduction.php - * \ingroup product - * \brief Page of translation of products + * \file htdocs/categories/traduction.php + * \ingroup categories + * \brief Page of translation of categories */ require '../main.inc.php'; @@ -35,8 +35,8 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; // Load translation files required by the page $langs->loadLangs(array('categories', 'languages')); -$id = GETPOST('id', 'int'); -$label = GETPOST('label', 'alpha'); +$id = GETPOST('id', 'int'); +$label = GETPOST('label', 'alpha'); $action = GETPOST('action', 'aZ09'); $cancel = GETPOST('cancel', 'alpha'); @@ -56,21 +56,23 @@ if ($result <= 0) { $type = $object->type; if (is_numeric($type)) { - $type = Categorie::$MAP_ID_TO_CODE[$type]; // For backward compatibility + $type = Categorie::$MAP_ID_TO_CODE[$type]; // For backward compatibility } + /* * Actions */ + $error = 0; -// retour a l'affichage des traduction si annulation +// return to translation view if cancelled if ($cancel == $langs->trans("Cancel")) { $action = ''; } -// Validation de l'ajout +// validation of addition if ($action == 'vadd' && $cancel != $langs->trans("Cancel") && ($user->rights->categorie->creer)) { @@ -94,7 +96,7 @@ $cancel != $langs->trans("Cancel") && } if (!$error) { - // update de l'objet + // update the object if ($forcelangprod == $current_lang) { $object->label = $libelle; $object->description = dol_htmlcleanlastbr($desc); @@ -103,7 +105,7 @@ $cancel != $langs->trans("Cancel") && $object->multilangs[$forcelangprod]["description"] = dol_htmlcleanlastbr($desc); } - // sauvegarde en base + // save in base / sauvegarde en base $res = $object->setMultiLangs($user); if ($res < 0) { $error++; @@ -119,14 +121,14 @@ $cancel != $langs->trans("Cancel") && } } -// Validation de l'edition +// validation of the edition if ($action == 'vedit' && $cancel != $langs->trans("Cancel") && ($user->rights->categorie->creer)) { $object->fetch($id); $current_lang = $langs->getDefaultLang(); - foreach ($object->multilangs as $key => $value) { // enregistrement des nouvelles valeurs dans l'objet + foreach ($object->multilangs as $key => $value) { // recording of new values in the object $libelle = GETPOST('libelle-'.$key, 'alpha'); $desc = GETPOST('desc-'.$key); @@ -164,7 +166,7 @@ $cancel != $langs->trans("Cancel") && * View */ -$form = new Form($db); +$form = new Form($db); $formadmin = new FormAdmin($db); $formother = new FormOther($db); @@ -223,10 +225,10 @@ print dol_get_fiche_end(); - /* * Action bar */ + print "\n
\n"; if ($action == '') { @@ -243,7 +245,7 @@ print "\n
\n"; if ($action == 'edit') { - //WYSIWYG Editor + // WYSIWYG Editor require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; print ''; @@ -260,6 +262,7 @@ if ($action == 'edit') { // Label $libelle = (GETPOST('libelle-'.$key, 'alpha') ? GETPOST('libelle-'.$key, 'alpha') : $object->multilangs[$key]['label']); print '
'.$langs->trans('Label').'
'.$langs->trans('Description').''; From bb9ebaf8fe5639fb080900adde249012c757bc69 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Tue, 23 Aug 2022 19:18:42 +0000 Subject: [PATCH 776/826] Fixing style errors. --- htdocs/categories/traduction.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/categories/traduction.php b/htdocs/categories/traduction.php index 00ff32c6206..69a27c5cff5 100644 --- a/htdocs/categories/traduction.php +++ b/htdocs/categories/traduction.php @@ -262,7 +262,7 @@ if ($action == 'edit') { // Label $libelle = (GETPOST('libelle-'.$key, 'alpha') ? GETPOST('libelle-'.$key, 'alpha') : $object->multilangs[$key]['label']); print '
'.$langs->trans('Label').'
'.$langs->trans('Description').''; From 68bef8ebcf02878088e4cccc6015ebe5a0cb1afe Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 23 Aug 2022 22:34:44 +0200 Subject: [PATCH 777/826] Merge branch 'imap-by-oauth2' of github.com:fboitel/dolibarr into fboitel-imap-by-oauth2 # Conflicts: # htdocs/install/mysql/migration/16.0.0-17.0.0.sql --- dev/setup/codesniffer/ruleset.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/setup/codesniffer/ruleset.xml b/dev/setup/codesniffer/ruleset.xml index e78438d8791..752a9271e59 100644 --- a/dev/setup/codesniffer/ruleset.xml +++ b/dev/setup/codesniffer/ruleset.xml @@ -135,7 +135,7 @@ - + From 5071c3d626bd912b2391c6abed43f55db1eafb96 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 23 Aug 2022 22:59:03 +0200 Subject: [PATCH 778/826] Clean option MAIN_IMAP_USE_PHPIMAP --- htdocs/emailcollector/class/emailcollector.class.php | 6 +++--- htdocs/langs/en_US/admin.lang | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index 2e0d9a14738..86d16f2cf61 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -129,10 +129,10 @@ class EmailCollector extends CommonObject 'host' => array('type'=>'varchar(255)', 'label'=>'EMailHost', 'visible'=>1, 'enabled'=>1, 'position'=>90, 'notnull'=>1, 'searchall'=>1, 'comment'=>"IMAP server", 'help'=>'Example: imap.gmail.com', 'csslist'=>'tdoverflow125'), 'port' => array('type'=>'varchar(10)', 'label'=>'EMailHostPort', 'visible'=>1, 'enabled'=>1, 'position'=>91, 'notnull'=>1, 'searchall'=>0, 'comment'=>"IMAP server port", 'help'=>'Example: 993', 'csslist'=>'tdoverflow125', 'default'=>'993'), 'hostcharset' => array('type'=>'varchar(16)', 'label'=>'HostCharset', 'visible'=>-1, 'enabled'=>1, 'position'=>92, 'notnull'=>0, 'searchall'=>0, 'comment'=>"IMAP server charset", 'help'=>'Example: "UTF-8" (May be "US-ASCII" with some Office365)', 'default'=>'UTF-8'), - 'acces_type' => array('type'=>'integer', 'label'=>'accessType', 'visible'=>-1, 'enabled'=>1, 'position'=>101, 'notnull'=>0, 'index'=>1, 'comment'=>"IMAP login type", 'arrayofkeyval'=>array('0'=>'loginPassword', '1'=>'oauthToken'), 'default'=>'0', 'help'=>'OnlyOneFieldBelowToBeFilled'), + 'acces_type' => array('type'=>'integer', 'label'=>'accessType', 'visible'=>-1, 'enabled'=>"getDolGlobalInt('MAIN_IMAP_USE_PHPIMAP')", 'position'=>101, 'notnull'=>1, 'index'=>1, 'comment'=>"IMAP login type", 'arrayofkeyval'=>array('0'=>'loginPassword', '1'=>'oauthToken'), 'default'=>'0', 'help'=>''), 'login' => array('type'=>'varchar(128)', 'label'=>'Login', 'visible'=>-1, 'enabled'=>1, 'position'=>102, 'notnull'=>-1, 'index'=>1, 'comment'=>"IMAP login", 'help'=>'Example: myaccount@gmail.com'), - 'oauth_service' => array('type'=>'varchar(128)', 'label'=>'oauthService', 'visible'=>-1, 'enabled'=>1, 'position'=>103, 'notnull'=>0, 'index'=>1, 'comment'=>"IMAP login oauthService", 'arrayofkeyval'=>array(), 'help'=>'TokenMustHaveBeenCreated'), - 'password' => array('type'=>'password', 'label'=>'Password', 'visible'=>-1, 'enabled'=>1, 'position'=>103, 'notnull'=>-1, 'comment'=>"IMAP password", 'help'=>'WithGMailYouCanCreateADedicatedPassword'), + 'password' => array('type'=>'password', 'label'=>'Password', 'visible'=>-1, 'enabled'=>"1", 'position'=>103, 'notnull'=>-1, 'comment'=>"IMAP password", 'help'=>'WithGMailYouCanCreateADedicatedPassword'), + 'oauth_service' => array('type'=>'varchar(128)', 'label'=>'oauthService', 'visible'=>-1, 'enabled'=>"getDolGlobalInt('MAIN_IMAP_USE_PHPIMAP')", 'position'=>104, 'notnull'=>0, 'index'=>1, 'comment'=>"IMAP login oauthService", 'arrayofkeyval'=>array(), 'help'=>'TokenMustHaveBeenCreated'), 'source_directory' => array('type'=>'varchar(255)', 'label'=>'MailboxSourceDirectory', 'visible'=>-1, 'enabled'=>1, 'position'=>104, 'notnull'=>1, 'default' => 'Inbox', 'help'=>'Example: INBOX'), //'filter' => array('type'=>'text', 'label'=>'Filter', 'visible'=>1, 'enabled'=>1, 'position'=>105), //'actiontodo' => array('type'=>'varchar(255)', 'label'=>'ActionToDo', 'visible'=>1, 'enabled'=>1, 'position'=>106), diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 0a0083e7132..c68a0ada7d6 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -2071,8 +2071,7 @@ loginPassword=Login/Password oauthToken=Oauth2 token accessType=Acces type oauthService=Oauth service -OnlyOneFieldBelowToBeFilled=Only one field below is to be filled in according to your choice here -TokenMustHaveBeenCreated=An oauth2 token must have been created upstream with the correct permissions +TokenMustHaveBeenCreated=Module OAuth2 must be enabled and an oauth2 token must have been created with the correct permissions (for example scope "gmail_full" with OAuth for Gmail). MailboxSourceDirectory=Mailbox source directory MailboxTargetDirectory=Mailbox target directory EmailcollectorOperations=Operations to do by collector From 056fa0aba9ba8955051dda3293245ad53b4acfbf Mon Sep 17 00:00:00 2001 From: bagtaib Date: Wed, 24 Aug 2022 00:20:11 +0100 Subject: [PATCH 779/826] added mods suggested --- .../partnership/class/partnership.class.php | 65 +--- htdocs/public/partnership/new.php | 365 +++++++++--------- 2 files changed, 191 insertions(+), 239 deletions(-) diff --git a/htdocs/partnership/class/partnership.class.php b/htdocs/partnership/class/partnership.class.php index 05d37ac9ee1..38d8c333749 100644 --- a/htdocs/partnership/class/partnership.class.php +++ b/htdocs/partnership/class/partnership.class.php @@ -248,70 +248,7 @@ class Partnership extends CommonObject } $this->status = 0; - - global $conf, $langs; - - $error = 0; - - $now = dol_now(); - - // Clean parameters - $this->import_key = trim($this->import_key); - - if (!$this->date_creation) { - $this->date_creation = $now; - } - - - $this->db->begin(); - - // Insert partnership - $sql = "INSERT INTO ".MAIN_DB_PREFIX."partnership"; - $sql .= " (ref, date_creation,fk_user_creat,fk_user_modif,fk_type,entity,import_key)"; - $sql .= " VALUES ("; - $sql .= " '(PROV)'"; - $sql .= ", '".$this->db->idate($this->datec)."'"; - $sql .= ", ".($user->id > 0 ? $user->id : "null"); // Can be null because partnership can be created by a guest or a script - $sql .= ", null "; - $sql .= ", ".((int) $this->fk_type); - $sql .= ", ".$conf->entity; - $sql .= ", ".(!empty($this->import_key) ? "'".$this->db->escape($this->import_key)."'" : "null"); - $sql .= ")"; - - dol_syslog(get_class($this)."::create", LOG_DEBUG); - $result = $this->db->query($sql); - if ($result) { - $id = $this->db->last_insert_id(MAIN_DB_PREFIX."partnership"); - if ($id > 0) { - $this->id = $id; - $this->ref = (string) $id; - - // Update minor fields - $result = $this->update($user, 1, 1, 0, 0, 'add'); // nosync is 1 to avoid update data of user - if ($result < 0) { - $this->db->rollback(); - return -1; - } - - if (count($this->errors)) { - dol_syslog(get_class($this)."::create ".implode(',', $this->errors), LOG_ERR); - $this->db->rollback(); - return -3; - } else { - $this->db->commit(); - return $this->id; - } - } else { - $this->error = 'Failed to get last insert id'; - dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR); - $this->db->rollback(); - return -2; - } - } else { - $this->error = $this->db->error(); - $this->db->rollback(); - return -1; - } + return $this->createCommon($user, $notrigger); } /** diff --git a/htdocs/public/partnership/new.php b/htdocs/public/partnership/new.php index b5ff6eecf57..aced814a9b3 100644 --- a/htdocs/public/partnership/new.php +++ b/htdocs/public/partnership/new.php @@ -67,7 +67,7 @@ $backtopage = GETPOST('backtopage', 'alpha'); $action = GETPOST('action', 'aZ09'); // Load translation files -$langs->loadLangs(array("main", "members", "companies", "install", "other")); // maybe change this one +$langs->loadLangs(array("main", "members", "companies", "install", "other")); // Security check if (empty($conf->partnership->enabled)) { @@ -208,6 +208,7 @@ if (empty($reshook) && $action == 'add') { if (!$error) { $partnership = new Partnership($db); + $partnershipt = new PartnershipType($db); // We try to find the thirdparty or the member if (getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR', 'thirdparty') == 'thirdparty') { @@ -218,16 +219,20 @@ if (empty($reshook) && $action == 'add') { // need to change this part $partnership->status = 0; - $partnership->firstname = GETPOST('firstname'); - $partnership->lastname = GETPOST('lastname'); - $partnership->address = GETPOST('address'); - $partnership->zip = GETPOST('zipcode'); - $partnership->town = GETPOST('town'); - $partnership->email = GETPOST('email'); - $partnership->country_id = GETPOST('country_id', 'int'); - $partnership->state_id = GETPOST('state_id', 'int'); - //$partnership->typeid = $conf->global->PARTNERSHIP_NEWFORM_FORCETYPE ? $conf->global->PARTNERSHIP_NEWFORM_FORCETYPE : GETPOST('typeid', 'int'); $partnership->note_private = GETPOST('note_private'); + $partnership->date_creation = dol_now(); + $partnership->date_partnership_start = dol_now(); + $partnership->$partnershipt->fetch(0, 'default'); + $partnership->fk_user_creat=$user->id; + //$partnership->firstname = GETPOST('firstname'); + //$partnership->lastname = GETPOST('lastname'); + //$partnership->address = GETPOST('address'); + //$partnership->zip = GETPOST('zipcode'); + //$partnership->town = GETPOST('town'); + //$partnership->email = GETPOST('email'); + //$partnership->country_id = GETPOST('country_id', 'int'); + //$partnership->state_id = GETPOST('state_id', 'int'); + //$partnership->typeid = $conf->global->PARTNERSHIP_NEWFORM_FORCETYPE ? $conf->global->PARTNERSHIP_NEWFORM_FORCETYPE : GETPOST('typeid', 'int'); // Fill array 'array_options' with data from add form $extrafields->fetch_name_optionals_label($partnership->table_element); @@ -236,7 +241,7 @@ if (empty($reshook) && $action == 'add') { $error++; } // test if societe already exist - $sql = "SELECT nom FROM ".MAIN_DB_PREFIX."societe WHERE nom='".GETPOST('societe')."'"; + $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."societe WHERE nom='".$db->escape(GETPOST('societe'))."'"; $result = $db->query($sql); if ($result) { $num = $db->num_rows($result); @@ -244,196 +249,206 @@ if (empty($reshook) && $action == 'add') { if ($num = 0) { //create thirdparty $company = new Societe($db); + + $company->address = GETPOST('address'); + $company->zip = GETPOST('zipcode'); + $company->town = GETPOST('town'); + $company->email = GETPOST('email'); + $company->country_id = GETPOST('country_id', 'int'); + $company->state_id = GETPOST('state_id', 'int'); + $company->name_alias = dolGetFirstLastname(GETPOST('firstname'), GETPOST('lastname')); + $resultat=$company->create($user); if ($result < 0) { $error++; $errmsg .= join('
', $company->errors); } - $sql = "UPDATE ".MAIN_DB_PREFIX."societe"; - $sql .= " SET name = ".(GETPOST('societe')).", email = ".(GETPOST('email')); - $sql .= ", address = ".(($GETPOSTISSET('address') ? GETPOST('address') : "null")).", zip = ".(($GETPOSTISSET('zipcode') ? GETPOST('zipcode') : "null")); - $sql .= ", town = ".(($GETPOSTISSET('town') ? GETPOST('town') : "null")).", fk_pays = ".(($GETPOSTISSET('country_id') ? GETPOST('country_id') : "null")); - $sql .= ", fk_departement = ".(($GETPOSTISSET('state_id') ? GETPOST('state_id') : "null")).", note_private = ".(($GETPOSTISSET('note_private') ? GETPOST('note_private') : "null")); - $sql .= " WHERE rowid = ".((int) $company->id); - $resql = $db->query($sql); + $partnership->fk_soc = $company->id; + } elseif ($num > 1) { + $error++; + $errmsg = 'Message'; } else { - $don=$result->fetch(); - $partnership->fk_soc =$don['rowid']; + $company = $db->fetch_object($result); + $partnership->fk_soc = $company->rowid; } - $result = $partnership->create($user); - if ($result > 0) { - require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'; - $object = $partnership; + if (!$error) { + $result = $partnership->create($user); + if ($result > 0) { + /* + require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'; + $object = $partnership; - /* - $partnershipt = new PartnershipType($db); - $partnershipt->fetch($object->typeid); - if ($object->email) { - $subject = ''; - $msg = ''; + $partnershipt = new PartnershipType($db); + $partnershipt->fetch($object->typeid); - // Send subscription email - include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php'; - $formmail = new FormMail($db); - // Set output language - $outputlangs = new Translate('', $conf); - $outputlangs->setDefaultLang(empty($object->thirdparty->default_lang) ? $mysoc->default_lang : $object->thirdparty->default_lang); - // Load traductions files required by page - $outputlangs->loadLangs(array("main", "members")); - // Get email content from template - $arraydefaultmessage = null; - $labeltouse = $conf->global->PARTNERSHIP_EMAIL_TEMPLATE_AUTOREGISTER; + if ($object->email) { + $subject = ''; + $msg = ''; - if (!empty($labeltouse)) { - $arraydefaultmessage = $formmail->getEMailTemplate($db, 'member', $user, $outputlangs, 0, 1, $labeltouse); + // Send subscription email + include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php'; + $formmail = new FormMail($db); + // Set output language + $outputlangs = new Translate('', $conf); + $outputlangs->setDefaultLang(empty($object->thirdparty->default_lang) ? $mysoc->default_lang : $object->thirdparty->default_lang); + // Load traductions files required by page + $outputlangs->loadLangs(array("main", "members")); + // Get email content from template + $arraydefaultmessage = null; + $labeltouse = $conf->global->PARTNERSHIP_EMAIL_TEMPLATE_AUTOREGISTER; + + if (!empty($labeltouse)) { + $arraydefaultmessage = $formmail->getEMailTemplate($db, 'member', $user, $outputlangs, 0, 1, $labeltouse); + } + + if (!empty($labeltouse) && is_object($arraydefaultmessage) && $arraydefaultmessage->id > 0) { + $subject = $arraydefaultmessage->topic; + $msg = $arraydefaultmessage->content; + } + + $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $object); + complete_substitutions_array($substitutionarray, $outputlangs, $object); + $subjecttosend = make_substitutions($subject, $substitutionarray, $outputlangs); + $texttosend = make_substitutions(dol_concatdesc($msg, $partnershipt->getMailOnValid()), $substitutionarray, $outputlangs); + + if ($subjecttosend && $texttosend) { + $moreinheader = 'X-Dolibarr-Info: send_an_email by public/members/new.php'."\r\n"; + + $result = $object->send_an_email($texttosend, $subjecttosend, array(), array(), array(), "", "", 0, -1, '', $moreinheader); + } } - if (!empty($labeltouse) && is_object($arraydefaultmessage) && $arraydefaultmessage->id > 0) { - $subject = $arraydefaultmessage->topic; - $msg = $arraydefaultmessage->content; - } - $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $object); - complete_substitutions_array($substitutionarray, $outputlangs, $object); - $subjecttosend = make_substitutions($subject, $substitutionarray, $outputlangs); - $texttosend = make_substitutions(dol_concatdesc($msg, $partnershipt->getMailOnValid()), $substitutionarray, $outputlangs); - - if ($subjecttosend && $texttosend) { - $moreinheader = 'X-Dolibarr-Info: send_an_email by public/members/new.php'."\r\n"; - - $result = $object->send_an_email($texttosend, $subjecttosend, array(), array(), array(), "", "", 0, -1, '', $moreinheader); - } - } - */ - - // Send email to the foundation to say a new member subscribed with autosubscribe form - /* - if (getDolGlobalString('MAIN_INFO_SOCIETE_MAIL') && !empty($conf->global->PARTNERSHIP_AUTOREGISTER_NOTIF_MAIL_SUBJECT) && - !empty($conf->global->PARTNERSHIP_AUTOREGISTER_NOTIF_MAIL)) { - // Define link to login card - $appli = constant('DOL_APPLICATION_TITLE'); - if (!empty($conf->global->MAIN_APPLICATION_TITLE)) { - $appli = $conf->global->MAIN_APPLICATION_TITLE; - if (preg_match('/\d\.\d/', $appli)) { - if (!preg_match('/'.preg_quote(DOL_VERSION).'/', $appli)) { - $appli .= " (".DOL_VERSION.")"; // If new title contains a version that is different than core + // Send email to the foundation to say a new member subscribed with autosubscribe form + /* + if (getDolGlobalString('MAIN_INFO_SOCIETE_MAIL') && !empty($conf->global->PARTNERSHIP_AUTOREGISTER_NOTIF_MAIL_SUBJECT) && + !empty($conf->global->PARTNERSHIP_AUTOREGISTER_NOTIF_MAIL)) { + // Define link to login card + $appli = constant('DOL_APPLICATION_TITLE'); + if (!empty($conf->global->MAIN_APPLICATION_TITLE)) { + $appli = $conf->global->MAIN_APPLICATION_TITLE; + if (preg_match('/\d\.\d/', $appli)) { + if (!preg_match('/'.preg_quote(DOL_VERSION).'/', $appli)) { + $appli .= " (".DOL_VERSION.")"; // If new title contains a version that is different than core + } + } else { + $appli .= " ".DOL_VERSION; } } else { $appli .= " ".DOL_VERSION; } + + $to = $partnership->makeSubstitution(getDolGlobalString('MAIN_INFO_SOCIETE_MAIL')); + $from = getDolGlobalString('PARTNERSHIP_MAIL_FROM'); + $mailfile = new CMailFile( + '['.$appli.'] '.getDolGlobalString('PARTNERSHIP_AUTOREGISTER_NOTIF_MAIL_SUBJECT', 'Partnership request'), + $to, + $from, + $partnership->makeSubstitution(getDolGlobalString('PARTNERSHIP_AUTOREGISTER_NOTIF_MAIL')), + array(), + array(), + array(), + "", + "", + 0, + -1 + ); + + if (!$mailfile->sendfile()) { + dol_syslog($langs->trans("ErrorFailedToSendMail", $from, $to), LOG_ERR); + } + }*/ + + + + + if (!empty($backtopage)) { + $urlback = $backtopage; + } elseif (!empty($conf->global->PARTNERSHIP_URL_REDIRECT_SUBSCRIPTION)) { + $urlback = $conf->global->PARTNERSHIP_URL_REDIRECT_SUBSCRIPTION; + // TODO Make replacement of __AMOUNT__, etc... } else { - $appli .= " ".DOL_VERSION; + $urlback = $_SERVER["PHP_SELF"]."?action=added&token=".newToken(); } - $to = $partnership->makeSubstitution(getDolGlobalString('MAIN_INFO_SOCIETE_MAIL')); - $from = getDolGlobalString('PARTNERSHIP_MAIL_FROM'); - $mailfile = new CMailFile( - '['.$appli.'] '.getDolGlobalString('PARTNERSHIP_AUTOREGISTER_NOTIF_MAIL_SUBJECT', 'Partnership request'), - $to, - $from, - $partnership->makeSubstitution(getDolGlobalString('PARTNERSHIP_AUTOREGISTER_NOTIF_MAIL')), - array(), - array(), - array(), - "", - "", - 0, - -1 - ); + /* + if (!empty($conf->global->PARTNERSHIP_NEWFORM_PAYONLINE) && $conf->global->PARTNERSHIP_NEWFORM_PAYONLINE != '-1') { + if ($conf->global->PARTNERSHIP_NEWFORM_PAYONLINE == 'all') { + $urlback = DOL_MAIN_URL_ROOT.'/public/payment/newpayment.php?from=partnershipnewform&source=membersubscription&ref='.urlencode($partnership->ref); + if (price2num(GETPOST('amount', 'alpha'))) { + $urlback .= '&amount='.price2num(GETPOST('amount', 'alpha')); + } + if (GETPOST('email')) { + $urlback .= '&email='.urlencode(GETPOST('email')); + } + if (!empty($conf->global->PAYMENT_SECURITY_TOKEN)) { + if (!empty($conf->global->PAYMENT_SECURITY_TOKEN_UNIQUE)) { + $urlback .= '&securekey='.urlencode(dol_hash($conf->global->PAYMENT_SECURITY_TOKEN.'membersubscription'.$partnership->ref, 2)); + } else { + $urlback .= '&securekey='.urlencode($conf->global->PAYMENT_SECURITY_TOKEN); + } + } + } elseif ($conf->global->PARTNERSHIP_NEWFORM_PAYONLINE == 'paybox') { + $urlback = DOL_MAIN_URL_ROOT.'/public/paybox/newpayment.php?from=partnershipnewform&source=membersubscription&ref='.urlencode($partnership->ref); + if (price2num(GETPOST('amount', 'alpha'))) { + $urlback .= '&amount='.price2num(GETPOST('amount', 'alpha')); + } + if (GETPOST('email')) { + $urlback .= '&email='.urlencode(GETPOST('email')); + } + if (!empty($conf->global->PAYMENT_SECURITY_TOKEN)) { + if (!empty($conf->global->PAYMENT_SECURITY_TOKEN_UNIQUE)) { + $urlback .= '&securekey='.urlencode(dol_hash($conf->global->PAYMENT_SECURITY_TOKEN.'membersubscription'.$partnership->ref, 2)); + } else { + $urlback .= '&securekey='.urlencode($conf->global->PAYMENT_SECURITY_TOKEN); + } + } + } elseif ($conf->global->PARTNERSHIP_NEWFORM_PAYONLINE == 'paypal') { + $urlback = DOL_MAIN_URL_ROOT.'/public/paypal/newpayment.php?from=partnershipnewform&source=membersubscription&ref='.urlencode($partnership->ref); + if (price2num(GETPOST('amount', 'alpha'))) { + $urlback .= '&amount='.price2num(GETPOST('amount', 'alpha')); + } + if (GETPOST('email')) { + $urlback .= '&email='.urlencode(GETPOST('email')); + } + if (!empty($conf->global->PAYMENT_SECURITY_TOKEN)) { + if (!empty($conf->global->PAYMENT_SECURITY_TOKEN_UNIQUE)) { + $urlback .= '&securekey='.urlencode(dol_hash($conf->global->PAYMENT_SECURITY_TOKEN.'membersubscription'.$partnership->ref, 2)); + } else { + $urlback .= '&securekey='.urlencode($conf->global->PAYMENT_SECURITY_TOKEN); + } + } + } elseif ($conf->global->PARTNERSHIP_NEWFORM_PAYONLINE == 'stripe') { + $urlback = DOL_MAIN_URL_ROOT.'/public/stripe/newpayment.php?from=partnershipnewform&source=membersubscription&ref='.$partnership->ref; + if (price2num(GETPOST('amount', 'alpha'))) { + $urlback .= '&amount='.price2num(GETPOST('amount', 'alpha')); + } + if (GETPOST('email')) { + $urlback .= '&email='.urlencode(GETPOST('email')); + } + if (!empty($conf->global->PAYMENT_SECURITY_TOKEN)) { + if (!empty($conf->global->PAYMENT_SECURITY_TOKEN_UNIQUE)) { + $urlback .= '&securekey='.urlencode(dol_hash($conf->global->PAYMENT_SECURITY_TOKEN.'membersubscription'.$partnership->ref, 2)); + } else { + $urlback .= '&securekey='.urlencode($conf->global->PAYMENT_SECURITY_TOKEN); + } + } + } else { + dol_print_error('', "Autosubscribe form is setup to ask an online payment for a not managed online payment"); + exit; + } + }*/ - if (!$mailfile->sendfile()) { - dol_syslog($langs->trans("ErrorFailedToSendMail", $from, $to), LOG_ERR); + if (!empty($entity)) { + $urlback .= '&entity='.$entity; } - }*/ - - - - - if (!empty($backtopage)) { - $urlback = $backtopage; - } elseif (!empty($conf->global->PARTNERSHIP_URL_REDIRECT_SUBSCRIPTION)) { - $urlback = $conf->global->PARTNERSHIP_URL_REDIRECT_SUBSCRIPTION; - // TODO Make replacement of __AMOUNT__, etc... + dol_syslog("partnership ".$partnership->ref." was created, we redirect to ".$urlback); } else { - $urlback = $_SERVER["PHP_SELF"]."?action=added&token=".newToken(); + $error++; + $errmsg .= join('
', $partnership->errors); } - - if (!empty($conf->global->PARTNERSHIP_NEWFORM_PAYONLINE) && $conf->global->PARTNERSHIP_NEWFORM_PAYONLINE != '-1') { - if ($conf->global->PARTNERSHIP_NEWFORM_PAYONLINE == 'all') { - $urlback = DOL_MAIN_URL_ROOT.'/public/payment/newpayment.php?from=partnershipnewform&source=membersubscription&ref='.urlencode($partnership->ref); - if (price2num(GETPOST('amount', 'alpha'))) { - $urlback .= '&amount='.price2num(GETPOST('amount', 'alpha')); - } - if (GETPOST('email')) { - $urlback .= '&email='.urlencode(GETPOST('email')); - } - if (!empty($conf->global->PAYMENT_SECURITY_TOKEN)) { - if (!empty($conf->global->PAYMENT_SECURITY_TOKEN_UNIQUE)) { - $urlback .= '&securekey='.urlencode(dol_hash($conf->global->PAYMENT_SECURITY_TOKEN.'membersubscription'.$partnership->ref, 2)); - } else { - $urlback .= '&securekey='.urlencode($conf->global->PAYMENT_SECURITY_TOKEN); - } - } - } elseif ($conf->global->PARTNERSHIP_NEWFORM_PAYONLINE == 'paybox') { - $urlback = DOL_MAIN_URL_ROOT.'/public/paybox/newpayment.php?from=partnershipnewform&source=membersubscription&ref='.urlencode($partnership->ref); - if (price2num(GETPOST('amount', 'alpha'))) { - $urlback .= '&amount='.price2num(GETPOST('amount', 'alpha')); - } - if (GETPOST('email')) { - $urlback .= '&email='.urlencode(GETPOST('email')); - } - if (!empty($conf->global->PAYMENT_SECURITY_TOKEN)) { - if (!empty($conf->global->PAYMENT_SECURITY_TOKEN_UNIQUE)) { - $urlback .= '&securekey='.urlencode(dol_hash($conf->global->PAYMENT_SECURITY_TOKEN.'membersubscription'.$partnership->ref, 2)); - } else { - $urlback .= '&securekey='.urlencode($conf->global->PAYMENT_SECURITY_TOKEN); - } - } - } elseif ($conf->global->PARTNERSHIP_NEWFORM_PAYONLINE == 'paypal') { - $urlback = DOL_MAIN_URL_ROOT.'/public/paypal/newpayment.php?from=partnershipnewform&source=membersubscription&ref='.urlencode($partnership->ref); - if (price2num(GETPOST('amount', 'alpha'))) { - $urlback .= '&amount='.price2num(GETPOST('amount', 'alpha')); - } - if (GETPOST('email')) { - $urlback .= '&email='.urlencode(GETPOST('email')); - } - if (!empty($conf->global->PAYMENT_SECURITY_TOKEN)) { - if (!empty($conf->global->PAYMENT_SECURITY_TOKEN_UNIQUE)) { - $urlback .= '&securekey='.urlencode(dol_hash($conf->global->PAYMENT_SECURITY_TOKEN.'membersubscription'.$partnership->ref, 2)); - } else { - $urlback .= '&securekey='.urlencode($conf->global->PAYMENT_SECURITY_TOKEN); - } - } - } elseif ($conf->global->PARTNERSHIP_NEWFORM_PAYONLINE == 'stripe') { - $urlback = DOL_MAIN_URL_ROOT.'/public/stripe/newpayment.php?from=partnershipnewform&source=membersubscription&ref='.$partnership->ref; - if (price2num(GETPOST('amount', 'alpha'))) { - $urlback .= '&amount='.price2num(GETPOST('amount', 'alpha')); - } - if (GETPOST('email')) { - $urlback .= '&email='.urlencode(GETPOST('email')); - } - if (!empty($conf->global->PAYMENT_SECURITY_TOKEN)) { - if (!empty($conf->global->PAYMENT_SECURITY_TOKEN_UNIQUE)) { - $urlback .= '&securekey='.urlencode(dol_hash($conf->global->PAYMENT_SECURITY_TOKEN.'membersubscription'.$partnership->ref, 2)); - } else { - $urlback .= '&securekey='.urlencode($conf->global->PAYMENT_SECURITY_TOKEN); - } - } - } else { - dol_print_error('', "Autosubscribe form is setup to ask an online payment for a not managed online payment"); - exit; - } - } - - if (!empty($entity)) { - $urlback .= '&entity='.$entity; - } - dol_syslog("partnership ".$partnership->ref." was created, we redirect to ".$urlback); - } else { - $error++; - $errmsg .= join('
', $partnership->errors); } } From f36303a951e5cc08316ccab20b37edfb27dcdeaf Mon Sep 17 00:00:00 2001 From: bagtaib Date: Wed, 24 Aug 2022 00:23:39 +0100 Subject: [PATCH 780/826] debug --- htdocs/public/partnership/new.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/public/partnership/new.php b/htdocs/public/partnership/new.php index aced814a9b3..f817a36aa1b 100644 --- a/htdocs/public/partnership/new.php +++ b/htdocs/public/partnership/new.php @@ -222,7 +222,7 @@ if (empty($reshook) && $action == 'add') { $partnership->note_private = GETPOST('note_private'); $partnership->date_creation = dol_now(); $partnership->date_partnership_start = dol_now(); - $partnership->$partnershipt->fetch(0, 'default'); + $partnership->fk_type = $partnershipt->fetch(0, 'default'); $partnership->fk_user_creat=$user->id; //$partnership->firstname = GETPOST('firstname'); //$partnership->lastname = GETPOST('lastname'); From fcbe9335237f345a2df43dd38c9c2da0c4aaaae1 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 24 Aug 2022 02:17:53 +0200 Subject: [PATCH 781/826] Can use the login/pass with PHP-IMAP --- .../class/emailcollector.class.php | 173 ++++++++++-------- 1 file changed, 97 insertions(+), 76 deletions(-) diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index 86d16f2cf61..5c885209a71 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -1022,75 +1022,92 @@ class EmailCollector extends CommonObject $this->fetchFilters(); $this->fetchActions(); - if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP) && $this->acces_type == 1) { - require_once DOL_DOCUMENT_ROOT.'/core/lib/oauth.lib.php'; // define $supportedoauth2array - $keyforsupportedoauth2array = $this->oauth_service; - if (preg_match('/^.*-/', $keyforsupportedoauth2array)) { - $keyforprovider = preg_replace('/^.*-/', '', $keyforsupportedoauth2array); - } else { - $keyforprovider = ''; - } - $keyforsupportedoauth2array = preg_replace('/-.*$/', '', $keyforsupportedoauth2array); - $keyforsupportedoauth2array = 'OAUTH_'.$keyforsupportedoauth2array.'_NAME'; - - $OAUTH_SERVICENAME = (empty($supportedoauth2array[$keyforsupportedoauth2array]['name']) ? 'Unknown' : $supportedoauth2array[$keyforsupportedoauth2array]['name'].($keyforprovider ? '-'.$keyforprovider : '')); - - require_once DOL_DOCUMENT_ROOT.'/includes/OAuth/bootstrap.php'; - $debugtext = "Host: ".$this->host."
Port: ".$this->port."
Login: ".$this->login."
Password: ".$this->password."
access type: ".$this->acces_type."
oauth service: ".$this->oauth_service."
Max email per collect: ".$this->maxemailpercollect; - - $storage = new DoliStorage($db, $conf); - - try { - $tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME); - $expire = true; - // Is token expired or will token expire in the next 30 seconds - // if (is_object($tokenobj)) { - // $expire = ($tokenobj->getEndOfLife() !== -9002 && $tokenobj->getEndOfLife() !== -9001 && time() > ($tokenobj->getEndOfLife() - 30)); - // } - // Token expired so we refresh it - if (is_object($tokenobj) && $expire) { - $credentials = new Credentials( - getDolGlobalString('OAUTH_'.$this->oauth_service.'_ID'), - getDolGlobalString('OAUTH_'.$this->oauth_service.'_SECRET'), - getDolGlobalString('OAUTH_'.$this->oauth_service.'_URLAUTHORIZE') - ); - $serviceFactory = new \OAuth\ServiceFactory(); - $oauthname = explode('-', $OAUTH_SERVICENAME); - // ex service is Google-Emails we need only the first part Google - $apiService = $serviceFactory->createService($oauthname[0], $credentials, $storage, array()); - // We have to save the token because Google give it only once - $refreshtoken = $tokenobj->getRefreshToken(); - $tokenobj = $apiService->refreshAccessToken($tokenobj); - $tokenobj->setRefreshToken($refreshtoken); - $storage->storeAccessToken($OAUTH_SERVICENAME, $tokenobj); - } - $tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME); - if (is_object($tokenobj)) { - $token = $tokenobj->getAccessToken(); + if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP)) { + if ($this->acces_type == 1) { + // Mode OAUth2 with PHP-IMAP + require_once DOL_DOCUMENT_ROOT.'/core/lib/oauth.lib.php'; // define $supportedoauth2array + $keyforsupportedoauth2array = $this->oauth_service; + if (preg_match('/^.*-/', $keyforsupportedoauth2array)) { + $keyforprovider = preg_replace('/^.*-/', '', $keyforsupportedoauth2array); } else { - $this->error = "Token not found"; + $keyforprovider = ''; + } + $keyforsupportedoauth2array = preg_replace('/-.*$/', '', $keyforsupportedoauth2array); + $keyforsupportedoauth2array = 'OAUTH_'.$keyforsupportedoauth2array.'_NAME'; + + $OAUTH_SERVICENAME = (empty($supportedoauth2array[$keyforsupportedoauth2array]['name']) ? 'Unknown' : $supportedoauth2array[$keyforsupportedoauth2array]['name'].($keyforprovider ? '-'.$keyforprovider : '')); + + require_once DOL_DOCUMENT_ROOT.'/includes/OAuth/bootstrap.php'; + //$debugtext = "Host: ".$this->host."
Port: ".$this->port."
Login: ".$this->login."
Password: ".$this->password."
access type: ".$this->acces_type."
oauth service: ".$this->oauth_service."
Max email per collect: ".$this->maxemailpercollect; + //dol_syslog($debugtext); + + $storage = new DoliStorage($db, $conf); + + try { + $tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME); + $expire = true; + // Is token expired or will token expire in the next 30 seconds + // if (is_object($tokenobj)) { + // $expire = ($tokenobj->getEndOfLife() !== -9002 && $tokenobj->getEndOfLife() !== -9001 && time() > ($tokenobj->getEndOfLife() - 30)); + // } + // Token expired so we refresh it + if (is_object($tokenobj) && $expire) { + $credentials = new Credentials( + getDolGlobalString('OAUTH_'.$this->oauth_service.'_ID'), + getDolGlobalString('OAUTH_'.$this->oauth_service.'_SECRET'), + getDolGlobalString('OAUTH_'.$this->oauth_service.'_URLAUTHORIZE') + ); + $serviceFactory = new \OAuth\ServiceFactory(); + $oauthname = explode('-', $OAUTH_SERVICENAME); + // ex service is Google-Emails we need only the first part Google + $apiService = $serviceFactory->createService($oauthname[0], $credentials, $storage, array()); + // We have to save the token because Google give it only once + $refreshtoken = $tokenobj->getRefreshToken(); + $tokenobj = $apiService->refreshAccessToken($tokenobj); + $tokenobj->setRefreshToken($refreshtoken); + $storage->storeAccessToken($OAUTH_SERVICENAME, $tokenobj); + } + $tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME); + if (is_object($tokenobj)) { + $token = $tokenobj->getAccessToken(); + } else { + $this->error = "Token not found"; + return -1; + } + } catch (Exception $e) { + // Return an error if token not found + $this->error = $e->getMessage(); + dol_syslog("CMailFile::sendfile: mail end error=".$this->error, LOG_ERR); return -1; } - } catch (Exception $e) { - // Return an error if token not found - $this->error = $e->getMessage(); - dol_syslog("CMailFile::sendfile: mail end error=".$this->error, LOG_ERR); - return -1; + + + $cm = new ClientManager(); + $client = $cm->make([ + 'host' => $this->host, + 'port' => $this->port, + 'encryption' => 'ssl', + 'validate_cert' => true, + 'protocol' => 'imap', + 'username' => $this->login, + 'password' => $token, + 'authentication' => "oauth", + ]); + } else { + // Mode login/pass with PHP-IMAP + $cm = new ClientManager(); + $client = $cm->make([ + 'host' => $this->host, + 'port' => $this->port, + 'encryption' => 'ssl', + 'validate_cert' => true, + 'protocol' => 'imap', + 'username' => $this->login, + 'password' => $this->password, + 'authentication' => "login", + ]); } - - $cm = new ClientManager(); - $client = $cm->make([ - 'host' => $this->host, - 'port' => 993, - 'encryption' => 'ssl', - 'validate_cert' => true, - 'protocol' => 'imap', - 'username' => $this->login, - 'password' => $token, - 'authentication' => "oauth", - ]); - try { $client->connect(); } catch (ConnectionFailedException $e) { @@ -1102,6 +1119,7 @@ class EmailCollector extends CommonObject $host = dol_getprefix('email'); } else { + // Use native IMAP functions if (!function_exists('imap_open')) { $this->error = 'IMAP function not enabled on your PHP'; return -2; @@ -1115,7 +1133,7 @@ class EmailCollector extends CommonObject $connection = imap_open($connectstringsource, $this->login, $this->password); if (!$connection) { - $this->error = 'Failed to open IMAP connection '.$connectstringsource; + $this->error = 'Failed to open IMAP connection '.$connectstringsource.' '.imap_last_error(); return -3; } imap_errors(); // Clear stack of errors. @@ -1129,7 +1147,7 @@ class EmailCollector extends CommonObject //$search='ALL'; } - if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP) && $this->acces_type == 1) { + if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP)) { $criteria = array(array('UNDELETED')); // Seems not supported by some servers $search = ''; $searchhead = ''; @@ -1341,7 +1359,7 @@ class EmailCollector extends CommonObject $nbactiondone = 0; $charset = ($this->hostcharset ? $this->hostcharset : "UTF-8"); - if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP) && $this->acces_type == 1) { + if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP)) { try { //$criteria = [['ALL']]; //$Query = $client->getFolders()[0]->messages()->where($criteria); @@ -1412,11 +1430,12 @@ class EmailCollector extends CommonObject // GET header and overview datas - if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP) && $this->acces_type == 1) { + if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP)) { $header = $imapemail->getHeader()->raw; $overview = $imapemail->getAttributes(); } else { - $header = imap_headerinfo($connection, $imapemail); + //$header = imap_headerinfo($connection, $imapemail); + $header = imap_fetchheader($connection, $imapemail, 0); $overview = imap_fetch_overview($connection, $imapemail, 0); } @@ -1446,7 +1465,6 @@ class EmailCollector extends CommonObject dol_syslog("** Process email ".$iforemailloop." References: ".$headers['References']." Subject: ".$headers['Subject']); - // If there is a filter on trackid if ($searchfilterdoltrackid > 0) { if (empty($headers['References']) || !preg_match('/@'.preg_quote($host, '/').'/', $headers['References'])) { @@ -1520,9 +1538,10 @@ class EmailCollector extends CommonObject $this->db->begin(); - if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP) && $this->acces_type == 1) { + if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP)) { dol_syslog("msgid=".$overview['message_id']." date=".dol_print_date($overview['date'], 'dayrfc', 'gmt')." from=".$overview['from']." to=".$overview['to']." subject=".$overview['subject']); + // Removed emojis $overview['subject'] = preg_replace('/[\x{10000}-\x{10FFFF}]/u', "\xEF\xBF\xBD", $overview['subject']); } else { dol_syslog("msgid=".$overview[0]->message_id." date=".dol_print_date($overview[0]->udate, 'dayrfc', 'gmt')." from=".$overview[0]->from." to=".$overview[0]->to." subject=".$overview[0]->subject); @@ -1538,7 +1557,7 @@ class EmailCollector extends CommonObject global $htmlmsg, $plainmsg, $charset, $attachments; - if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP) && $this->acces_type == 1) { + if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP)) { if ($imapemail->hasHTMLBody()) { $htmlmsg = $imapemail->getHTMLBody(); } @@ -1614,7 +1633,7 @@ class EmailCollector extends CommonObject //print $messagetext; //exit; - if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP) && $this->acces_type == 1) { + if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP)) { $fromstring = $overview['from']; $sender = $overview['sender']; @@ -2514,7 +2533,7 @@ class EmailCollector extends CommonObject $this->errors = $tickettocreate->errors; } else { if ($attachments) { - if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP) && $this->acces_type == 1) { + if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP)) { $destdir = $conf->ticket->dir_output.'/'.$tickettocreate->ref; if (!dol_is_dir($destdir)) { return -1; @@ -2663,7 +2682,7 @@ class EmailCollector extends CommonObject // Error for email or not ? if (!$errorforactions) { - if (empty($conf->global->MAIN_IMAP_USE_PHPIMAP) || $this->acces_type != 1) { + if (empty($conf->global->MAIN_IMAP_USE_PHPIMAP)) { if ($targetdir) { dol_syslog("EmailCollector::doCollectOneCollector move message ".$imapemail." to ".$connectstringtarget, LOG_DEBUG); $res = imap_mail_move($connection, $imapemail, $targetdir, 0); @@ -2675,6 +2694,7 @@ class EmailCollector extends CommonObject } } else { dol_syslog("EmailCollector::doCollectOneCollector message ".$imapemail." to ".$connectstringtarget." was set to read", LOG_DEBUG); + // TODO Make the move } } } else { @@ -2714,13 +2734,14 @@ class EmailCollector extends CommonObject $output = $langs->trans('NoNewEmailToProcess'); } - if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP) && $this->acces_type == 1) { + if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP)) { $client->disconnect(); } else { imap_expunge($connection); // To validate any move imap_close($connection); } + $this->datelastresult = $now; $this->lastresult = $output; $this->debuginfo = 'IMAP search string used : '.$search; From d751a00e7b359a5ebabf81616b8e765c4d55be0c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 24 Aug 2022 03:51:25 +0200 Subject: [PATCH 782/826] Clean comment --- htdocs/core/db/pgsql.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/db/pgsql.class.php b/htdocs/core/db/pgsql.class.php index fe3269867a9..d33affec476 100644 --- a/htdocs/core/db/pgsql.class.php +++ b/htdocs/core/db/pgsql.class.php @@ -875,10 +875,10 @@ class DoliDBPgsql extends DoliDB global $conf; // Type of encryption (2: AES (recommended), 1: DES , 0: no encryption) - $cryptType = ($conf->db->dolibarr_main_db_encryption ? $conf->db->dolibarr_main_db_encryption : 0); + //$cryptType = ($conf->db->dolibarr_main_db_encryption ? $conf->db->dolibarr_main_db_encryption : 0); //Encryption key - $cryptKey = (!empty($conf->db->dolibarr_main_db_cryptkey) ? $conf->db->dolibarr_main_db_cryptkey : ''); + //$cryptKey = (!empty($conf->db->dolibarr_main_db_cryptkey) ? $conf->db->dolibarr_main_db_cryptkey : ''); $return = $value; return $return; From c60f42b1bfd5dd754b14a25e4442d842d5ecf881 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 24 Aug 2022 04:54:02 +0200 Subject: [PATCH 783/826] NEW Introduce dolEncrypt and dolDecrypt to be able to encrypt data in db --- htdocs/core/lib/security.lib.php | 75 ++++++++++++++++++- .../class/emailcollector.class.php | 19 ++++- 2 files changed, 92 insertions(+), 2 deletions(-) diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php index 1d3f013e9f3..13361392396 100644 --- a/htdocs/core/lib/security.lib.php +++ b/htdocs/core/lib/security.lib.php @@ -92,7 +92,80 @@ function dol_decode($chain, $key = '1') } /** - * Returns a hash of a string. + * Encode a string with a symetric encryption. Used to encrypt sensitive data into database. + * Note: If a backup is restored onto another instance with a different $dolibarr_main_instance_unique_id, then decoded value will differ. + * + * @param string $chain string to encode + * @param string $key If '', we use $dolibarr_main_instance_unique_id + * @param string $ciphering Default ciphering algorithm + * @return string encoded string + * @see dolDecrypt(), dol_hash() + */ +function dolEncrypt($chain, $key = '', $ciphering = "AES-256-CTR") +{ + global $dolibarr_main_instance_unique_id; + + if ($chain === '') { + return ''; + } + + $reg = array(); + if (preg_match('/^dolcrypt:([^:]+):(.+)$/', $chain, $reg)) { + // The $chain is already a crypted string + return $chain; + } + + if (empty($key)) { + $key = $dolibarr_main_instance_unique_id; + } + + $newchain = $chain; + + if (!function_exists('openssl_encrypt')) { + return $chain; + } else { + $newchain = openssl_encrypt($chain, $ciphering, $key); + return 'dolcrypt:'.$ciphering.':'.$newchain; + } +} + +/** + * Decode a string with a symetric encryption. Used to decrypt sensitive data saved into database. + * Note: If a backup is restored onto another instance with a different $dolibarr_main_instance_unique_id, then decoded value will differ. + * + * @param string $chain string to encode + * @param string $key If '', we use $dolibarr_main_instance_unique_id + * @return string encoded string + * @see dolEncrypt(), dol_hash() + */ +function dolDecrypt($chain, $key = '') +{ + global $dolibarr_main_instance_unique_id; + + if ($chain === '') { + return ''; + } + + if (empty($key)) { + $key = $dolibarr_main_instance_unique_id; + } + + $reg = array(); + if (preg_match('/^dolcrypt:([^:]+):(.+)$/', $chain, $reg)) { + $ciphering = $reg[1]; + if (function_exists('openssl_decrypt')) { + $newchain = openssl_decrypt($reg[2], $ciphering, $key); + } else { + $newchain = 'Error function openssl_decrypt() not available'; + } + return $newchain; + } else { + return $chain; + } +} + +/** + * Returns a hash (non reversible encryption) of a string. * If constant MAIN_SECURITY_HASH_ALGO is defined, we use this function as hashing function (recommanded value is 'password_hash') * If constant MAIN_SECURITY_SALT is defined, we use it as a salt (used only if hashing algorightm is something else than 'password_hash'). * diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index 5c885209a71..7c43286ed9f 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -311,8 +311,13 @@ class EmailCollector extends CommonObject return -1; } + include_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php'; + $this->password = dolEncrypt($this->password); + $id = $this->createCommon($user, $notrigger); + $this->password = dolDecrypt($this->password); + if (is_array($this->filters) && count($this->filters)) { $emailcollectorfilter = new EmailCollectorFilter($this->db); @@ -371,6 +376,7 @@ class EmailCollector extends CommonObject unset($object->id); unset($object->fk_user_creat); unset($object->import_key); + unset($object->password); // Clear fields $object->ref = "copy_of_".$object->ref; @@ -422,6 +428,10 @@ class EmailCollector extends CommonObject public function fetch($id, $ref = null) { $result = $this->fetchCommon($id, $ref); + + include_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php'; + $this->password = dolDecrypt($this->password); + //if ($result > 0 && ! empty($this->table_element_line)) $this->fetchLines(); return $result; } @@ -517,7 +527,14 @@ class EmailCollector extends CommonObject return -1; } - return $this->updateCommon($user, $notrigger); + include_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php'; + $this->password = dolEncrypt($this->password); + + $result = $this->updateCommon($user, $notrigger); + + $this->password = dolDecrypt($this->password); + + return $result; } /** From 2e49ae143f602027fa6bc75fc50589103c6643f9 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Wed, 24 Aug 2022 09:57:04 +0200 Subject: [PATCH 784/826] FIX php8 compatibility --- htdocs/admin/const.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/htdocs/admin/const.php b/htdocs/admin/const.php index a5a68a0bb49..5495c34ca5e 100644 --- a/htdocs/admin/const.php +++ b/htdocs/admin/const.php @@ -185,12 +185,12 @@ print ''; print '
'; print ''; print ''; -print getTitleFieldOfList('Name', 0, $_SERVER['PHP_SELF'], 'name', '', $param, '', $sortfield, $sortorder, '')."\n"; +print getTitleFieldOfList('Name', 0, $_SERVER['PHP_SELF'], 'name', '', $param, '', $sortfield, $sortorder, '') . "\n"; print getTitleFieldOfList("Value", 0, $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder); print getTitleFieldOfList("Comment", 0, $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder); -print getTitleFieldOfList('DateModificationShort', 0, $_SERVER['PHP_SELF'], 'tms', '', $param, '', $sortfield, $sortorder, 'center ')."\n"; -if (!empty($conf->multicompany->enabled) && !$user->entity) { - print getTitleFieldOfList('Entity', 0, $_SERVER['PHP_SELF'], 'tms', '', $param, '', $sortfield, $sortorder, 'center ')."\n"; +print getTitleFieldOfList('DateModificationShort', 0, $_SERVER['PHP_SELF'], 'tms', '', $param, '', $sortfield, $sortorder, 'center ') . "\n"; +if (isModEnabled('multicompany') && !$user->entity) { + print getTitleFieldOfList('Entity', 0, $_SERVER['PHP_SELF'], 'tms', '', $param, '', $sortfield, $sortorder, 'center ') . "\n"; } print getTitleFieldOfList("", 0, $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, 'center '); print "\n"; @@ -211,14 +211,14 @@ print ''; print ''; // Limit to superadmin -if (!empty($conf->multicompany->enabled) && !$user->entity) { +if (isModEnabled('multicompany') && !$user->entity) { print ''; print '\n"; @@ -278,14 +278,14 @@ if ($result) { print ''; // Entity limit to superadmin - if (!empty($conf->multicompany->enabled) && !$user->entity) { + if (isModEnabled('multicompany') && !$user->entity) { print ''; print ''; } // Limit to superadmin -if (!empty($conf->multicompany->enabled) && !$user->entity) { +if (isModEnabled('multicompany') && !$user->entity) { print ''; } else { print ''; } print ''; foreach ($modules as $module => $delays) { - if (!empty($conf->$module->enabled)) { + if (isModEnabled('module')) { foreach ($delays as $delay) { - $value = (!empty($conf->global->{$delay['code']}) ? $conf->global->{$delay['code']}:0); + $value = (!empty($conf->global->{$delay['code']}) ? $conf->global->{$delay['code']} : 0); print ''; - print ''; - print ''; + print ''; + print ''; } } } @@ -260,13 +260,13 @@ if ($action == 'edit') { print ''; foreach ($modules as $module => $delays) { - if (!empty($conf->$module->enabled)) { + if (isModEnabled('module')) { foreach ($delays as $delay) { - $value = (!empty($conf->global->{$delay['code']}) ? $conf->global->{$delay['code']}:0); + $value = (!empty($conf->global->{$delay['code']}) ? $conf->global->{$delay['code']} : 0); print ''; - print ''; - print ''; - print ''; + print ''; + print ''; + print ''; } } } From 67300536abf5ccf9f540c17b39664454a894ae07 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Wed, 24 Aug 2022 10:04:32 +0200 Subject: [PATCH 788/826] FIX php8 compatibility --- htdocs/admin/emailcollector_card.php | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/htdocs/admin/emailcollector_card.php b/htdocs/admin/emailcollector_card.php index e297ba02d61..e41777da9d9 100644 --- a/htdocs/admin/emailcollector_card.php +++ b/htdocs/admin/emailcollector_card.php @@ -37,7 +37,7 @@ include_once DOL_DOCUMENT_ROOT.'/emailcollector/lib/emailcollector.lib.php'; if (!$user->admin) { accessforbidden(); } -if (empty($conf->emailcollector->enabled)) { +if (!isModEnabled('emailcollector')) { accessforbidden(); } @@ -547,20 +547,21 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print ''; $arrayoftypes = array( - 'loadthirdparty'=>$langs->trans('LoadThirdPartyFromName', $langs->transnoentities("ThirdPartyName")), - 'loadandcreatethirdparty'=>$langs->trans('LoadThirdPartyFromNameOrCreate', $langs->transnoentities("ThirdPartyName")), - 'recordjoinpiece'=>'AttachJoinedDocumentsToObject', - 'recordevent'=>'RecordEvent'); + 'loadthirdparty' => $langs->trans('LoadThirdPartyFromName', $langs->transnoentities("ThirdPartyName")), + 'loadandcreatethirdparty' => $langs->trans('LoadThirdPartyFromNameOrCreate', $langs->transnoentities("ThirdPartyName")), + 'recordjoinpiece' => 'AttachJoinedDocumentsToObject', + 'recordevent' => 'RecordEvent' + ); $arrayoftypesnocondition = $arrayoftypes; - if (!empty($conf->project->enabled)) { + if (isModEnabled('project')) { $arrayoftypes['project'] = 'CreateLeadAndThirdParty'; } $arrayoftypesnocondition['project'] = 'CreateLeadAndThirdParty'; - if (!empty($conf->ticket->enabled)) { + if (isModEnabled('ticket')) { $arrayoftypes['ticket'] = 'CreateTicketAndThirdParty'; } $arrayoftypesnocondition['ticket'] = 'CreateTicketAndThirdParty'; - if (!empty($conf->recruitment->enabled)) { + if (isModEnabled('recruitment')) { $arrayoftypes['candidature'] = 'CreateCandidature'; } $arrayoftypesnocondition['candidature'] = 'CreateCandidature'; From a35bbd37f002d36d143e65702549386b5b4674d8 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Wed, 24 Aug 2022 10:05:36 +0200 Subject: [PATCH 789/826] FIX php8 compatibility --- htdocs/admin/expensereport.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/admin/expensereport.php b/htdocs/admin/expensereport.php index 64cf24ca6fa..2418ec3e26c 100644 --- a/htdocs/admin/expensereport.php +++ b/htdocs/admin/expensereport.php @@ -6,7 +6,7 @@ * Copyright (C) 2005-2014 Regis Houssin * Copyright (C) 2008 Raphael Bertrand (Resultic) * Copyright (C) 2011-2013 Juanjo Menent - * Copyright (C) 2011-2018 Philippe Grand + * Copyright (C) 2011-2022 Philippe Grand * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -148,7 +148,7 @@ if ($action == 'updateMask') { $res2 = dolibarr_set_const($db, "EXPENSEREPORT_DRAFT_WATERMARK", trim($draft), 'chaine', 0, '', $conf->entity); $res3 = 0; - if (!empty($conf->project->enabled) && GETPOSTISSET('EXPENSEREPORT_PROJECT_IS_REQUIRED')) { // Option may not be provided + if (isModEnabled('project') && GETPOSTISSET('EXPENSEREPORT_PROJECT_IS_REQUIRED')) { // Option may not be provided $res3 = dolibarr_set_const($db, 'EXPENSEREPORT_PROJECT_IS_REQUIRED', GETPOST('EXPENSEREPORT_PROJECT_IS_REQUIRED', 'int'), 'chaine', 0, '', $conf->entity); } @@ -471,7 +471,7 @@ print $form->textwithpicto($langs->trans("WatermarkOnDraftExpenseReports"), $htm print ''; print ''."\n"; -if (!empty($conf->project->enabled)) { +if (isModEnabled('project')) { print ''; } From 10731b22c839edc3534fe31fb0742a8b168fb2d0 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Wed, 24 Aug 2022 10:11:47 +0200 Subject: [PATCH 792/826] FIX php8 compatibility --- htdocs/admin/ldap.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/htdocs/admin/ldap.php b/htdocs/admin/ldap.php index ef488943a4b..196702b938b 100644 --- a/htdocs/admin/ldap.php +++ b/htdocs/admin/ldap.php @@ -158,24 +158,24 @@ if (!empty($conf->global->LDAP_SYNCHRO_ACTIVE) && empty($conf->global->LDAP_USER print ''; // Synchro contact active -if (!empty($conf->societe->enabled)) { - print ''; + print ''; } // Synchro member active -if (!empty($conf->adherent->enabled)) { - print ''; + print ''; } // Synchro member type active -if (!empty($conf->adherent->enabled)) { - print ''; + print ''; } // Fields from hook From 893a2eeb43bd7ef27b2f41fae75e38a99e0b097a Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Wed, 24 Aug 2022 10:16:43 +0200 Subject: [PATCH 793/826] FIX php8 compatibility --- htdocs/admin/limits.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/htdocs/admin/limits.php b/htdocs/admin/limits.php index 1209f41c48e..d644f2bd2f6 100644 --- a/htdocs/admin/limits.php +++ b/htdocs/admin/limits.php @@ -36,7 +36,7 @@ if (!$user->admin) { $action = GETPOST('action', 'aZ09'); $currencycode = GETPOST('currencycode', 'alpha'); -if (!empty($conf->multicurrency->enabled) && !empty($conf->global->MULTICURRENCY_USE_LIMIT_BY_CURRENCY)) { +if (isModEnabled('multicompany') && !empty($conf->global->MULTICURRENCY_USE_LIMIT_BY_CURRENCY)) { // When MULTICURRENCY_USE_LIMIT_BY_CURRENCY is on, we use always a defined currency code instead of '' even for default. $currencycode = (!empty($currencycode) ? $currencycode : $conf->currency); } @@ -105,12 +105,12 @@ print load_fiche_titre($title, '', 'title_setup'); $aCurrencies = array($conf->currency); // Default currency always first position -if (!empty($conf->multicurrency->enabled) && !empty($conf->global->MULTICURRENCY_USE_LIMIT_BY_CURRENCY)) { - require_once DOL_DOCUMENT_ROOT.'/core/lib/multicurrency.lib.php'; +if (isModEnabled('multicompany') && !empty($conf->global->MULTICURRENCY_USE_LIMIT_BY_CURRENCY)) { + require_once DOL_DOCUMENT_ROOT . '/core/lib/multicurrency.lib.php'; - $sql = "SELECT rowid, code FROM ".MAIN_DB_PREFIX."multicurrency"; - $sql .= " WHERE entity = ".((int) $conf->entity); - $sql .= " AND code <> '".$db->escape($conf->currency)."'"; // Default currency always first position + $sql = "SELECT rowid, code FROM " . MAIN_DB_PREFIX . "multicurrency"; + $sql .= " WHERE entity = " . ((int) $conf->entity); + $sql .= " AND code <> '" . $db->escape($conf->currency) . "'"; // Default currency always first position $resql = $db->query($sql); if ($resql) { while ($obj = $db->fetch_object($resql)) { @@ -129,11 +129,11 @@ print ''.$langs->trans("LimitsDesc")."
\n" print "
\n"; if ($action == 'edit') { - print ''; - print ''; + print ''; + print ''; print ''; - if (!empty($conf->multicurrency->enabled) && !empty($conf->global->MULTICURRENCY_USE_LIMIT_BY_CURRENCY)) { - print ''; + if (isModEnabled('multicompany') && !empty($conf->global->MULTICURRENCY_USE_LIMIT_BY_CURRENCY)) { + print ''; } clearstatcache(); @@ -194,7 +194,7 @@ if ($action == 'edit') { print ''; } -if (!empty($conf->multicurrency->enabled) && !empty($conf->global->MULTICURRENCY_USE_LIMIT_BY_CURRENCY)) { +if (isModEnabled('multicompany') && !empty($conf->global->MULTICURRENCY_USE_LIMIT_BY_CURRENCY)) { if (!empty($aCurrencies) && count($aCurrencies) > 1) { print dol_get_fiche_end(); } From db3f37f416140c6d06d11ed8e564bca0fce9327d Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Wed, 24 Aug 2022 10:20:02 +0200 Subject: [PATCH 794/826] FIX php8 compatibility --- htdocs/admin/mails_emailing.php | 48 ++++++++++++++++----------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/htdocs/admin/mails_emailing.php b/htdocs/admin/mails_emailing.php index 79ddda792e0..f7203d88474 100644 --- a/htdocs/admin/mails_emailing.php +++ b/htdocs/admin/mails_emailing.php @@ -294,16 +294,16 @@ if ($action == 'edit') { } print '
'; } @@ -326,15 +326,15 @@ if ($action == 'edit') { } print ''; @@ -342,14 +342,14 @@ if ($action == 'edit') { // ID if (!empty($conf->use_javascript_ajax) || (isset($conf->global->MAIN_MAIL_SENDMODE_EMAILING) && in_array($conf->global->MAIN_MAIL_SENDMODE_EMAILING, array('smtps', 'swiftmailer')))) { $mainstmpid = (!empty($conf->global->MAIN_MAIL_SMTPS_ID_EMAILING) ? $conf->global->MAIN_MAIL_SMTPS_ID_EMAILING : ''); - print ''; } @@ -357,14 +357,14 @@ if ($action == 'edit') { // PW if (!empty($conf->use_javascript_ajax) || (isset($conf->global->MAIN_MAIL_SENDMODE_EMAILING) && in_array($conf->global->MAIN_MAIL_SENDMODE_EMAILING, array('smtps', 'swiftmailer')))) { $mainsmtppw = (!empty($conf->global->MAIN_MAIL_SMTPS_PW_EMAILING) ? $conf->global->MAIN_MAIL_SMTPS_PW_EMAILING : ''); - print ''; } @@ -533,16 +533,16 @@ if ($action == 'edit') { if (!empty($conf->global->MAIN_MAIL_SENDMODE_EMAILING) && $conf->global->MAIN_MAIL_SENDMODE_EMAILING != 'default') { if ($conf->global->MAIN_MAIL_SENDMODE_EMAILING != 'mail' || !$linuxlike) { if (function_exists('fsockopen') && $port && $server) { - print ''.$langs->trans("DoTestServerAvailability").''; + print '' . $langs->trans("DoTestServerAvailability") . ''; } } else { - print ''.$langs->trans("DoTestServerAvailability").''; + print '' . $langs->trans("DoTestServerAvailability") . ''; } - print ''.$langs->trans("DoTestSend").''; + print '' . $langs->trans("DoTestSend") . ''; - if (!empty($conf->fckeditor->enabled)) { - print ''.$langs->trans("DoTestSendHTML").''; + if (isModEnabled('fckeditor')) { + print '' . $langs->trans("DoTestSendHTML") . ''; } } From 74c5892e4cbe604c402a1e9e3fd57c1e13933ca6 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Wed, 24 Aug 2022 10:22:06 +0200 Subject: [PATCH 795/826] FIX php8 compatibility --- htdocs/admin/loan.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/htdocs/admin/loan.php b/htdocs/admin/loan.php index 72b2a15d678..3c777e1f187 100644 --- a/htdocs/admin/loan.php +++ b/htdocs/admin/loan.php @@ -26,7 +26,7 @@ require '../main.inc.php'; // Class require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; -if (!empty($conf->accounting->enabled)) { +if (isModEnabled('accounting')) { require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php'; } @@ -76,7 +76,7 @@ if ($action == 'update') { llxHeader(); $form = new Form($db); -if (!empty($conf->accounting->enabled)) { +if (isModEnabled('accounting')) { $formaccounting = new FormAccounting($db); } @@ -100,14 +100,14 @@ foreach ($list as $key) { // Param $label = $langs->trans($key); - print ''; + print ''; // Value print ''; } From 03dc21bef229a2527d12bebc306058c735f28534 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 24 Aug 2022 10:22:48 +0200 Subject: [PATCH 796/826] NEW Saved token of OAUTH module are now encrypted into llx_oauth_token --- htdocs/includes/OAuth/Common/Storage/DoliStorage.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/htdocs/includes/OAuth/Common/Storage/DoliStorage.php b/htdocs/includes/OAuth/Common/Storage/DoliStorage.php index 32422cf1712..3e09e53fbe6 100644 --- a/htdocs/includes/OAuth/Common/Storage/DoliStorage.php +++ b/htdocs/includes/OAuth/Common/Storage/DoliStorage.php @@ -104,7 +104,9 @@ class DoliStorage implements TokenStorageInterface //var_dump($token); dol_syslog("storeAccessToken service=".$service); - $serializedToken = serialize($token); + include_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php'; + $serializedToken = dolEncrypt(serialize($token)); + $this->tokens[$service] = $token; if (!is_array($this->tokens)) { @@ -155,7 +157,8 @@ class DoliStorage implements TokenStorageInterface } $result = $this->db->fetch_array($resql); if ($result) { - $token = unserialize($result['token']); + include_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php'; + $token = unserialize(dolDecrypt($result['token'])); $this->date_creation = $this->db->jdate($result['datec']); $this->date_modification = $this->db->jdate($result['tms']); $this->state = $result['state']; From 38ea28813f1600487c65b281c8e10b237df1aff8 Mon Sep 17 00:00:00 2001 From: Francis Appels Date: Thu, 11 Aug 2022 18:49:04 +0200 Subject: [PATCH 797/826] HAR-19 Fix missing shared supplier orders in product related objects. --- htdocs/product/stats/commande_fournisseur.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/product/stats/commande_fournisseur.php b/htdocs/product/stats/commande_fournisseur.php index 5a236334b5e..8a4957d574d 100644 --- a/htdocs/product/stats/commande_fournisseur.php +++ b/htdocs/product/stats/commande_fournisseur.php @@ -150,7 +150,7 @@ if ($id > 0 || !empty($ref)) { $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; } $sql .= " WHERE c.fk_soc = s.rowid"; - $sql .= " AND c.entity = ".$conf->entity; + $sql .= " AND c.entity IN (".getEntity('supplier_order').")"; $sql .= " AND d.fk_commande = c.rowid"; $sql .= " AND d.fk_product = ".((int) $product->id); if (!empty($search_month)) { From d1fee1f83a51ed22f48bb7b875b1ae77d9ed7876 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 24 Aug 2022 11:49:02 +0200 Subject: [PATCH 798/826] Update ticket.lib.php --- htdocs/core/lib/ticket.lib.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/htdocs/core/lib/ticket.lib.php b/htdocs/core/lib/ticket.lib.php index ef2f6bcf286..8ef509057c4 100644 --- a/htdocs/core/lib/ticket.lib.php +++ b/htdocs/core/lib/ticket.lib.php @@ -1,7 +1,7 @@ * Copyright (C) 2016 Christophe Battarel - * Copyright (C) 2019-2020 Frédéric France + * Copyright (C) 2019-2022 Frédéric France * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -250,7 +250,7 @@ function llxHeaderTicket($title, $head = "", $disablejs = 0, $disablehead = 0, $ if (!empty($conf->global->TICKET_IMAGE_PUBLIC_INTERFACE)) { print '
'; - print ''; + print ''; print '
'; } @@ -560,7 +560,7 @@ function show_ticket_messaging($conf, $langs, $db, $filterobj, $objcon = '', $no // Set $out to sow events $out = ''; - if (empty($conf->agenda->enabled)) { + if (!isModEnabled('agenda')) { $langs->loadLangs(array("admin", "errors")); $out = info_admin($langs->trans("WarningModuleXDisabledSoYouMayMissEventHere", $langs->transnoentitiesnoconv("Module2400Name")), 0, 0, 'warning'); } @@ -697,8 +697,8 @@ function show_ticket_messaging($conf, $langs, $db, $filterobj, $objcon = '', $no // $out.=''.$langs->trans('Show').''; //} - if ($user->rights->agenda->allactions->create || - (($actionstatic->authorid == $user->id || $actionstatic->userownerid == $user->id) && $user->rights->agenda->myactions->create)) { + if (!empty($user->rights->agenda->allactions->create) || + (($actionstatic->authorid == $user->id || $actionstatic->userownerid == $user->id) && !empty($user->rights->agenda->myactions->create))) { $out .= ''; } From 03d086f741ea382ef2fc70af6395ec5cf2484695 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 24 Aug 2022 10:22:48 +0200 Subject: [PATCH 799/826] NEW Encrypt all sensitive constants in llx_const --- htdocs/admin/mailman.php | 2 +- htdocs/core/class/CMailFile.class.php | 1 + htdocs/core/class/conf.class.php | 5 +++-- htdocs/core/lib/admin.lib.php | 20 +++++++++++++++---- htdocs/core/lib/security2.lib.php | 10 ++++++++++ htdocs/core/modules/modAdherent.class.php | 2 +- .../OAuth/Common/Storage/DoliStorage.php | 7 +++++-- .../install/mysql/migration/16.0.0-17.0.0.sql | 2 ++ htdocs/langs/en_US/mailmanspip.lang | 2 +- .../mailmanspip/class/mailmanspip.class.php | 2 +- 10 files changed, 41 insertions(+), 12 deletions(-) diff --git a/htdocs/admin/mailman.php b/htdocs/admin/mailman.php index 8b003ce2d4e..eca17ea8e76 100644 --- a/htdocs/admin/mailman.php +++ b/htdocs/admin/mailman.php @@ -158,7 +158,7 @@ if (!empty($conf->global->ADHERENT_USE_MAILMAN)) { $link .= ''; // Edition des varibales globales $constantes = array( - 'ADHERENT_MAILMAN_ADMINPW', + 'ADHERENT_MAILMAN_ADMIN_PASSWORD', 'ADHERENT_MAILMAN_URL', 'ADHERENT_MAILMAN_UNSUB_URL', 'ADHERENT_MAILMAN_LISTS' diff --git a/htdocs/core/class/CMailFile.class.php b/htdocs/core/class/CMailFile.class.php index d9a21fdb71e..a9518ee6dab 100644 --- a/htdocs/core/class/CMailFile.class.php +++ b/htdocs/core/class/CMailFile.class.php @@ -1555,6 +1555,7 @@ class CMailFile dol_syslog("Try socket connection to host=".$host." port=".$port); //See if we can connect to the SMTP server + $errno = 0; $errstr = ''; if ($socket = @fsockopen( $host, // Host to test, IP or domain. Add ssl:// for SSL/TLS. $port, // which Port number to use diff --git a/htdocs/core/class/conf.class.php b/htdocs/core/class/conf.class.php index e3063f6f4e2..626052551d5 100644 --- a/htdocs/core/class/conf.class.php +++ b/htdocs/core/class/conf.class.php @@ -255,6 +255,8 @@ class Conf ); if (!is_null($db) && is_object($db)) { + include_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php'; + // Define all global constants into $this->global->key=value $sql = "SELECT ".$db->decrypt('name')." as name,"; $sql .= " ".$db->decrypt('value')." as value, entity"; @@ -278,8 +280,7 @@ class Conf $value = $_ENV['DOLIBARR_'.$key]; } - //if (! defined("$key")) define("$key", $value); // In some cases, the constant might be already forced (Example: SYSLOG_HANDLERS during install) - $this->global->$key = $value; + $this->global->$key = dolDecrypt($value); if ($value && strpos($key, 'MAIN_MODULE_') === 0) { $reg = array(); diff --git a/htdocs/core/lib/admin.lib.php b/htdocs/core/lib/admin.lib.php index a68c268f8bd..53193db176c 100644 --- a/htdocs/core/lib/admin.lib.php +++ b/htdocs/core/lib/admin.lib.php @@ -603,7 +603,8 @@ function dolibarr_get_const($db, $name, $entity = 1) if ($resql) { $obj = $db->fetch_object($resql); if ($obj) { - $value = $obj->value; + include_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php'; + $value = dolDecrypt($obj->value); } } return $value; @@ -651,11 +652,22 @@ function dolibarr_set_const($db, $name, $value, $type = 'chaine', $visible = 0, $resql = $db->query($sql); if (strcmp($value, '')) { // true if different. Must work for $value='0' or $value=0 - $sql = "INSERT INTO ".MAIN_DB_PREFIX."const(name,value,type,visible,note,entity)"; + if (!preg_match('/^MAIN_LOGEVENTS/', $name) && (preg_match('/(_KEY|_EXPORTKEY|_SECUREKEY|_SERVERKEY|_PASS|_PASSWORD|_PW|_PW_TICKET|_PW_EMAILING|_SECRET|_SECURITY_TOKEN|_WEB_TOKEN)$/', $name))) { + // This seems a sensitive constant, we encrypt its value + // To list all sensitive constant, you can make a + // WHERE name like '%\_KEY' or name like '%\_EXPORTKEY' or name like '%\_SECUREKEY' or name like '%\_SERVERKEY' or name like '%\_PASS' or name like '%\_PASSWORD' or name like '%\_SECRET' + // or name like '%\_SECURITY_TOKEN' or name like '%\WEB_TOKEN' + include_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php'; + $newvalue = dolEncrypt($value); + } else { + $newvalue = $value; + } + + $sql = "INSERT INTO ".MAIN_DB_PREFIX."const(name, value, type, visible, note, entity)"; $sql .= " VALUES ("; $sql .= $db->encrypt($name); - $sql .= ", ".$db->encrypt($value); - $sql .= ",'".$db->escape($type)."',".((int) $visible).",'".$db->escape($note)."',".((int) $entity).")"; + $sql .= ", ".$db->encrypt($newvalue); + $sql .= ", '".$db->escape($type)."', ".((int) $visible).", '".$db->escape($note)."', ".((int) $entity).")"; //print "sql".$value."-".pg_escape_string($value)."-".$sql;exit; //print "xx".$db->escape($value); diff --git a/htdocs/core/lib/security2.lib.php b/htdocs/core/lib/security2.lib.php index 8f4abca6167..380282fc48b 100644 --- a/htdocs/core/lib/security2.lib.php +++ b/htdocs/core/lib/security2.lib.php @@ -374,13 +374,16 @@ function encodedecode_dbpassconf($level = 0) $lineofpass = 0; + $reg = array(); if (preg_match('/^[^#]*dolibarr_main_db_encrypted_pass[\s]*=[\s]*(.*)/i', $buffer, $reg)) { // Old way to save crypted value $val = trim($reg[1]); // This also remove CR/LF $val = preg_replace('/^["\']/', '', $val); $val = preg_replace('/["\'][\s;]*$/', '', $val); if (!empty($val)) { $passwd_crypted = $val; + // method dol_encode/dol_decode $val = dol_decode($val); + //$val = dolEncrypt($val); $passwd = $val; $lineofpass = 1; } @@ -389,10 +392,17 @@ function encodedecode_dbpassconf($level = 0) $val = preg_replace('/^["\']/', '', $val); $val = preg_replace('/["\'][\s;]*$/', '', $val); if (preg_match('/crypted:/i', $buffer)) { + // method dol_encode/dol_decode $val = preg_replace('/crypted:/i', '', $val); $passwd_crypted = $val; $val = dol_decode($val); $passwd = $val; + } elseif (preg_match('/^dolcrypt:([^:]+):(.*)$/i', $buffer, $reg)) { + // method dolEncrypt/dolDecrypt + $val = preg_replace('/crypted:([^:]+):/i', '', $val); + $passwd_crypted = $val; + $val = dolDecrypt($buffer); + $passwd = $val; } else { $passwd = $val; $val = dol_encode($val); diff --git a/htdocs/core/modules/modAdherent.class.php b/htdocs/core/modules/modAdherent.class.php index ec0546e9af1..a86c5162b01 100644 --- a/htdocs/core/modules/modAdherent.class.php +++ b/htdocs/core/modules/modAdherent.class.php @@ -145,7 +145,7 @@ class modAdherent extends DolibarrModules $this->const[$r][4] = 0; $r++; - $this->const[$r][0] = "ADHERENT_MAILMAN_ADMINPW"; + $this->const[$r][0] = "ADHERENT_MAILMAN_ADMIN_PASSWORD"; $this->const[$r][1] = "chaine"; $this->const[$r][2] = ""; $this->const[$r][3] = "Mot de passe Admin des liste mailman"; diff --git a/htdocs/includes/OAuth/Common/Storage/DoliStorage.php b/htdocs/includes/OAuth/Common/Storage/DoliStorage.php index 32422cf1712..3e09e53fbe6 100644 --- a/htdocs/includes/OAuth/Common/Storage/DoliStorage.php +++ b/htdocs/includes/OAuth/Common/Storage/DoliStorage.php @@ -104,7 +104,9 @@ class DoliStorage implements TokenStorageInterface //var_dump($token); dol_syslog("storeAccessToken service=".$service); - $serializedToken = serialize($token); + include_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php'; + $serializedToken = dolEncrypt(serialize($token)); + $this->tokens[$service] = $token; if (!is_array($this->tokens)) { @@ -155,7 +157,8 @@ class DoliStorage implements TokenStorageInterface } $result = $this->db->fetch_array($resql); if ($result) { - $token = unserialize($result['token']); + include_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php'; + $token = unserialize(dolDecrypt($result['token'])); $this->date_creation = $this->db->jdate($result['datec']); $this->date_modification = $this->db->jdate($result['tms']); $this->state = $result['state']; diff --git a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql index d469b2de777..f0906b024bf 100644 --- a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql +++ b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql @@ -55,6 +55,8 @@ ALTER TABLE llx_user DROP COLUMN idpers3; -- v17 +UPDATE llx_const set name = 'ADHERENT_MAILMAN_ADMIN_PASSWORD' WHERE name = 'ADHERENT_MAILMAN_ADMINPW'; + ALTER TABLE llx_oauth_token ADD COLUMN state text after tokenstring; ALTER TABLE llx_adherent ADD COLUMN default_lang VARCHAR(6) DEFAULT NULL AFTER datefin; diff --git a/htdocs/langs/en_US/mailmanspip.lang b/htdocs/langs/en_US/mailmanspip.lang index bab4b3576b4..6ff3ac9f770 100644 --- a/htdocs/langs/en_US/mailmanspip.lang +++ b/htdocs/langs/en_US/mailmanspip.lang @@ -7,7 +7,7 @@ MailmanCreationSuccess=Subscription test was executed successfully MailmanDeletionSuccess=Unsubscription test was executed successfully SynchroMailManEnabled=A Mailman update will be performed SynchroSpipEnabled=A Spip update will be performed -DescADHERENT_MAILMAN_ADMINPW=Mailman administrator password +DescADHERENT_MAILMAN_ADMIN_PASSWORD=Mailman administrator password DescADHERENT_MAILMAN_URL=URL for Mailman subscriptions DescADHERENT_MAILMAN_UNSUB_URL=URL for Mailman unsubscriptions DescADHERENT_MAILMAN_LISTS=List(s) for automatic inscription of new members (separated by a comma) diff --git a/htdocs/mailmanspip/class/mailmanspip.class.php b/htdocs/mailmanspip/class/mailmanspip.class.php index 9635c0e2c1f..bcfb1b83d6e 100644 --- a/htdocs/mailmanspip/class/mailmanspip.class.php +++ b/htdocs/mailmanspip/class/mailmanspip.class.php @@ -141,7 +141,7 @@ class MailmanSpip $list, $object->email, $object->pass, - $conf->global->ADHERENT_MAILMAN_ADMINPW + $conf->global->ADHERENT_MAILMAN_ADMIN_PASSWORD ); $curl_url = str_replace($patterns, $replace, $url); From eb8ff378e66a3c4978a851a2e56fe0d689d923a1 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 24 Aug 2022 12:27:50 +0200 Subject: [PATCH 800/826] Fix encryption of sensitive constants --- htdocs/admin/const.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/htdocs/admin/const.php b/htdocs/admin/const.php index a5a68a0bb49..f8e8de04c20 100644 --- a/htdocs/admin/const.php +++ b/htdocs/admin/const.php @@ -26,6 +26,7 @@ require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php'; // Load translation files required by the page $langs->load("admin"); @@ -255,16 +256,18 @@ if ($result) { while ($i < $num) { $obj = $db->fetch_object($result); + $value = dolDecrypt($obj->value); + print "\n"; - print '
'."\n"; + print ''."\n"; // Value print ''; // Note @@ -280,12 +283,12 @@ if ($result) { // Entity limit to superadmin if (!empty($conf->multicompany->enabled) && !$user->entity) { print ''; print ''; } - if (!empty(isModEnabled('paymentbybanktransfer'))) { + if (isModEnabled('paymentbybanktransfer')) { print ''; print ''; From 99689f107dfbfbe8e3016046a81a08c312a67318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 24 Aug 2022 18:11:12 +0200 Subject: [PATCH 805/826] Update card.php --- htdocs/compta/bank/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/bank/card.php b/htdocs/compta/bank/card.php index 0ffa5cfaf0d..420ff97ff0d 100644 --- a/htdocs/compta/bank/card.php +++ b/htdocs/compta/bank/card.php @@ -234,7 +234,7 @@ if (empty($reshook)) { $object->number = trim(GETPOST("number")); $object->cle_rib = trim(GETPOST("cle_rib")); $object->bic = trim(GETPOST("bic")); - $object->iban = trim(GETPOST("iban"));('paymentbybankt + $object->iban = trim(GETPOST("iban")); $object->domiciliation = trim(GETPOST("domiciliation", "alphanohtml")); $object->pti_in_ctti = empty(GETPOST("pti_in_ctti")) ? 0 : 1; From 6f8de50004f41f055f72427e9821ef3cdf4c509e Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Wed, 24 Aug 2022 19:59:06 +0200 Subject: [PATCH 806/826] Add right --- htdocs/core/lib/product.lib.php | 15 ++++++++++----- htdocs/core/modules/modProduct.class.php | 8 ++++++++ htdocs/core/modules/modService.class.php | 8 ++++++++ htdocs/langs/en_US/admin.lang | 2 ++ htdocs/product/list.php | 22 +++++++++++++++------- 5 files changed, 43 insertions(+), 12 deletions(-) diff --git a/htdocs/core/lib/product.lib.php b/htdocs/core/lib/product.lib.php index 7b3d1e4637f..5b1d5ba91d0 100644 --- a/htdocs/core/lib/product.lib.php +++ b/htdocs/core/lib/product.lib.php @@ -38,8 +38,11 @@ function product_prepare_head($object) $langs->load("products"); $label = $langs->trans('Product'); + $usercancreadprice = getDolGlobalString('MAIN_USE_ADVANCED_PERMS')?$user->hasRight('product', 'product_advance', 'read_prices'):$user->hasRight('produit', 'lire'); + if ($object->isService()) { $label = $langs->trans('Service'); + $usercancreadprice = getDolGlobalString('MAIN_USE_ADVANCED_PERMS')?$user->hasRight('service', 'service_advance', 'read_prices'):$user->hasRight('service', 'lire'); } $h = 0; @@ -50,7 +53,7 @@ function product_prepare_head($object) $head[$h][2] = 'card'; $h++; - if (!empty($object->status)) { + if (!empty($object->status) && $usercancreadprice) { $head[$h][0] = DOL_URL_ROOT."/product/price.php?id=".$object->id; $head[$h][1] = $langs->trans("SellingPrices"); $head[$h][2] = 'price'; @@ -61,10 +64,12 @@ function product_prepare_head($object) if ((((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) && $user->rights->fournisseur->lire) || (!empty($conf->margin->enabled) && $user->rights->margin->liretous) ) { - $head[$h][0] = DOL_URL_ROOT."/product/fournisseurs.php?id=".$object->id; - $head[$h][1] = $langs->trans("BuyingPrices"); - $head[$h][2] = 'suppliers'; - $h++; + if ($usercancreadprice) { + $head[$h][0] = DOL_URL_ROOT."/product/fournisseurs.php?id=".$object->id; + $head[$h][1] = $langs->trans("BuyingPrices"); + $head[$h][2] = 'suppliers'; + $h++; + } } } diff --git a/htdocs/core/modules/modProduct.class.php b/htdocs/core/modules/modProduct.class.php index 090fdd59fa3..b32cc5a3cda 100644 --- a/htdocs/core/modules/modProduct.class.php +++ b/htdocs/core/modules/modProduct.class.php @@ -127,6 +127,14 @@ class modProduct extends DolibarrModules $this->rights[$r][4] = 'creer'; $r++; + $this->rights[$r][0] = 33; // id de la permission + $this->rights[$r][1] = 'Read prices products'; // libelle de la permission + $this->rights[$r][2] = 'w'; // type de la permission (deprecie a ce jour) + $this->rights[$r][3] = 0; // La permission est-elle une permission par defaut + $this->rights[$r][4] = 'product_advance'; + $this->rights[$r][5] = 'read_prices'; + $r++; + $this->rights[$r][0] = 34; // id de la permission $this->rights[$r][1] = 'Delete products'; // libelle de la permission $this->rights[$r][2] = 'd'; // type de la permission (deprecie a ce jour) diff --git a/htdocs/core/modules/modService.class.php b/htdocs/core/modules/modService.class.php index 8f4b697332b..7649e8d5b76 100644 --- a/htdocs/core/modules/modService.class.php +++ b/htdocs/core/modules/modService.class.php @@ -102,6 +102,14 @@ class modService extends DolibarrModules $this->rights[$r][4] = 'creer'; $r++; + $this->rights[$r][0] = 533; // id de la permission + $this->rights[$r][1] = 'Read prices services'; // libelle de la permission + $this->rights[$r][2] = 'w'; // type de la permission (deprecie a ce jour) + $this->rights[$r][3] = 0; // La permission est-elle une permission par defaut + $this->rights[$r][4] = 'service_advance'; + $this->rights[$r][5] = 'read_prices'; + $r++; + $this->rights[$r][0] = 534; // id de la permission $this->rights[$r][1] = 'Delete les services'; // libelle de la permission $this->rights[$r][2] = 'd'; // type de la permission (deprecie a ce jour) diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index c68a0ada7d6..f34d0a17e15 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -714,6 +714,7 @@ Permission27=Delete commercial proposals Permission28=Export commercial proposals Permission31=Read products Permission32=Create/modify products +Permission33=Read prices products Permission34=Delete products Permission36=See/manage hidden products Permission38=Export products @@ -875,6 +876,7 @@ Permission525=Access loan calculator Permission527=Export loans Permission531=Read services Permission532=Create/modify services +Permission533=Read prices services Permission534=Delete services Permission536=See/manage hidden services Permission538=Export services diff --git a/htdocs/product/list.php b/htdocs/product/list.php index 4cc79472ada..f66b1cb5b8b 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -291,7 +291,6 @@ if ($search_type == '0') { $result = restrictedArea($user, 'produit|service', '', '', '', '', '', 0); } - /* * Actions */ @@ -1360,6 +1359,11 @@ if ($resql) { } } + $usercancreadprice = getDolGlobalString('MAIN_USE_ADVANCED_PERMS')?$user->hasRight('product', 'product_advance', 'read_prices'):$user->hasRight('produit', 'lire'); + if ($product_static->isService()) { + $usercancreadprice = getDolGlobalString('MAIN_USE_ADVANCED_PERMS')?$user->hasRight('service', 'service_advance', 'read_prices'):$user->hasRight('service', 'lire'); + } + print ''; // Action column @@ -1622,7 +1626,7 @@ if ($resql) { // Sell price if (!empty($arrayfields['p.sellprice']['checked'])) { print ''; } // Cost price if (!empty($arrayfields['p.cost_price']['checked'])) { print ''; } From 845c20e5f7c8cab071effc54c604f81676774d6c Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Wed, 24 Aug 2022 21:49:33 +0200 Subject: [PATCH 807/826] Update llx_user.sql --- htdocs/install/mysql/tables/llx_user.sql | 154 +++++++++++------------ 1 file changed, 77 insertions(+), 77 deletions(-) diff --git a/htdocs/install/mysql/tables/llx_user.sql b/htdocs/install/mysql/tables/llx_user.sql index ae3715eb028..a47b40cb3d1 100644 --- a/htdocs/install/mysql/tables/llx_user.sql +++ b/htdocs/install/mysql/tables/llx_user.sql @@ -19,95 +19,95 @@ create table llx_user ( - rowid integer AUTO_INCREMENT PRIMARY KEY, - entity integer DEFAULT 1 NOT NULL, -- multi company id + rowid integer AUTO_INCREMENT PRIMARY KEY, + entity integer DEFAULT 1 NOT NULL, -- multi company id - ref_employee varchar(50), - ref_ext varchar(50), -- reference into an external system (not used by dolibarr) + ref_employee varchar(50), + ref_ext varchar(50), -- reference into an external system (not used by dolibarr) - admin smallint DEFAULT 0, -- user has admin profile + admin smallint DEFAULT 0, -- user has admin profile - employee tinyint DEFAULT 1, -- 1 if user is an employee - fk_establishment integer DEFAULT 0, + employee tinyint DEFAULT 1, -- 1 if user is an employee + fk_establishment integer DEFAULT 0, - datec datetime, - tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - fk_user_creat integer, - fk_user_modif integer, - login varchar(50) NOT NULL, - pass_encoding varchar(24), - pass varchar(128), - pass_crypted varchar(128), - pass_temp varchar(128), -- temporary password when asked for forget password or 'hashtoallowreset:YYYMMDDHHMMSS' (where date is max date of validity) - api_key varchar(128), -- key to use REST API by this user - gender varchar(10), - civility varchar(6), - lastname varchar(50), - firstname varchar(50), - address varchar(255), -- user personal address - zip varchar(25), -- zipcode - town varchar(50), -- town - fk_state integer DEFAULT 0, - fk_country integer DEFAULT 0, - birth date, -- birthday - job varchar(128), - office_phone varchar(20), - office_fax varchar(20), - user_mobile varchar(20), - personal_mobile varchar(20), - email varchar(255), - personal_email varchar(255), - signature text DEFAULT NULL, + datec datetime, -- date/time of creation + tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + fk_user_creat integer, -- user who created dataset + fk_user_modif integer, -- user who modified dataset + login varchar(50) NOT NULL, + pass_encoding varchar(24), + pass varchar(128), + pass_crypted varchar(128), + pass_temp varchar(128), -- temporary password when asked for forget password or 'hashtoallowreset:YYYMMDDHHMMSS' (where date is max date of validity) + api_key varchar(128), -- key to use REST API by this user + gender varchar(10), + civility varchar(6), + lastname varchar(50), + firstname varchar(50), + address varchar(255), -- user personal address + zip varchar(25), -- zipcode + town varchar(50), -- town + fk_state integer DEFAULT 0, + fk_country integer DEFAULT 0, + birth date, -- birthday + job varchar(128), + office_phone varchar(20), + office_fax varchar(20), + user_mobile varchar(20), + personal_mobile varchar(20), + email varchar(255), + personal_email varchar(255), + signature text DEFAULT NULL, - socialnetworks text DEFAULT NULL, -- json with socialnetworks + socialnetworks text DEFAULT NULL, -- json with socialnetworks --module_comm smallint DEFAULT 1, --module_compta smallint DEFAULT 1, - fk_soc integer NULL, -- id thirdparty if user linked to a company (external user) - fk_socpeople integer NULL, -- id contact origin if user linked to a contact - fk_member integer NULL, -- if member if suer linked to a member - fk_user integer NULL, -- Supervisor, hierarchic parent - fk_user_expense_validator integer NULL, - fk_user_holiday_validator integer NULL, + fk_soc integer NULL, -- id thirdparty if user linked to a company (external user) + fk_socpeople integer NULL, -- id contact origin if user linked to a contact + fk_member integer NULL, -- if member if user linked to a member + fk_user integer NULL, -- Supervisor, hierarchic parent + fk_user_expense_validator integer NULL, + fk_user_holiday_validator integer NULL, - idpers1 varchar(128), - idpers2 varchar(128), - idpers3 varchar(128), + idpers1 varchar(128), + idpers2 varchar(128), + idpers3 varchar(128), - note_public text, - note text DEFAULT NULL, - model_pdf varchar(255) DEFAULT NULL, - datelastlogin datetime, - datepreviouslogin datetime, - datelastpassvalidation datetime, -- last date we change password or we made a disconnect all - datestartvalidity datetime, - dateendvalidity datetime, - iplastlogin varchar(250), - ippreviouslogin varchar(250), - egroupware_id integer, - ldap_sid varchar(255) DEFAULT NULL, - openid varchar(255), - statut tinyint DEFAULT 1, - photo varchar(255), -- filename or url of photo - lang varchar(6), -- default language for communication. Note that language selected by user as interface language is savec into llx_user_param. - color varchar(6), - barcode varchar(255) DEFAULT NULL, - fk_barcode_type integer DEFAULT 0, - accountancy_code varchar(32) NULL, - nb_holiday integer DEFAULT 0, - thm double(24,8), - tjm double(24,8), + note_public text, + note text DEFAULT NULL, + model_pdf varchar(255) DEFAULT NULL, + datelastlogin datetime, + datepreviouslogin datetime, + datelastpassvalidation datetime, -- last date we change password or we made a disconnect all + datestartvalidity datetime, + dateendvalidity datetime, + iplastlogin varchar(250), + ippreviouslogin varchar(250), + egroupware_id integer, + ldap_sid varchar(255) DEFAULT NULL, + openid varchar(255), + statut tinyint DEFAULT 1, + photo varchar(255), -- filename or url of photo + lang varchar(6), -- default language for communication. Note that language selected by user as interface language is savec into llx_user_param. + color varchar(6), + barcode varchar(255) DEFAULT NULL, + fk_barcode_type integer DEFAULT 0, + accountancy_code varchar(32) NULL, + nb_holiday integer DEFAULT 0, + thm double(24,8), + tjm double(24,8), - salary double(24,8), -- denormalized value coming from llx_user_employment - salaryextra double(24,8), -- denormalized value coming from llx_user_employment - dateemployment date, -- denormalized value coming from llx_user_employment - dateemploymentend date, -- denormalized value coming from llx_user_employment - weeklyhours double(16,8), -- denormalized value coming from llx_user_employment + salary double(24,8), -- denormalized value coming from llx_user_employment + salaryextra double(24,8), -- denormalized value coming from llx_user_employment + dateemployment date, -- denormalized value coming from llx_user_employment + dateemploymentend date, -- denormalized value coming from llx_user_employment + weeklyhours double(16,8), -- denormalized value coming from llx_user_employment - import_key varchar(14), -- import key - default_range integer, - default_c_exp_tax_cat integer, + import_key varchar(14), -- import key + default_range integer, + default_c_exp_tax_cat integer, national_registration_number varchar(50), - fk_warehouse integer -- default warehouse os user + fk_warehouse integer -- default warehouse of user )ENGINE=innodb; From 1efca018d90512d8bd3e68932cfa158f230c2f64 Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Wed, 24 Aug 2022 23:13:27 +0200 Subject: [PATCH 808/826] Update list.php --- htdocs/commande/list.php | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index 710d5fa1941..b92140efa03 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -49,7 +49,7 @@ require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; // Load translation files required by the page -$langs->loadLangs(array("orders", 'sendings', 'deliveries', 'companies', 'compta', 'bills', 'stocks', 'products')); +$langs->loadLangs(array('orders', 'sendings', 'deliveries', 'companies', 'compta', 'bills', 'stocks', 'products')); $action = GETPOST('action', 'aZ09'); $massaction = GETPOST('massaction', 'alpha'); @@ -70,6 +70,7 @@ $search_dateorder_start = dol_mktime(0, 0, 0, GETPOST('search_dateorder_start_mo $search_dateorder_end = dol_mktime(23, 59, 59, GETPOST('search_dateorder_end_month', 'int'), GETPOST('search_dateorder_end_day', 'int'), GETPOST('search_dateorder_end_year', 'int')); $search_datedelivery_start = dol_mktime(0, 0, 0, GETPOST('search_datedelivery_start_month', 'int'), GETPOST('search_datedelivery_start_day', 'int'), GETPOST('search_datedelivery_start_year', 'int')); $search_datedelivery_end = dol_mktime(23, 59, 59, GETPOST('search_datedelivery_end_month', 'int'), GETPOST('search_datedelivery_end_day', 'int'), GETPOST('search_datedelivery_end_year', 'int')); + $search_product_category = GETPOST('search_product_category', 'int'); $search_ref = GETPOST('search_ref', 'alpha') != '' ?GETPOST('search_ref', 'alpha') : GETPOST('sref', 'alpha'); $search_ref_customer = GETPOST('search_ref_customer', 'alpha'); @@ -77,22 +78,25 @@ $search_company = GETPOST('search_company', 'alpha'); $search_company_alias = GETPOST('search_company_alias', 'alpha'); $search_town = GETPOST('search_town', 'alpha'); $search_zip = GETPOST('search_zip', 'alpha'); -$search_state = GETPOST("search_state", 'alpha'); -$search_country = GETPOST("search_country", 'int'); -$search_type_thirdparty = GETPOST("search_type_thirdparty", 'int'); +$search_state = GETPOST('search_state', 'alpha'); +$search_country = GETPOST('search_country', 'int'); +$search_type_thirdparty = GETPOST('search_type_thirdparty', 'int'); $sall = trim((GETPOST('search_all', 'alphanohtml') != '') ? GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml')); $socid = GETPOST('socid', 'int'); $search_user = GETPOST('search_user', 'int'); $search_sale = GETPOST('search_sale', 'int'); + $search_total_ht = GETPOST('search_total_ht', 'alpha'); $search_total_vat = GETPOST('search_total_vat', 'alpha'); $search_total_ttc = GETPOST('search_total_ttc', 'alpha'); $search_warehouse = GETPOST('search_warehouse', 'int'); + $search_multicurrency_code = GETPOST('search_multicurrency_code', 'alpha'); $search_multicurrency_tx = GETPOST('search_multicurrency_tx', 'alpha'); -$search_multicurrency_montant_ht = GETPOST('search_multicurrency_montant_ht', 'alpha'); +$search_multicurrency_montant_ht = GETPOST('search_multicurrency_montant_ht', 'alpha'); $search_multicurrency_montant_vat = GETPOST('search_multicurrency_montant_vat', 'alpha'); $search_multicurrency_montant_ttc = GETPOST('search_multicurrency_montant_ttc', 'alpha'); + $search_login = GETPOST('search_login', 'alpha'); $search_categ_cus = GETPOST("search_categ_cus", 'int'); $optioncss = GETPOST('optioncss', 'alpha'); @@ -103,10 +107,11 @@ $search_remove_btn = GETPOST('button_removefilter', 'alpha'); $search_project_ref = GETPOST('search_project_ref', 'alpha'); $search_project = GETPOST('search_project', 'alpha'); $search_shippable = GETPOST('search_shippable', 'aZ09'); -$search_fk_cond_reglement = GETPOST("search_fk_cond_reglement", 'int'); -$search_fk_shipping_method = GETPOST("search_fk_shipping_method", 'int'); -$search_fk_mode_reglement = GETPOST("search_fk_mode_reglement", 'int'); -$search_fk_input_reason = GETPOST("search_fk_input_reason", 'int'); + +$search_fk_cond_reglement = GETPOST('search_fk_cond_reglement', 'int'); +$search_fk_shipping_method = GETPOST('search_fk_shipping_method', 'int'); +$search_fk_mode_reglement = GETPOST('search_fk_mode_reglement', 'int'); +$search_fk_input_reason = GETPOST('search_fk_input_reason', 'int'); // Security check $id = (GETPOST('orderid') ?GETPOST('orderid', 'int') : GETPOST('id', 'int')); From b4663a41f4b2a9c4df42cca3050c4a29430e09ab Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Wed, 24 Aug 2022 23:17:18 +0200 Subject: [PATCH 809/826] Update card.php --- htdocs/don/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/don/card.php b/htdocs/don/card.php index a622167819e..c867418cfbb 100644 --- a/htdocs/don/card.php +++ b/htdocs/don/card.php @@ -44,7 +44,7 @@ if (!empty($conf->project->enabled)) { } require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; -$langs->loadLangs(array("bills", "companies", "donations", "users")); +$langs->loadLangs(array('bills', 'companies', 'donations', 'users')); $id = GETPOST('rowid') ?GETPOST('rowid', 'int') : GETPOST('id', 'int'); $action = GETPOST('action', 'aZ09'); From 6d3dca90b43ed1f9171cdcb9b98a88796ea45e66 Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Wed, 24 Aug 2022 23:18:56 +0200 Subject: [PATCH 810/826] Update document.php --- htdocs/don/document.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/don/document.php b/htdocs/don/document.php index 030ca5cb085..1bb371c7812 100644 --- a/htdocs/don/document.php +++ b/htdocs/don/document.php @@ -40,7 +40,7 @@ if (!empty($conf->project->enabled)) { } // Load translation files required by the page -$langs->loadLangs(array("companies", "other", "donations")); +$langs->loadLangs(array('companies', 'other', 'donations')); $id = GETPOST('id', 'int'); $ref = GETPOST('ref', 'alpha'); From 6e36fef1769548ed05dbd35765bad5e60cb0f777 Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Wed, 24 Aug 2022 23:22:18 +0200 Subject: [PATCH 811/826] Update info.php --- htdocs/don/info.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/htdocs/don/info.php b/htdocs/don/info.php index f326972f782..29d8f129036 100644 --- a/htdocs/don/info.php +++ b/htdocs/don/info.php @@ -30,7 +30,7 @@ if (!empty($conf->project->enabled)) { require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; } -$langs->load("donations"); +$langs->load('donations'); $id = GETPOST('id', 'int'); $ref = GETPOST('ref', 'alpha'); @@ -45,17 +45,22 @@ $result = restrictedArea($user, 'don', $id, ''); $object = new Don($db); $object->fetch($id); + + /* * Actions */ + if ($action == 'classin' && $user->rights->don->creer) { $object->fetch($id); $object->setProject($projectid); } + /* * View */ + $title = $langs->trans('Donation')." - ".$langs->trans('Info'); $help_url = 'EN:Module_Donations|FR:Module_Dons|ES:Módulo_Donaciones|DE:Modul_Spenden'; From 7fcf6874dc8d22812d763d02644743e355ab51cd Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Wed, 24 Aug 2022 23:23:48 +0200 Subject: [PATCH 812/826] Update list.php --- htdocs/don/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/don/list.php b/htdocs/don/list.php index 891f7e6877b..68f8ab0bbea 100644 --- a/htdocs/don/list.php +++ b/htdocs/don/list.php @@ -32,7 +32,7 @@ if (!empty($conf->project->enabled)) { } // Load translation files required by the page -$langs->loadLangs(array("companies", "donations")); +$langs->loadLangs(array('companies', 'donations')); $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'sclist'; From e97d7aa86b6d67f9f9f12964829f941bfe3741b3 Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Wed, 24 Aug 2022 23:25:15 +0200 Subject: [PATCH 813/826] Update note.php --- htdocs/don/note.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/don/note.php b/htdocs/don/note.php index 8e1b5192ee2..0b1c555e772 100644 --- a/htdocs/don/note.php +++ b/htdocs/don/note.php @@ -35,7 +35,7 @@ if (!empty($conf->project->enabled)) { } // Load translation files required by the page -$langs->loadLangs(array("companies", "bills", "donations")); +$langs->loadLangs(array('companies', 'bills', 'donations')); $id = (GETPOST('id', 'int') ?GETPOST('id', 'int') : GETPOST('facid', 'int')); // For backward compatibility $ref = GETPOST('ref', 'alpha'); @@ -60,6 +60,7 @@ $permissionnote = $user->rights->don->creer; // Used by the include of actions_s /* * Actions */ + $reshook = $hookmanager->executeHooks('doActions', array(), $object, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); @@ -73,6 +74,7 @@ if ($action == 'classin' && $user->rights->don->creer) { $object->setProject($projectid); } + /* * View */ From 899aa81b058bf0d90ed32eb7b1e4f9d4ae81fe0b Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Wed, 24 Aug 2022 23:27:19 +0200 Subject: [PATCH 814/826] Update index.php --- htdocs/ecm/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/ecm/index.php b/htdocs/ecm/index.php index aec4b54bc6c..ceaf74f533d 100644 --- a/htdocs/ecm/index.php +++ b/htdocs/ecm/index.php @@ -32,7 +32,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/treeview.lib.php'; require_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmdirectory.class.php'; // Load translation files required by the page -$langs->loadLangs(array("ecm", "companies", "other", "users", "orders", "propal", "bills", "contracts")); +$langs->loadLangs(array('ecm', 'companies', 'other', 'users', 'orders', 'propal', 'bills', 'contracts')); // Get parameters $socid = GETPOST('socid', 'int'); From dedf039f3f00c9795c54944727d3b98899e555f3 Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Wed, 24 Aug 2022 23:35:16 +0200 Subject: [PATCH 815/826] Update account.php --- htdocs/accountancy/admin/account.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/accountancy/admin/account.php b/htdocs/accountancy/admin/account.php index f818e9a0a1a..d26afd31331 100644 --- a/htdocs/accountancy/admin/account.php +++ b/htdocs/accountancy/admin/account.php @@ -30,7 +30,7 @@ require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingaccount.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php'; // Load translation files required by the page -$langs->loadLangs(array("compta", "bills", "admin", "accountancy", "salaries")); +$langs->loadLangs(array('accountancy', 'admin', 'bills', 'compta', 'salaries')); $mesg = ''; $action = GETPOST('action', 'aZ09'); From c9693d266fb803445f0f5ba80896ee2784d28653 Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Wed, 24 Aug 2022 23:38:05 +0200 Subject: [PATCH 816/826] Update accountmodel.php --- htdocs/accountancy/admin/accountmodel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/accountancy/admin/accountmodel.php b/htdocs/accountancy/admin/accountmodel.php index 201898dedd1..c1bc435145f 100644 --- a/htdocs/accountancy/admin/accountmodel.php +++ b/htdocs/accountancy/admin/accountmodel.php @@ -44,7 +44,7 @@ if (isModEnabled('accounting')) { } // Load translation files required by the page -$langs->loadLangs(array("errors", "admin", "companies", "resource", "holiday", "compta", "accountancy", "hrm")); +$langs->loadLangs(array('accountancy', 'admin', 'companies', 'compta', 'errors', 'holiday', 'hrm', 'resource')); $action = GETPOST('action', 'aZ09') ?GETPOST('action', 'aZ09') : 'view'; $confirm = GETPOST('confirm', 'alpha'); From f5e8b6b0b2018901f4c6cdacca6433e81605368a Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Wed, 24 Aug 2022 23:39:27 +0200 Subject: [PATCH 817/826] Update card.php --- htdocs/accountancy/admin/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/accountancy/admin/card.php b/htdocs/accountancy/admin/card.php index 5c1044380f9..7876712fe51 100644 --- a/htdocs/accountancy/admin/card.php +++ b/htdocs/accountancy/admin/card.php @@ -32,7 +32,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php'; $error = 0; // Load translation files required by the page -$langs->loadLangs(array("bills", "accountancy", "compta")); +$langs->loadLangs(array('accountancy', 'bills', 'compta')); $action = GETPOST('action', 'aZ09'); $backtopage = GETPOST('backtopage', 'alpha'); From 17c404e9407abd78b3c72711ca1af9ae1311af18 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 24 Aug 2022 23:41:26 +0200 Subject: [PATCH 818/826] Support Initialisation vector in crypt/decrypt --- htdocs/core/lib/security.lib.php | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php index 5678d1553aa..62c0a22e76b 100644 --- a/htdocs/core/lib/security.lib.php +++ b/htdocs/core/lib/security.lib.php @@ -124,8 +124,14 @@ function dolEncrypt($chain, $key = '', $ciphering = "AES-256-CTR") if (!function_exists('openssl_encrypt')) { return $chain; } else { - $newchain = openssl_encrypt($chain, $ciphering, $key); - return 'dolcrypt:'.$ciphering.':'.$newchain; + $ivlen = openssl_cipher_iv_length($ciphering); + if ($ivlen < 0 || $ivlen > 32) { + $ivlen = 32; + } + $ivseed = mt_rand(0, pow(2, $ivlen) - 1); + + $newchain = openssl_encrypt($chain, $ciphering, $key, null, $ivseed); + return 'dolcrypt:'.$ciphering.':'.$ivseed.':'.$newchain; } } @@ -154,7 +160,12 @@ function dolDecrypt($chain, $key = '') if (preg_match('/^dolcrypt:([^:]+):(.+)$/', $chain, $reg)) { $ciphering = $reg[1]; if (function_exists('openssl_decrypt')) { - $newchain = openssl_decrypt($reg[2], $ciphering, $key); + $tmpexplode = explode(':', $reg[2]); + if (!empty($tmpexplode[1]) && is_numeric($tmpexplode[0])) { + $newchain = openssl_decrypt($tmpexplode[1], $ciphering, $key, null, $tmpexplode[0]); + } else { + $newchain = openssl_decrypt($tmpexplode[0], $ciphering, $key, null, null); + } } else { $newchain = 'Error function openssl_decrypt() not available'; } From a7f9ec159b19a7ef5f889e0a212a294a7b02c827 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 25 Aug 2022 02:04:48 +0200 Subject: [PATCH 819/826] Support Initialisation vector in crypt/decrypt --- htdocs/core/lib/security.lib.php | 34 ++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php index 62c0a22e76b..bc0dd522d1b 100644 --- a/htdocs/core/lib/security.lib.php +++ b/htdocs/core/lib/security.lib.php @@ -91,6 +91,21 @@ function dol_decode($chain, $key = '1') return $chain; } +/** + * Return a string of random bytes (hexa string) with length = $length fro cryptographic purposes. + * + * @param int $length Length of random string + * @return string Random string + */ +function dolGetRandomBytes($length) +{ + if (function_exists('random_bytes')) { // Available with PHP 7 only. + return bin2hex(random_bytes((int) floor($length / 2))); // the bin2hex will double the number of bytes so we take length / 2 + } + + return bin2hex(openssl_random_pseudo_bytes((int) floor($length / 2))); // the bin2hex will double the number of bytes so we take length / 2. May be very slow on Windows. +} + /** * Encode a string with a symetric encryption. Used to encrypt sensitive data into database. * Note: If a backup is restored onto another instance with a different $dolibarr_main_instance_unique_id, then decoded value will differ. @@ -121,17 +136,20 @@ function dolEncrypt($chain, $key = '', $ciphering = "AES-256-CTR") $newchain = $chain; - if (!function_exists('openssl_encrypt')) { - return $chain; - } else { - $ivlen = openssl_cipher_iv_length($ciphering); - if ($ivlen < 0 || $ivlen > 32) { - $ivlen = 32; + if (function_exists('openssl_encrypt')) { + $ivlen = 16; + if (function_exists('openssl_cipher_iv_length')) { + $ivlen = openssl_cipher_iv_length($ciphering); } - $ivseed = mt_rand(0, pow(2, $ivlen) - 1); + if ($ivlen === false || $ivlen < 1 || $ivlen > 32) { + $ivlen = 16; + } + $ivseed = dolGetRandomBytes($ivlen); $newchain = openssl_encrypt($chain, $ciphering, $key, null, $ivseed); return 'dolcrypt:'.$ciphering.':'.$ivseed.':'.$newchain; + } else { + return $chain; } } @@ -161,7 +179,7 @@ function dolDecrypt($chain, $key = '') $ciphering = $reg[1]; if (function_exists('openssl_decrypt')) { $tmpexplode = explode(':', $reg[2]); - if (!empty($tmpexplode[1]) && is_numeric($tmpexplode[0])) { + if (!empty($tmpexplode[1]) && is_string($tmpexplode[0])) { $newchain = openssl_decrypt($tmpexplode[1], $ciphering, $key, null, $tmpexplode[0]); } else { $newchain = openssl_decrypt($tmpexplode[0], $ciphering, $key, null, null); From ff2ae4069177efe222f275524f42db2f24ecbba9 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 25 Aug 2022 02:52:54 +0200 Subject: [PATCH 820/826] Fix default value for recipient --- htdocs/core/tpl/card_presend.tpl.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/tpl/card_presend.tpl.php b/htdocs/core/tpl/card_presend.tpl.php index 0376a5e85c9..c0e64a513ab 100644 --- a/htdocs/core/tpl/card_presend.tpl.php +++ b/htdocs/core/tpl/card_presend.tpl.php @@ -198,7 +198,7 @@ if ($action == 'presend') { } $formmail->withto = $liste; - $formmail->withtofree = (GETPOSTISSET('sendto') ? (GETPOST('sendto', 'alphawithlgt') ? GETPOST('sendto', 'alphawithlgt') : '1') : '1'); + $formmail->withtofree = (GETPOST('sendto', 'alphawithlgt') ? GETPOST('sendto', 'alphawithlgt') : '1'); $formmail->withtocc = $liste; $formmail->withtoccc = getDolGlobalString('MAIN_EMAIL_USECCC'); $formmail->withtopic = $topicmail; From 198ff218906b8ad2f9916ac87b2ced7ab8519d24 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Thu, 25 Aug 2022 08:32:18 +0200 Subject: [PATCH 821/826] forgot --- htdocs/product/list.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/htdocs/product/list.php b/htdocs/product/list.php index f66b1cb5b8b..2c3351b69ac 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -1787,7 +1787,9 @@ if ($resql) { if ($obj->seuil_stock_alerte != '' && $product_static->stock_reel < (float) $obj->seuil_stock_alerte) { print img_warning($langs->trans("StockLowerThanLimit", $obj->seuil_stock_alerte)).' '; } - print price(price2num($product_static->stock_reel, 'MS')); + if ($usercancreadprice) { + print price(price2num($product_static->stock_reel, 'MS')); + } } print ''; if (!$i) { @@ -1801,7 +1803,9 @@ if ($resql) { if ($obj->seuil_stock_alerte != '' && $product_static->stock_theorique < (float) $obj->seuil_stock_alerte) { print img_warning($langs->trans("StockLowerThanLimit", $obj->seuil_stock_alerte)).' '; } - print price(price2num($product_static->stock_theorique, 'MS')); + if ($usercancreadprice) { + print price(price2num($product_static->stock_theorique, 'MS')); + } } print ''; if (!$i) { From b9b3e5ca29ead430d1876316b62f62e4e27d6e6f Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Thu, 25 Aug 2022 08:51:39 +0200 Subject: [PATCH 822/826] Correction droit --- htdocs/core/lib/product.lib.php | 2 +- htdocs/product/list.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/lib/product.lib.php b/htdocs/core/lib/product.lib.php index 5b1d5ba91d0..1bf7955bbd9 100644 --- a/htdocs/core/lib/product.lib.php +++ b/htdocs/core/lib/product.lib.php @@ -38,7 +38,7 @@ function product_prepare_head($object) $langs->load("products"); $label = $langs->trans('Product'); - $usercancreadprice = getDolGlobalString('MAIN_USE_ADVANCED_PERMS')?$user->hasRight('product', 'product_advance', 'read_prices'):$user->hasRight('produit', 'lire'); + $usercancreadprice = getDolGlobalString('MAIN_USE_ADVANCED_PERMS')?$user->hasRight('product', 'product_advance', 'read_prices'):$user->hasRight('product', 'lire'); if ($object->isService()) { $label = $langs->trans('Service'); diff --git a/htdocs/product/list.php b/htdocs/product/list.php index 2c3351b69ac..ae0e28576d5 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -1359,7 +1359,7 @@ if ($resql) { } } - $usercancreadprice = getDolGlobalString('MAIN_USE_ADVANCED_PERMS')?$user->hasRight('product', 'product_advance', 'read_prices'):$user->hasRight('produit', 'lire'); + $usercancreadprice = getDolGlobalString('MAIN_USE_ADVANCED_PERMS')?$user->hasRight('product', 'product_advance', 'read_prices'):$user->hasRight('product', 'lire'); if ($product_static->isService()) { $usercancreadprice = getDolGlobalString('MAIN_USE_ADVANCED_PERMS')?$user->hasRight('service', 'service_advance', 'read_prices'):$user->hasRight('service', 'lire'); } From 5e910361ac60fd51d919ac93aab4baad0b808124 Mon Sep 17 00:00:00 2001 From: bagtaib Date: Thu, 25 Aug 2022 09:57:18 +0100 Subject: [PATCH 823/826] fix fetch errror --- htdocs/public/partnership/new.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/htdocs/public/partnership/new.php b/htdocs/public/partnership/new.php index 9026aacce4d..b9332b32366 100644 --- a/htdocs/public/partnership/new.php +++ b/htdocs/public/partnership/new.php @@ -221,8 +221,14 @@ if (empty($reshook) && $action == 'add') { $partnership->note_private = GETPOST('note_private'); $partnership->date_creation = dol_now(); $partnership->date_partnership_start = dol_now(); - $partnership->fk_type = $partnershipt->fetch(0, 'default'); $partnership->fk_user_creat=$user->id; + + $partnershipt->fetch(0, 'default'); + if ($partnershipt->id > 0) { + $partnership->fk_type = $partnershipt->id; + } + + //$partnership->firstname = GETPOST('firstname'); //$partnership->lastname = GETPOST('lastname'); //$partnership->address = GETPOST('address'); From d6cc6f25769c7cb3afc2cbd09f90270ba5fab3d3 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 25 Aug 2022 11:46:44 +0200 Subject: [PATCH 824/826] Change sql creation of a partnership from a public page --- htdocs/install/mysql/migration/16.0.0-17.0.0.sql | 3 +++ .../install/mysql/tables/llx_partnership-partnership.sql | 2 +- htdocs/public/partnership/new.php | 8 ++++---- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql index 9b584448bc3..c5d93a70e1f 100644 --- a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql +++ b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql @@ -55,6 +55,9 @@ ALTER TABLE llx_user DROP COLUMN idpers3; -- v17 +-- VMYSQL4.3 ALTER TABLE llx_partnership MODIFY COLUMN fk_user_creat integer NULL; +-- VPGSQL8.2 ALTER TABLE llx_partnership ALTER COLUMN fk_user_creat DROP NOT NULL; + UPDATE llx_const set name = 'ADHERENT_MAILMAN_ADMIN_PASSWORD' WHERE name = 'ADHERENT_MAILMAN_ADMINPW'; ALTER TABLE llx_oauth_token ADD COLUMN state text after tokenstring; diff --git a/htdocs/install/mysql/tables/llx_partnership-partnership.sql b/htdocs/install/mysql/tables/llx_partnership-partnership.sql index 8f83e2e82e5..1c32ff5ea0f 100644 --- a/htdocs/install/mysql/tables/llx_partnership-partnership.sql +++ b/htdocs/install/mysql/tables/llx_partnership-partnership.sql @@ -28,7 +28,7 @@ CREATE TABLE llx_partnership( entity integer DEFAULT 1 NOT NULL, -- multi company id, 0 = all reason_decline_or_cancel text NULL, date_creation datetime NOT NULL, - fk_user_creat integer NOT NULL, + fk_user_creat integer NULL, -- can be null if created from public page tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, fk_user_modif integer, note_private text, diff --git a/htdocs/public/partnership/new.php b/htdocs/public/partnership/new.php index b9332b32366..9178d37ddc6 100644 --- a/htdocs/public/partnership/new.php +++ b/htdocs/public/partnership/new.php @@ -221,13 +221,13 @@ if (empty($reshook) && $action == 'add') { $partnership->note_private = GETPOST('note_private'); $partnership->date_creation = dol_now(); $partnership->date_partnership_start = dol_now(); - $partnership->fk_user_creat=$user->id; + $partnership->fk_user_creat = 0; - $partnershipt->fetch(0, 'default'); + /*$partnershipt->fetch(0, 'default'); if ($partnershipt->id > 0) { $partnership->fk_type = $partnershipt->id; - } - + }*/ + $partnership->fk_type = GETPOST('partnershiptype', 'int'); //$partnership->firstname = GETPOST('firstname'); //$partnership->lastname = GETPOST('lastname'); From 4a8b7dbecf59b01f4bb32f5050a82bab95e08049 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 25 Aug 2022 12:07:44 +0200 Subject: [PATCH 825/826] Add ip on table of partnership --- htdocs/install/mysql/migration/16.0.0-17.0.0.sql | 2 ++ htdocs/install/mysql/tables/llx_partnership-partnership.sql | 1 + 2 files changed, 3 insertions(+) diff --git a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql index c5d93a70e1f..805cfea260c 100644 --- a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql +++ b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql @@ -58,6 +58,8 @@ ALTER TABLE llx_user DROP COLUMN idpers3; -- VMYSQL4.3 ALTER TABLE llx_partnership MODIFY COLUMN fk_user_creat integer NULL; -- VPGSQL8.2 ALTER TABLE llx_partnership ALTER COLUMN fk_user_creat DROP NOT NULL; +ALTER TABLE llx_partnership ADD COLUMN ip varchar(250); + UPDATE llx_const set name = 'ADHERENT_MAILMAN_ADMIN_PASSWORD' WHERE name = 'ADHERENT_MAILMAN_ADMINPW'; ALTER TABLE llx_oauth_token ADD COLUMN state text after tokenstring; diff --git a/htdocs/install/mysql/tables/llx_partnership-partnership.sql b/htdocs/install/mysql/tables/llx_partnership-partnership.sql index 1c32ff5ea0f..d023e67920e 100644 --- a/htdocs/install/mysql/tables/llx_partnership-partnership.sql +++ b/htdocs/install/mysql/tables/llx_partnership-partnership.sql @@ -37,6 +37,7 @@ CREATE TABLE llx_partnership( url_to_check varchar(255), -- url to check to find a specific keyword (defined into llx_c_partnership) to keep status of partnership valid count_last_url_check_error integer DEFAULT '0', -- last result of check of keyword into url last_check_backlink datetime NULL, -- date of last check of keyword into url + ip varchar(250), import_key varchar(14), model_pdf varchar(255) ) ENGINE=innodb; \ No newline at end of file From eeba47b933b3523b5db46ebac98ffdc5764ef639 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 25 Aug 2022 12:09:56 +0200 Subject: [PATCH 826/826] Add ip on table llx_adherent (for public submission page) --- htdocs/install/mysql/migration/16.0.0-17.0.0.sql | 1 + htdocs/install/mysql/tables/llx_adherent.sql | 1 + 2 files changed, 2 insertions(+) diff --git a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql index 805cfea260c..5f297619c50 100644 --- a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql +++ b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql @@ -59,6 +59,7 @@ ALTER TABLE llx_user DROP COLUMN idpers3; -- VPGSQL8.2 ALTER TABLE llx_partnership ALTER COLUMN fk_user_creat DROP NOT NULL; ALTER TABLE llx_partnership ADD COLUMN ip varchar(250); +ALTER TABLE llx_adherent ADD COLUMN ip varchar(250); UPDATE llx_const set name = 'ADHERENT_MAILMAN_ADMIN_PASSWORD' WHERE name = 'ADHERENT_MAILMAN_ADMINPW'; diff --git a/htdocs/install/mysql/tables/llx_adherent.sql b/htdocs/install/mysql/tables/llx_adherent.sql index be29e82d013..a91de4c65df 100644 --- a/htdocs/install/mysql/tables/llx_adherent.sql +++ b/htdocs/install/mysql/tables/llx_adherent.sql @@ -82,5 +82,6 @@ create table llx_adherent fk_user_mod integer, fk_user_valid integer, canvas varchar(32), -- type of canvas if used (null by default) + ip varchar(250), -- ip used to create record (for public membership submission page) import_key varchar(14) -- Import key )ENGINE=innodb;
'; print ''; - print ''; + print ''; print ''; } else { print ''; - print ''; + print ''; } print ''; print "'; - print ''; + print ''; print ''; } else { print ''; - print ''; + print ''; } if ($conf->use_javascript_ajax) { From 422fd2871e77b933291dbdeeebdd2d2a25a0a251 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Wed, 24 Aug 2022 09:59:08 +0200 Subject: [PATCH 785/826] FIX php8 compatibility --- htdocs/admin/dav.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/admin/dav.php b/htdocs/admin/dav.php index 698bb187d67..d9825ad6886 100644 --- a/htdocs/admin/dav.php +++ b/htdocs/admin/dav.php @@ -185,13 +185,13 @@ $message .= ajax_autoselect('webdavpublicurl'); $message .= '
'; if (!empty($conf->global->DAV_ALLOW_PUBLIC_DIR)) { - $urlEntity = (!empty($conf->multicompany->enabled) ? '?entity='.$conf->entity : ''); - $url = ''.$urlwithroot.'/dav/fileserver.php/public/'.$urlEntity.''; + $urlEntity = (isModEnabled('multicompany') ? '?entity=' . $conf->entity : ''); + $url = '' . $urlwithroot . '/dav/fileserver.php/public/' . $urlEntity . ''; - $message .= img_picto('', 'globe').' '.str_replace('{url}', $url, $langs->trans("WebDavServer", 'WebDAV public', '')); - $message .= '
'; - print ''; // We see environment, but to change it we must switch on other entity + print ''; // We see environment, but to change it we must switch on other entity print ''; - print ''; + print ''; print ''; From c9d24528469128128c56cc632b240a4a1ec753d9 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Wed, 24 Aug 2022 10:02:06 +0200 Subject: [PATCH 787/826] FIX php8 compatibility --- htdocs/admin/delais.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/htdocs/admin/delais.php b/htdocs/admin/delais.php index 2ae77b03d07..af8fed1c197 100644 --- a/htdocs/admin/delais.php +++ b/htdocs/admin/delais.php @@ -172,7 +172,7 @@ if (!isset($conf->global->MAIN_DELAY_ORDERS_TO_PROCESS)) { if ($action == 'update') { foreach ($modules as $module => $delays) { - if (!empty($conf->$module->enabled)) { + if (isModEnabled('module')) { foreach ($delays as $delay) { if (GETPOST($delay['code']) != '') { dolibarr_set_const($db, $delay['code'], GETPOST($delay['code']), 'chaine', 0, '', $conf->entity); @@ -226,13 +226,13 @@ if ($action == 'edit') { print ''.$langs->trans("LateWarningAfter").'
'.img_object('', $delay['img']).''.$langs->trans('Delays_'.$delay['code']).''; - print ' '.$langs->trans("days").'
' . img_object('', $delay['img']) . '' . $langs->trans('Delays_' . $delay['code']) . ''; + print ' ' . $langs->trans("days") . '
'.$langs->trans("DelaysOfToleranceBeforeWarning").''.$langs->trans("Value").'
'.img_object('', $delay['img']).''.$langs->trans('Delays_'.$delay['code']).''.$value.' '.$langs->trans("days").'
' . img_object('', $delay['img']) . '' . $langs->trans('Delays_' . $delay['code']) . '' . $value . ' ' . $langs->trans("days") . '
'; print $langs->trans('ProjectIsRequiredOnExpenseReports'); print ''; From 1c5feaf6b0112d209293f2e223d43e0ca854d0d4 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Wed, 24 Aug 2022 10:07:02 +0200 Subject: [PATCH 790/826] FIX php8 compatibility --- htdocs/admin/knowledgemanagement.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/admin/knowledgemanagement.php b/htdocs/admin/knowledgemanagement.php index 041216014b0..b1710a53839 100644 --- a/htdocs/admin/knowledgemanagement.php +++ b/htdocs/admin/knowledgemanagement.php @@ -208,12 +208,12 @@ if ($action == 'edit') { print ''; if ($val['type'] == 'textarea') { - print '\n"; - } elseif ($val['type']== 'html') { + } elseif ($val['type'] == 'html') { require_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php'; - $doleditor = new DolEditor($constname, $conf->global->{$constname}, '', 160, 'dolibarr_notes', '', false, false, $conf->fckeditor->enabled, ROWS_5, '90%'); + $doleditor = new DolEditor($constname, $conf->global->{$constname}, '', 160, 'dolibarr_notes', '', false, false, isModEnabled('fckeditor'), ROWS_5, '90%'); $doleditor->Create(); } elseif ($val['type'] == 'yesno') { print $form->selectyesno($constname, $conf->global->{$constname}, 1); From a4fbfa23eb5347932c185bf53bb0eae57df73978 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Wed, 24 Aug 2022 10:10:03 +0200 Subject: [PATCH 791/826] FIX php8 compatibility --- htdocs/admin/hrm.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/htdocs/admin/hrm.php b/htdocs/admin/hrm.php index cfe40c006b7..c568e6de39c 100644 --- a/htdocs/admin/hrm.php +++ b/htdocs/admin/hrm.php @@ -492,14 +492,14 @@ if ($action == 'edit') { print ''; if ($val['type'] == 'textarea') { - print '\n"; - } elseif ($val['type']== 'integer') { - print '' . "\n"; - } elseif ($val['type']== 'html') { + } elseif ($val['type'] == 'integer') { + print '' . "\n"; + } elseif ($val['type'] == 'html') { require_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php'; - $doleditor = new DolEditor($constname, $conf->global->{$constname}, '', 160, 'dolibarr_notes', '', false, false, $conf->fckeditor->enabled, ROWS_5, '90%'); + $doleditor = new DolEditor($constname, $conf->global->{$constname}, '', 160, 'dolibarr_notes', '', false, false, isModEnabled('fckeditor'), ROWS_5, '90%'); $doleditor->Create(); } elseif ($val['type'] == 'yesno') { print $form->selectyesno($constname, $conf->global->{$constname}, 1); @@ -532,25 +532,25 @@ if ($action == 'edit') { print img_picto('', 'category', 'class="pictofixedwidth"'); print $formother->select_categories($tmp[1], $conf->global->{$constname}, $constname, 0, $langs->trans('CustomersProspectsCategoriesShort')); } elseif (preg_match('/thirdparty_type/', $val['type'])) { - require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; + require_once DOL_DOCUMENT_ROOT . '/core/class/html.formcompany.class.php'; $formcompany = new FormCompany($db); print $formcompany->selectProspectCustomerType($conf->global->{$constname}, $constname); } elseif ($val['type'] == 'securekey') { - print ''; + print ''; if (!empty($conf->use_javascript_ajax)) { - print ' '.img_picto($langs->trans('Generate'), 'refresh', 'id="generate_token'.$constname.'" class="linkobject"'); + print ' ' . img_picto($langs->trans('Generate'), 'refresh', 'id="generate_token' . $constname . '" class="linkobject"'); } // Add button to autosuggest a key - include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; - print dolJSToSetRandomPassword($constname, 'generate_token'.$constname); + include_once DOL_DOCUMENT_ROOT . '/core/lib/security2.lib.php'; + print dolJSToSetRandomPassword($constname, 'generate_token' . $constname); } elseif ($val['type'] == 'product') { - if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) { + if (isModEnabled('product') || isModEnabled('service')) { $selected = (empty($conf->global->$constname) ? '' : $conf->global->$constname); $form->select_produits($selected, $constname, '', 0); } } else { - print ''; + print ''; } print '
'.$langs->trans("LDAPDnContactActive").''; +if (isModEnabled('societe')) { + print '
' . $langs->trans("LDAPDnContactActive") . ''; print $formldap->selectLdapDnSynchroActive(getDolGlobalInt('LDAP_CONTACT_ACTIVE'), 'activecontact', array(Ldap::SYNCHRO_LDAP_TO_DOLIBARR)); - print ''.$langs->trans("LDAPDnContactActiveExample").'
' . $langs->trans("LDAPDnContactActiveExample") . '
'.$langs->trans("LDAPDnMemberActive").''; +if (isModEnabled('adherent')) { + print '
' . $langs->trans("LDAPDnMemberActive") . ''; print $formldap->selectLdapDnSynchroActive(getDolGlobalInt('LDAP_MEMBER_ACTIVE'), 'activemembers', array(), 2); - print ''.$langs->trans("LDAPDnMemberActiveExample").'
' . $langs->trans("LDAPDnMemberActiveExample") . '
'.$langs->trans("LDAPDnMemberTypeActive").''; +if (isModEnabled('adherent')) { + print '
' . $langs->trans("LDAPDnMemberTypeActive") . ''; print $formldap->selectLdapDnSynchroActive(getDolGlobalInt('LDAP_MEMBER_TYPE_ACTIVE'), 'activememberstypes', array(), 2); - print ''.$langs->trans("LDAPDnMemberTypeActiveExample").'
' . $langs->trans("LDAPDnMemberTypeActiveExample") . '
'; // SuperAdministrator access only - if (empty($conf->multicompany->enabled) || ($user->admin && !$user->entity)) { - print ''; - print ''; - print ''.$langs->trans("SeeLocalSendMailSetup").''; - print ' '.$langs->trans("SeeLinkToOnlineDocumentation").''; + if (!isModEnabled('multicompany') || ($user->admin && !$user->entity)) { + print ''; + print ''; + print '' . $langs->trans("SeeLocalSendMailSetup") . ''; + print ' ' . $langs->trans("SeeLinkToOnlineDocumentation") . ''; } else { $text = !empty($mainserver) ? $mainserver : $smtpserver; $htmltext = $langs->trans("ContactSuperAdminForChange"); print $form->textwithpicto($text, $htmltext, 1, 'superadmin'); - print ''; + print ''; } print ''; // SuperAdministrator access only - if (empty($conf->multicompany->enabled) || ($user->admin && !$user->entity)) { - print ''; - print ''; - print ''.$langs->trans("SeeLocalSendMailSetup").''; + if (!isModEnabled('multicompany') || ($user->admin && !$user->entity)) { + print ''; + print ''; + print '' . $langs->trans("SeeLocalSendMailSetup") . ''; } else { $text = (!empty($mainport) ? $mainport : $smtpport); $htmltext = $langs->trans("ContactSuperAdminForChange"); print $form->textwithpicto($text, $htmltext, 1, 'superadmin'); - print ''; + print ''; } } print '
'.$langs->trans("MAIN_MAIL_SMTPS_ID").''; + print '
' . $langs->trans("MAIN_MAIL_SMTPS_ID") . ''; // SuperAdministrator access only - if (empty($conf->multicompany->enabled) || ($user->admin && !$user->entity)) { - print ''; + if (!isModEnabled('multicompany') || ($user->admin && !$user->entity)) { + print ''; } else { $htmltext = $langs->trans("ContactSuperAdminForChange"); print $form->textwithpicto($conf->global->MAIN_MAIL_SMTPS_ID_EMAILING, $htmltext, 1, 'superadmin'); - print ''; + print ''; } print '
'.$langs->trans("MAIN_MAIL_SMTPS_PW").''; + print '
' . $langs->trans("MAIN_MAIL_SMTPS_PW") . ''; // SuperAdministrator access only - if (empty($conf->multicompany->enabled) || ($user->admin && !$user->entity)) { - print ''; + if (!isModEnabled('multicompany') || ($user->admin && !$user->entity)) { + print ''; } else { $htmltext = $langs->trans("ContactSuperAdminForChange"); print $form->textwithpicto($conf->global->MAIN_MAIL_SMTPS_PW_EMAILING, $htmltext, 1, 'superadmin'); - print ''; + print ''; } print '
'; - if (!empty($conf->accounting->enabled)) { + if (isModEnabled('accounting')) { print $formaccounting->select_account(getDolGlobalString($key), $key, 1, '', 1, 1); } else { - print ''; + print ''; } print '
'.$obj->name.'
'.dol_escape_htmltag($obj->name).''; print ''; print ''; print ''; - print ''; + print ''; print ''; - print ''; + print ''; print ''; } else { print ''; - print ''; + print ''; } if ($conf->use_javascript_ajax) { From 17dccc2a6d766ef811d58a80ef1fea727c5c0449 Mon Sep 17 00:00:00 2001 From: bagtaib Date: Wed, 24 Aug 2022 12:02:38 +0100 Subject: [PATCH 801/826] added email check --- htdocs/public/partnership/new.php | 64 +++++++++++++++++-------------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/htdocs/public/partnership/new.php b/htdocs/public/partnership/new.php index f817a36aa1b..9026aacce4d 100644 --- a/htdocs/public/partnership/new.php +++ b/htdocs/public/partnership/new.php @@ -217,7 +217,6 @@ if (empty($reshook) && $action == 'add') { $partnership->fk_soc = 0; } - // need to change this part $partnership->status = 0; $partnership->note_private = GETPOST('note_private'); $partnership->date_creation = dol_now(); @@ -234,44 +233,56 @@ if (empty($reshook) && $action == 'add') { //$partnership->state_id = GETPOST('state_id', 'int'); //$partnership->typeid = $conf->global->PARTNERSHIP_NEWFORM_FORCETYPE ? $conf->global->PARTNERSHIP_NEWFORM_FORCETYPE : GETPOST('typeid', 'int'); - // Fill array 'array_options' with data from add form - $extrafields->fetch_name_optionals_label($partnership->table_element); - $ret = $extrafields->setOptionalsFromPost(null, $partnership); - if ($ret < 0) { - $error++; - } // test if societe already exist $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."societe WHERE nom='".$db->escape(GETPOST('societe'))."'"; $result = $db->query($sql); if ($result) { $num = $db->num_rows($result); } - if ($num = 0) { - //create thirdparty - $company = new Societe($db); - - $company->address = GETPOST('address'); - $company->zip = GETPOST('zipcode'); - $company->town = GETPOST('town'); - $company->email = GETPOST('email'); - $company->country_id = GETPOST('country_id', 'int'); - $company->state_id = GETPOST('state_id', 'int'); - $company->name_alias = dolGetFirstLastname(GETPOST('firstname'), GETPOST('lastname')); - - $resultat=$company->create($user); - if ($result < 0) { - $error++; - $errmsg .= join('
', $company->errors); + if ($num = 0) { // si il ya pas d'entree sur le nom on teste l'email + $sql1 = "SELECT rowid FROM ".MAIN_DB_PREFIX."societe WHERE email='".$db->escape(GETPOST('email'))."'"; + $result1 = $db->query($sql1); + if ($result1) { + $num1 = $db->num_rows($result1); } + if ($num1 != 0) { + $error++; + $errmsg = "email already exists please rewrite your company name"; + } else { + //create thirdparty + $company = new Societe($db); - $partnership->fk_soc = $company->id; + $company->address = GETPOST('address'); + $company->zip = GETPOST('zipcode'); + $company->town = GETPOST('town'); + $company->email = GETPOST('email'); + $company->country_id = GETPOST('country_id', 'int'); + $company->state_id = GETPOST('state_id', 'int'); + $company->name_alias = dolGetFirstLastname(GETPOST('firstname'), GETPOST('lastname')); + + $resultat=$company->create($user); + if ($resultat < 0) { + $error++; + $errmsg .= join('
', $company->errors); + } + + $partnership->fk_soc = $company->id; + } } elseif ($num > 1) { $error++; - $errmsg = 'Message'; + $errmsg = 'more than one entry exist for this company please contact us to complete your partnership request'; } else { $company = $db->fetch_object($result); $partnership->fk_soc = $company->rowid; } + + // Fill array 'array_options' with data from add form + $extrafields->fetch_name_optionals_label($partnership->table_element); + $ret = $extrafields->setOptionalsFromPost(null, $partnership); + if ($ret < 0) { + $error++; + } + if (!$error) { $result = $partnership->create($user); if ($result > 0) { @@ -361,9 +372,6 @@ if (empty($reshook) && $action == 'add') { } }*/ - - - if (!empty($backtopage)) { $urlback = $backtopage; } elseif (!empty($conf->global->PARTNERSHIP_URL_REDIRECT_SUBSCRIPTION)) { From 778d2454077d168965da3209a965acba2a5aff01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 24 Aug 2022 16:01:27 +0200 Subject: [PATCH 802/826] add fields for company bank accounts --- htdocs/install/mysql/migration/16.0.0-17.0.0.sql | 4 ++++ htdocs/install/mysql/tables/llx_societe_rib.sql | 15 +++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql index 3150aca844d..bb263710a0f 100644 --- a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql +++ b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql @@ -97,3 +97,7 @@ INSERT INTO llx_c_hrm_public_holiday (code, entity, fk_country, dayrule, year, m INSERT INTO llx_c_hrm_public_holiday (code, entity, fk_country, dayrule, year, month, day, active) VALUES('BE-EASTER', 0, 2, 'eastermonday', 0, 0, 0, 1); INSERT INTO llx_c_hrm_public_holiday (code, entity, fk_country, dayrule, year, month, day, active) VALUES('BE-ASCENSION', 0, 2, 'ascension', 0, 0, 0, 1); INSERT INTO llx_c_hrm_public_holiday (code, entity, fk_country, dayrule, year, month, day, active) VALUES('BE-PENTECOST', 0, 2, 'pentecost', 0, 0, 0, 1); + +ALTER TABLE llx_societe_rib ADD COLUMN state_id integer AFTER default_rib; +ALTER TABLE llx_societe_rib ADD COLUMN fk_country integer AFTER state_id; +ALTER TABLE llx_societe_rib ADD COLUMN currency_code varchar(3) AFTER fk_country; diff --git a/htdocs/install/mysql/tables/llx_societe_rib.sql b/htdocs/install/mysql/tables/llx_societe_rib.sql index 9ea6ccf9188..a798f6ac594 100644 --- a/htdocs/install/mysql/tables/llx_societe_rib.sql +++ b/htdocs/install/mysql/tables/llx_societe_rib.sql @@ -43,20 +43,23 @@ create table llx_societe_rib proprio varchar(60), owner_address varchar(255), default_rib smallint NOT NULL DEFAULT 0, - - -- For BAN direct debit feature + state_id integer, + fk_country integer, + currency_code varchar(3), + + -- For BAN direct debit feature rum varchar(32), -- RUM value to use for SEPA generation date_rum date, -- Date of mandate frstrecur varchar(16) default 'FRST', -- 'FRST' or 'RECUR' - + --For credit card last_four varchar(4), -- last 4 card_type varchar(255), -- card type 'VISA', 'MC' , ... - cvn varchar(255), + cvn varchar(255), exp_date_month INTEGER, exp_date_year INTEGER, country_code varchar(10), - + --For Paypal approved INTEGER DEFAULT 0, email varchar(255), @@ -65,7 +68,7 @@ create table llx_societe_rib preapproval_key varchar(255), starting_date date, total_amount_of_all_payments double(24,8), - + --For Stripe stripe_card_ref varchar(128), -- 'card_...' stripe_account varchar(128), -- 'pk_live_...' From c53fc449eed70d73f39be7b7138651e0d67bb0f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 24 Aug 2022 16:19:39 +0200 Subject: [PATCH 803/826] add fields for user bank accounts --- htdocs/install/mysql/migration/16.0.0-17.0.0.sql | 4 ++++ htdocs/install/mysql/tables/llx_user_rib.sql | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql index bb263710a0f..fcbd83c2a81 100644 --- a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql +++ b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql @@ -101,3 +101,7 @@ INSERT INTO llx_c_hrm_public_holiday (code, entity, fk_country, dayrule, year, m ALTER TABLE llx_societe_rib ADD COLUMN state_id integer AFTER default_rib; ALTER TABLE llx_societe_rib ADD COLUMN fk_country integer AFTER state_id; ALTER TABLE llx_societe_rib ADD COLUMN currency_code varchar(3) AFTER fk_country; + +ALTER TABLE llx_user_rib ADD COLUMN state_id integer AFTER owner_address; +ALTER TABLE llx_user_rib ADD COLUMN fk_country integer AFTER state_id; +ALTER TABLE llx_user_rib ADD COLUMN currency_code varchar(3) AFTER fk_country; diff --git a/htdocs/install/mysql/tables/llx_user_rib.sql b/htdocs/install/mysql/tables/llx_user_rib.sql index 4463a1f6f2b..c98e447a75e 100644 --- a/htdocs/install/mysql/tables/llx_user_rib.sql +++ b/htdocs/install/mysql/tables/llx_user_rib.sql @@ -33,5 +33,8 @@ create table llx_user_rib iban_prefix varchar(34), -- full iban. 34 according to ISO 13616 domiciliation varchar(255), proprio varchar(60), - owner_address varchar(255) + owner_address varchar(255), + state_id integer, + fk_country integer, + currency_code varchar(3) )ENGINE=innodb; From 2c7037bfe365751fbd05ff7d80db2263a80b2ffe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 24 Aug 2022 18:09:14 +0200 Subject: [PATCH 804/826] Update card.php --- htdocs/compta/bank/card.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/compta/bank/card.php b/htdocs/compta/bank/card.php index 9233d397152..0ffa5cfaf0d 100644 --- a/htdocs/compta/bank/card.php +++ b/htdocs/compta/bank/card.php @@ -6,7 +6,7 @@ * Copyright (C) 2014-2017 Alexandre Spangaro * Copyright (C) 2015 Jean-François Ferry * Copyright (C) 2016 Marcos García - * Copyright (C) 2018 Frédéric France + * Copyright (C) 2018-2022 Frédéric France * Copyright (C) 2022 Charlene Benke * * This program is free software; you can redistribute it and/or modify @@ -234,7 +234,7 @@ if (empty($reshook)) { $object->number = trim(GETPOST("number")); $object->cle_rib = trim(GETPOST("cle_rib")); $object->bic = trim(GETPOST("bic")); - $object->iban = trim(GETPOST("iban")); + $object->iban = trim(GETPOST("iban"));('paymentbybankt $object->domiciliation = trim(GETPOST("domiciliation", "alphanohtml")); $object->pti_in_ctti = empty(GETPOST("pti_in_ctti")) ? 0 : 1; @@ -1079,7 +1079,7 @@ if ($action == 'create') { print '
'.$form->textwithpicto($langs->trans("IDS"), $langs->trans("IDS").' ('.$langs->trans("UsedFor", $langs->transnoentitiesnoconv("BankTransfer")).')').'
'; - if ($obj->tosell) { + if ($obj->tosell && $usercancreadprice) { if ($obj->price_base_type == 'TTC') { print ''.price($obj->price_ttc).' '.$langs->trans("TTC").''; } else { @@ -1645,7 +1649,7 @@ if ($resql) { $productpricescache[$obj->rowid] = array(); } - if ($obj->tosell) { + if ($obj->tosell && $usercancreadprice) { // Make 1 request for all price levels (without filter on price_level) and saved result into an cache array // then reuse the cache array if we need prices for other price levels $sqlp = "SELECT p.rowid, p.fk_product, p.price, p.price_ttc, p.price_level, p.date_price, p.price_base_type"; @@ -1695,7 +1699,7 @@ if ($resql) { // Better buy price if (!empty($arrayfields['p.minbuyprice']['checked'])) { print ''; - if ($obj->tobuy && $obj->minsellprice != '') { + if ($obj->tobuy && $obj->minsellprice != '' && $usercancreadprice) { //print price($obj->minsellprice).' '.$langs->trans("HT"); if ($product_fourn->find_min_price_product_fournisseur($obj->rowid) > 0) { if ($product_fourn->product_fourn_price_id > 0) { @@ -1717,7 +1721,7 @@ if ($resql) { // Number of buy prices if (!empty($arrayfields['p.numbuyprice']['checked'])) { print ''; - if ($obj->tobuy) { + if ($obj->tobuy && $usercancreadprice) { if (count($productFournList = $product_fourn->list_product_fournisseur_price($obj->rowid)) > 0) { $htmltext = $product_fourn->display_price_product_fournisseur(1, 1, 0, 1, $productFournList); print $form->textwithpicto(count($productFournList), $htmltext); @@ -1739,14 +1743,18 @@ if ($resql) { // WAP if (!empty($arrayfields['p.pmp']['checked'])) { print ''; - print ''.price($product_static->pmp, 1, $langs).""; + if ($usercancreadprice) { + print ''.price($product_static->pmp, 1, $langs).""; + } print ''; //print $obj->cost_price; - print ''.price($obj->cost_price).' '.$langs->trans("HT").''; + if ($usercancreadprice) { + print ''.price($obj->cost_price).' '.$langs->trans("HT").''; + } print '