dolibarr.pl 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. #----------------------------------------------------------------------------
  2. # \file dolibarr.pl
  3. # \brief Dolibarr script install for Virtualmin Pro
  4. # \author (c)2009-2020 Regis Houssin <regis.houssin@inodbox.com>
  5. #----------------------------------------------------------------------------
  6. # script_dolibarr_desc()
  7. sub script_dolibarr_desc
  8. {
  9. return "Dolibarr";
  10. }
  11. sub script_dolibarr_uses
  12. {
  13. return ( "php" );
  14. }
  15. # script_dolibarr_longdesc()
  16. sub script_dolibarr_longdesc
  17. {
  18. return "Dolibarr ERP/CRM is a powerful Open Source software to manage a professional or foundation activity (small and medium enterprises, freelancers).";
  19. }
  20. sub script_dolibarr_author
  21. {
  22. return "Regis Houssin";
  23. }
  24. # script_dolibarr_versions()
  25. sub script_dolibarr_versions
  26. {
  27. return ( "14.0.5", "13.0.5", "12.0.5", "11.0.5", "10.0.7", "9.0.4", "8.0.6", "7.0.5" );
  28. }
  29. sub script_dolibarr_release
  30. {
  31. return 2; # for mysqli fix
  32. }
  33. sub script_dolibarr_category
  34. {
  35. return "Commerce";
  36. }
  37. sub script_dolibarr_php_vers
  38. {
  39. return ( 5 );
  40. }
  41. sub script_dolibarr_php_modules
  42. {
  43. local ($d, $ver, $phpver, $opts) = @_;
  44. local ($dbtype, $dbname) = split(/_/, $opts->{'db'}, 2);
  45. return $dbtype eq "mysql" ? ("mysql") : ("pgsql");
  46. }
  47. sub script_dolibarr_dbs
  48. {
  49. local ($d, $ver) = @_;
  50. return ("mysql", "postgres");
  51. }
  52. # script_dolibarr_depends(&domain, version)
  53. sub script_dolibarr_depends
  54. {
  55. local ($d, $ver, $sinfo, $phpver) = @_;
  56. local @rv;
  57. if ($ver >= 3.6) {
  58. # Check for PHP 5.3+
  59. local $phpv = &get_php_version($phpver || 5, $d);
  60. if (!$phpv) {
  61. push(@rv, "Could not work out exact PHP version");
  62. }
  63. elsif ($phpv < 5.3) {
  64. push(@rv, "Dolibarr requires PHP version 5.3 or later");
  65. }
  66. }
  67. if ($ver >= 12.0) {
  68. # Check for PHP 5.6+
  69. local $phpv = &get_php_version($phpver || 5, $d);
  70. if (!$phpv) {
  71. push(@rv, "Could not work out exact PHP version");
  72. }
  73. elsif ($phpv < 5.6) {
  74. push(@rv, "Dolibarr requires PHP version 5.6 or later");
  75. }
  76. }
  77. return @rv;
  78. }
  79. # script_dolibarr_params(&domain, version, &upgrade-info)
  80. # Returns HTML for table rows for options for installing dolibarr
  81. sub script_dolibarr_params
  82. {
  83. local ($d, $ver, $upgrade) = @_;
  84. local $rv;
  85. local $hdir = &public_html_dir($d, 1);
  86. if ($upgrade) {
  87. # Options are fixed when upgrading
  88. local ($dbtype, $dbname) = split(/_/, $upgrade->{'opts'}->{'db'}, 2);
  89. $rv .= &ui_table_row("Database for Dolibarr tables", $dbname);
  90. local $dir = $upgrade->{'opts'}->{'dir'};
  91. $dir =~ s/^$d->{'home'}\///;
  92. $rv .= &ui_table_row("Install directory", $dir);
  93. }
  94. else {
  95. # Show editable install options
  96. local @dbs = &domain_databases($d, [ "mysql"]);
  97. $rv .= &ui_table_row("Database for Dolibarr tables",
  98. &ui_database_select("db", undef, \@dbs, $d, "dolibarr"));
  99. $rv .= &ui_table_row("Install sub-directory under <tt>$hdir</tt>",
  100. &ui_opt_textbox("dir", &substitute_scriptname_template("dolibarr", $d), 30, "At top level"));
  101. if ($d->{'ssl'} && $ver >= 3.0) {
  102. $rv .= &ui_table_row("Force https connection?",
  103. &ui_yesno_radio("forcehttps", 0));
  104. }
  105. }
  106. return $rv;
  107. }
  108. # script_dolibarr_parse(&domain, version, &in, &upgrade-info)
  109. # Returns either a hash ref of parsed options, or an error string
  110. sub script_dolibarr_parse
  111. {
  112. local ($d, $ver, $in, $upgrade) = @_;
  113. if ($upgrade) {
  114. # Options are always the same
  115. return $upgrade->{'opts'};
  116. }
  117. else {
  118. local $hdir = &public_html_dir($d, 0);
  119. $in{'dir_def'} || $in{'dir'} =~ /\S/ && $in{'dir'} !~ /\.\./ ||
  120. return "Missing or invalid installation directory";
  121. local $dir = $in{'dir_def'} ? $hdir : "$hdir/$in{'dir'}";
  122. local ($newdb) = ($in->{'db'} =~ s/^\*//);
  123. return { 'db' => $in->{'db'},
  124. 'newdb' => $newdb,
  125. 'dir' => $dir,
  126. 'path' => $in->{'dir_def'} ? "/" : "/$in->{'dir'}",
  127. 'forcehttps' => $in->{'forcehttps'}, };
  128. }
  129. }
  130. # script_dolibarr_check(&domain, version, &opts, &upgrade-info)
  131. # Returns an error message if a required option is missing or invalid
  132. sub script_dolibarr_check
  133. {
  134. local ($d, $ver, $opts, $upgrade) = @_;
  135. $opts->{'dir'} =~ /^\// || return "Missing or invalid install directory";
  136. $opts->{'db'} || return "Missing database";
  137. if (-r "$opts->{'dir'}/conf/conf.php") {
  138. return "Dolibarr appears to be already installed in the selected directory";
  139. }
  140. local ($dbtype, $dbname) = split(/_/, $opts->{'db'}, 2);
  141. local $clash = &find_database_table($dbtype, $dbname, "llx_.*");
  142. $clash && return "Dolibarr appears to be already using the selected database (table $clash)";
  143. return undef;
  144. }
  145. # script_dolibarr_files(&domain, version, &opts, &upgrade-info)
  146. # Returns a list of files needed by dolibarr, each of which is a hash ref
  147. # containing a name, filename and URL
  148. sub script_dolibarr_files
  149. {
  150. local ($d, $ver, $opts, $upgrade) = @_;
  151. local @files = ( { 'name' => "source",
  152. 'file' => "Dolibarr_$ver.tar.gz",
  153. 'url' => "http://prdownloads.sourceforge.net/dolibarr/dolibarr-$ver.tgz" } );
  154. return @files;
  155. }
  156. sub script_dolibarr_commands
  157. {
  158. return ("tar", "gunzip");
  159. }
  160. # script_dolibarr_install(&domain, version, &opts, &files, &upgrade-info)
  161. # Actually installs dolibarr, and returns either 1 and an informational
  162. # message, or 0 and an error
  163. sub script_dolibarr_install
  164. {
  165. local ($d, $version, $opts, $files, $upgrade, $domuser, $dompass) = @_;
  166. local ($out, $ex);
  167. if ($opts->{'newdb'} && !$upgrade) {
  168. local $err = &create_script_database($d, $opts->{'db'});
  169. return (0, "Database creation failed : $err") if ($err);
  170. }
  171. local ($dbtype, $dbname) = split(/_/, $opts->{'db'}, 2);
  172. local $dbuser = $dbtype eq "mysql" ? &mysql_user($d) : &postgres_user($d);
  173. local $dbpass = $dbtype eq "mysql" ? &mysql_pass($d) : &postgres_pass($d, 1);
  174. local $dbphptype = $dbtype eq "mysql" && $version < 3.6 ? "mysql" :
  175. $dbtype eq "mysql" ? "mysqli" : "pgsql";
  176. local $dbhost = &get_database_host($dbtype, $d);
  177. local $dberr = &check_script_db_connection($dbtype, $dbname, $dbuser, $dbpass);
  178. return (0, "Database connection failed : $dberr") if ($dberr);
  179. # Extract tar file to temp dir and copy to target
  180. local $temp = &transname();
  181. local $err = &extract_script_archive($files->{'source'}, $temp, $d,
  182. $opts->{'dir'}, "dolibarr-$ver/htdocs");
  183. $err && return (0, "Failed to extract source : $err");
  184. # Add config file
  185. local $cfiledir = "$opts->{'dir'}/conf/";
  186. local $docdir = "$opts->{'dir'}/documents";
  187. local $altdir = "$opts->{'dir'}/custom";
  188. local $cfile = $cfiledir."conf.php";
  189. local $oldcfile = &transname();
  190. local $olddocdir = &transname();
  191. local $oldaltdir = &transname();
  192. local $url;
  193. $tmpl = &get_template($d->{'template'});
  194. $mycharset = $tmpl->{'mysql_charset'};
  195. $mycollate = $tmpl->{'mysql_collate'};
  196. $pgcharset = $tmpl->{'postgres_encoding'};
  197. $charset = $dbtype eq "mysql" ? $mycharset : $pgcharset;
  198. $collate = $dbtype eq "mysql" ? $mycollate : "C";
  199. $path = &script_path_url($d, $opts);
  200. if ($path =~ /^https:/ || $d->{'ssl'}) {
  201. $url = "https://$d->{'dom'}";
  202. }
  203. else {
  204. $url = "http://$d->{'dom'}";
  205. }
  206. if ($opts->{'path'} =~ /\w/) {
  207. $url .= $opts->{'path'};
  208. }
  209. if (!$upgrade) {
  210. local $cdef = "$opts->{'dir'}/conf/conf.php.example";
  211. &copy_source_dest_as_domain_user($d, $cdef, $cfile);
  212. &set_permissions_as_domain_user($d, 0777, $cfiledir);
  213. &copy_source_dest_as_domain_user($d, $cfile);
  214. &run_as_domain_user($d, "mkdir ".quotemeta($docdir));
  215. &set_permissions_as_domain_user($d, 0777, $docdir);
  216. }
  217. else {
  218. # Preserve old config file, documents and custom directory
  219. &copy_source_dest($cfile, $oldcfile);
  220. &copy_source_dest($docdir, $olddocdir);
  221. &copy_source_dest($altdir, $oldaltdir);
  222. }
  223. if ($upgrade) {
  224. # Put back original config file, documents and custom directory
  225. &copy_source_dest_as_domain_user($d, $oldcfile, $cfile);
  226. &copy_source_dest_as_domain_user($d, $olddocdir, $docdir);
  227. &copy_source_dest_as_domain_user($d, $oldaltdir, $altdir);
  228. # First page (Update database schema)
  229. local @params = ( [ "action", "upgrade" ],
  230. [ "versionfrom", $upgrade->{'version'} ],
  231. [ "versionto", $ver ],
  232. );
  233. local $err = &call_dolibarr_wizard_page(\@params, "upgrade", $d, $opts);
  234. return (-1, "Dolibarr wizard failed : $err") if ($err);
  235. # Second page (Migrate some data)
  236. local @params = ( [ "action", "upgrade" ],
  237. [ "versionfrom", $upgrade->{'version'} ],
  238. [ "versionto", $ver ],
  239. );
  240. local $err = &call_dolibarr_wizard_page(\@params, "upgrade2", $d, $opts);
  241. return (-1, "Dolibarr wizard failed : $err") if ($err);
  242. # Third page (Update version number)
  243. local @params = ( [ "action", "upgrade" ],
  244. [ "versionfrom", $upgrade->{'version'} ],
  245. [ "versionto", $ver ],
  246. [ "installlock", "444" ],
  247. );
  248. local $p = $ver >= 3.8 ? "step5" : "etape5";
  249. local $err = &call_dolibarr_wizard_page(\@params, $p, $d, $opts);
  250. return (-1, "Dolibarr wizard failed : $err") if ($err);
  251. # Remove the installation directory. (deprecated)
  252. # local $dinstall = "$opts->{'dir'}/install";
  253. # $dinstall =~ s/\/$//;
  254. # $out = &run_as_domain_user($d, "rm -rf ".quotemeta($dinstall));
  255. }
  256. else {
  257. # First page (Db connection and config file creation)
  258. local @params = ( [ "main_dir", $opts->{'dir'} ],
  259. [ "main_data_dir", $opts->{'dir'}."/documents" ],
  260. [ "main_url", $url ],
  261. [ "db_type", $dbphptype ],
  262. [ "db_host", $dbhost ],
  263. [ "db_name", $dbname ],
  264. [ "db_user", $dbuser ],
  265. [ "db_pass", $dbpass ],
  266. [ "action", "set" ],
  267. [ "main_force_https", $opts->{'forcehttps'} ],
  268. [ "dolibarr_main_db_character_set", $charset ],
  269. [ "dolibarr_main_db_collation", $collate ],
  270. [ "usealternaterootdir", "1" ],
  271. [ "main_alt_dir_name", "custom" ],
  272. );
  273. local $p = $ver >= 3.8 ? "step1" : "etape1";
  274. local $err = &call_dolibarr_wizard_page(\@params, $p, $d, $opts);
  275. return (-1, "Dolibarr wizard failed : $err") if ($err);
  276. # Second page (Populate database)
  277. local @params = ( [ "action", "set" ] );
  278. local $p = $ver >= 3.8 ? "step2" : "etape2";
  279. local $err = &call_dolibarr_wizard_page(\@params, $p, $d, $opts);
  280. return (-1, "Dolibarr wizard failed : $err") if ($err);
  281. # Third page (Add administrator account)
  282. local @params = ( [ "action", "set" ],
  283. [ "login", "admin" ],
  284. [ "pass", $dompass ],
  285. [ "pass_verif", $dompass ],
  286. [ "installlock", "444" ],
  287. );
  288. local $p = $ver >= 3.8 ? "step5" : "etape5";
  289. local $err = &call_dolibarr_wizard_page(\@params, $p, $d, $opts);
  290. return (-1, "Dolibarr wizard failed : $err") if ($err);
  291. # Remove the installation directory (deprecated)
  292. # local $dinstall = "$opts->{'dir'}/install";
  293. # $dinstall =~ s/\/$//;
  294. # $out = &run_as_domain_user($d, "rm -rf ".quotemeta($dinstall));
  295. # Protect config file
  296. &set_permissions_as_domain_user($d, 0644, $cfile);
  297. &set_permissions_as_domain_user($d, 0755, $cfiledir);
  298. }
  299. # Return a URL for the user
  300. local $rp = $opts->{'dir'};
  301. $rp =~ s/^$d->{'home'}\///;
  302. local $adminurl = $url;
  303. return (1, "Dolibarr installation complete. Go to <a target=_new href='$url'>$url</a> to use it.", "Under $rp using $dbtype database $dbname", $url, 'admin', $dompass);
  304. }
  305. # call_dolibarr_wizard_page(&parameters, step-no, &domain, &opts)
  306. sub call_dolibarr_wizard_page
  307. {
  308. local ($params, $page, $d, $opts) = @_;
  309. local $params = join("&", map { $_->[0]."=".&urlize($_->[1]) } @$params );
  310. local $ipage = $opts->{'path'}."/install/".$page.".php";
  311. local ($iout, $ierror);
  312. &post_http_connection($d, $ipage, $params, \$iout, \$ierror);
  313. if ($ierror) {
  314. return $ierror;
  315. }
  316. return undef;
  317. }
  318. # script_dolibarr_uninstall(&domain, version, &opts)
  319. # Un-installs a dolibarr installation, by deleting the directory.
  320. # Returns 1 on success and a message, or 0 on failure and an error
  321. sub script_dolibarr_uninstall
  322. {
  323. local ($d, $version, $opts) = @_;
  324. # Remove the contents of the target directory
  325. local $derr = &delete_script_install_directory($d, $opts);
  326. return (0, $derr) if ($derr);
  327. # Remove all llx_ tables from the database
  328. # 10 times because of constraints
  329. for(my $i=0; $i<10; $i++) {
  330. &cleanup_script_database($d, $opts->{'db'}, "llx_");
  331. }
  332. # Take out the DB
  333. if ($opts->{'newdb'}) {
  334. &delete_script_database($d, $opts->{'db'});
  335. }
  336. return (1, "Dolibarr directory and tables deleted.");
  337. }
  338. # script_dolibarr_realversion(&domain, &opts)
  339. # Returns the real version number of some script install, or undef if unknown
  340. sub script_dolibarr_realversion
  341. {
  342. local ($d, $opts, $sinfo) = @_;
  343. local $lref = &read_file_lines("$opts->{'dir'}/filefunc.inc.php", 1);
  344. foreach my $l (@$lref) {
  345. if ($l =~ /'DOL_VERSION',\s?'([0-9a-z\.\-]+)'/) {
  346. return $1;
  347. }
  348. }
  349. return undef;
  350. }
  351. # script_dolibarr_check_latest(version)
  352. # Checks if some version is the latest for this project, and if not returns
  353. # a newer one. Otherwise returns undef.
  354. sub script_dolibarr_check_latest
  355. {
  356. local ($ver) = @_;
  357. local @vers = &osdn_package_versions("dolibarr",
  358. $ver >= 14.0 ? "dolibarr\\-(12\\.0\\.[0-9\\.]+)\\.tgz" :
  359. $ver >= 13.0 ? "dolibarr\\-(12\\.0\\.[0-9\\.]+)\\.tgz" :
  360. $ver >= 12.0 ? "dolibarr\\-(12\\.0\\.[0-9\\.]+)\\.tgz" :
  361. $ver >= 11.0 ? "dolibarr\\-(11\\.0\\.[0-9\\.]+)\\.tgz" :
  362. $ver >= 10.0 ? "dolibarr\\-(10\\.0\\.[0-9\\.]+)\\.tgz" :
  363. $ver >= 9.0 ? "dolibarr\\-(9\\.0\\.[0-9\\.]+)\\.tgz" :
  364. $ver >= 8.0 ? "dolibarr\\-(8\\.0\\.[0-9\\.]+)\\.tgz" :
  365. $ver >= 7.0 ? "dolibarr\\-(7\\.0\\.[0-9\\.]+)\\.tgz" :
  366. $ver >= 6.0 ? "dolibarr\\-(6\\.0\\.[0-9\\.]+)\\.tgz" :
  367. $ver >= 5.0 ? "dolibarr\\-(5\\.0\\.[0-9\\.]+)\\.tgz" :
  368. $ver >= 4.0 ? "dolibarr\\-(4\\.0\\.[0-9\\.]+)\\.tgz" :
  369. $ver >= 3.9 ? "dolibarr\\-(3\\.9\\.[0-9\\.]+)\\.tgz" :
  370. $ver >= 3.8 ? "dolibarr\\-(3\\.8\\.[0-9\\.]+)\\.tgz" :
  371. $ver >= 3.7 ? "dolibarr\\-(3\\.7\\.[0-9\\.]+)\\.tgz" :
  372. $ver >= 3.6 ? "dolibarr\\-(3\\.6\\.[0-9\\.]+)\\.tgz" :
  373. $ver >= 3.5 ? "dolibarr\\-(3\\.5\\.[0-9\\.]+)\\.tgz" :
  374. $ver >= 2.9 ? "dolibarr\\-(2\\.9\\.[0-9\\.]+)\\.tgz" :
  375. "dolibarr\\-(2\\.8\\.[0-9\\.]+)\\.tgz");
  376. return "Failed to find versions" if (!@vers);
  377. return $ver eq $vers[0] ? undef : $vers[0];
  378. }
  379. sub script_dolibarr_site
  380. {
  381. return 'https://www.dolibarr.org/';
  382. }
  383. sub script_dolibarr_passmode
  384. {
  385. return 2;
  386. }
  387. 1;