summaryrefslogtreecommitdiff
path: root/setup.pl
blob: b71a356201bc038c3fac539b437b051540889467 (plain)
  1. #!/usr/bin/perl
  2. #
  3. ######################################################################
  4. # LedgerSMB Small Medium Business Accounting Software Installer
  5. # http://sourceforge.net/projects/ledger-smb/
  6. #
  7. # Copyright (C) 2006
  8. # This work contains copyrighted information from a number of sources all used
  9. # with permission.
  10. #
  11. # This file contains source code included with or based on SQL-Ledger which
  12. # is Copyright Dieter Simader and DWS Systems Inc. 2000-2005 and licensed
  13. # under the GNU General Public License version 2 or, at your option, any later
  14. # version. For a full list including contact information of contributors,
  15. # maintainers, and copyright holders, see the CONTRIBUTORS file.
  16. #
  17. # Original Copyright Notice from SQL-Ledger 2.6.17 (before the fork):
  18. # Copyright (c) 2002, Dieter Simader
  19. #
  20. # Web: http://www.sql-ledger.org
  21. #
  22. #######################################################################
  23. # Next bunch of lines are to check to see if they have the cpan module installed.
  24. my $cpan=0;
  25. eval {
  26. use CPAN;
  27. };
  28. if (!$@){
  29. $cpan = 1;
  30. }
  31. $| = 1;
  32. #not sure how safe this is. If the browser sends a blank HTTP_USER_AGENT
  33. #will this script destroy part of the install?
  34. #This script should probably be made inaccessible via HTTP until this feature is working
  35. if (($ENV{HTTP_USER_AGENT})||($ENV{HTTP_HOST})) {
  36. print "Content-type: text/html\n\nThis does not work yet! use $0 from the command line";
  37. exit;
  38. }
  39. # Make sure they have the required perl modules installed.
  40. # bin/mozilla/admin.pl needs Digest::MD5 for session handling
  41. # HTML:LinkExtor is used by the setup program.
  42. my @req_modules=(qw(DBI DBD::Pg Digest::MD5 HTML::LinkExtor));
  43. foreach my $module(@req_modules){
  44. print "Checking for: $module ...\t";
  45. my @results=&check_module($module);
  46. print "$results[1]\n";
  47. next if($results[0]); # Passed, no need to continue..
  48. if ($cpan == 1){
  49. # Can try to install the module..
  50. print "\n\nWould you like to try and install this package ($module) through CPAN? (Y/N) [Y]:";
  51. $response=<STDIN>;
  52. if(($response=~/y/i) or ($response eq "\n")){
  53. my $inst_obj = CPAN::Shell->install($module);
  54. @results=&check_module($module);
  55. if(!$results[0]){
  56. print "\n\nCould not install $module using CPAN.\n";
  57. die "Please try to install this module manually\n";
  58. }
  59. } else {
  60. die "Please install the $module perl module and retry the setup.\n";
  61. }
  62. } else {
  63. # Can't try to install the module..
  64. die "Please install the $module perl module and retry the setup.\n";
  65. }
  66. }
  67. use HTML::LinkExtor;
  68. $lynx = `lynx -version`; # if LWP is not installed use lynx
  69. $gzip = `gzip -V 2>&1`; # gz decompression utility
  70. $tar = `tar --version 2>&1`; # tar archiver
  71. $latex = `latex -version`;
  72. my $versionurl ='http://prdownloads.sourceforge.net/ledger-smb';
  73. %source = (
  74. 1 => { url => "http://voxel.dl.sourceforge.net/sourceforge/ledger-smb", site => "New York, U.S.A", locale => 'us' },
  75. 2 => { url => "http://easynews.dl.sourceforge.net/sourceforge/ledger-smb", site => "Arizona, U.S.A", locale => 'us' },
  76. 3 => { url => "http://ufpr.dl.sourceforge.net/sourceforge/ledger-smb", site =>"Brazil", locale => 'br' },
  77. 4 => { url => "http://surfnet.dl.sourceforge.net/sourceforge/ledger-smb", site => "The Netherlands", locale => 'nl' },
  78. 5 => { url => "http://http://kent.dl.sourceforge.net/sourceforge/ledger-smb", site => "U.K", locale => 'uk' },
  79. 6 => { url => "http://ovh.dl.sourceforge.net/sourceforge/ledger-smb", site => "France", locale => 'fr' },
  80. 7 => { url => "http://mesh.dl.sourceforge.net/sourceforge/ledger-smb", site => "Germany", locale => 'de' },
  81. 8 => { url => "http://citkit.dl.sourceforge.net/sourceforge/ledger-smb", site => "Russia", locale => 'ru' },
  82. 9 => { url => "http://optusnet.dl.sourceforge.net/sourceforge/ledger-smb", site => "Sydney, Australia", locale => 'au' },
  83. 10 => { url => "http://nchc.dl.sourceforge.net/sourceforge/ledger-smb", site => "Taiwan", locale => 'tw' },
  84. 11 => { url => "http://jaist.dl.sourceforge.net/sourceforge/ledger-smb", site => "Japan", locale => 'jp' },
  85. 12 => { url => "http://heanet.dl.sourceforge.net/sourceforge/ledger-smb", site => "Ireland", locale => 'ie' }
  86. );
  87. $userspath = "users"; # default for new installation
  88. eval { require "ledger-smb.conf"; };
  89. $filename = shift;
  90. chomp $filename;
  91. $newinstall = 1;
  92. # is LWP installed
  93. eval { require LWP::Simple; };
  94. $lwp = !($@);
  95. unless ($lwp || $lynx || $filename) {
  96. die "You must have either lynx or LWP installed or specify a filename.
  97. perl $0 <filename>\n";
  98. }
  99. if ($filename) {
  100. # extract version
  101. die "Not a Ledger-SMB archive\n" if ($filename !~ /^ledger-smb/);
  102. $version = $filename;
  103. $version =~ s/ledger-smb-(\d+\.\d+\.\d+).*$/$1/;
  104. }
  105. if (-f "VERSION") {
  106. # get installed version from VERSION file
  107. open(FH, "VERSION");
  108. @a = <FH>;
  109. close(FH);
  110. $version = $a[0];
  111. chomp $version;
  112. $newinstall = !$version;
  113. if (! -f "ledger-smb.conf") {
  114. $newinstall = 1;
  115. }
  116. }
  117. $webowner = "nobody";
  118. $webgroup = "nogroup";
  119. if ($httpd = `find /etc /usr/local/etc -type f -name 'httpd.conf'`) {
  120. chomp $httpd;
  121. $webowner = `grep "^User " $httpd`;
  122. $webgroup = `grep "^Group " $httpd`;
  123. chomp $webowner;
  124. chomp $webgroup;
  125. ($null, $webowner) = split / /, $webowner;
  126. ($null, $webgroup) = split / /, $webgroup;
  127. }
  128. if ($confd = `find /etc /usr/local/etc -type d -name 'apache*/conf.d'`) {
  129. chomp $confd;
  130. }
  131. system("tput clear");
  132. if ($filename) {
  133. $install = "\ninstall $version from (f)ile\n";
  134. }
  135. # check for latest version
  136. &get_latest_version;
  137. chomp $latest_version;
  138. if (!$newinstall) {
  139. $install .= "\n(r)einstall $version\n";
  140. }
  141. if ($version && $latest_version) {
  142. if ($version ne $latest_version) {
  143. $install .= "\n(u)pgrade to $latest_version\n";
  144. }
  145. }
  146. $install .= "\n(i)nstall $latest_version (from Internet)\n" if $latest_version;
  147. $install .= "\n(d)ownload $latest_version (no installation)" unless $filename;
  148. print qq|
  149. LedgerSMB Accounting and ERP Installation
  150. $install
  151. Enter: |;
  152. $a = <STDIN>;
  153. chomp $a;
  154. exit unless $a;
  155. $a = lc $a;
  156. if ($a !~ /d/) {
  157. print qq|\nEnter httpd owner [$webowner] : |;
  158. $web = <STDIN>;
  159. chomp $web;
  160. $webowner = $web if $web;
  161. print qq|\nEnter httpd group [$webgroup] : |;
  162. $web = <STDIN>;
  163. chomp $web;
  164. $webgroup = $web if $web;
  165. }
  166. if ($a ne 'f') {
  167. system("tput clear");
  168. # choose site
  169. foreach $item (sort { $a <=> $b } keys %source) {
  170. $i++;
  171. print qq|$i. $source{$item}{site}\n|;
  172. }
  173. $site = "1";
  174. print qq|\nChoose Location [$site] : |;
  175. $b = <STDIN>;
  176. chomp $b;
  177. $site = $b if $b;
  178. }
  179. if ($a eq 'd') {
  180. &download;
  181. }
  182. if ($a =~ /(i|u)/) {
  183. &install_smb;
  184. }
  185. if ($a eq 'r') {
  186. $latest_version = $version;
  187. &install_smb;
  188. }
  189. if ($a eq 'f') {
  190. &install_smb;
  191. }
  192. exit;
  193. # end main
  194. sub check_module{
  195. my($module)=@_;
  196. eval "use $module";
  197. if(!$@){
  198. return 1, "Ok";
  199. }else{
  200. return 0, "FAILED",$@;
  201. }
  202. }
  203. sub download {
  204. &get_source_code;
  205. }
  206. sub get_latest_version {
  207. print "Checking for latest version number .... ";
  208. if ($filename) {
  209. print "skipping, filename supplied\n";
  210. return;
  211. }
  212. my $urlresult = '';
  213. if ($lwp) {
  214. if ($urlresult = LWP::Simple::get("$versionurl")){
  215. $latest_version = parse_links($urlresult);
  216. last;
  217. } else {
  218. print "not found";
  219. }
  220. } else {
  221. if (!$lynx) {
  222. print "\nYou must have either lynx or LWP installed";
  223. exit 1;
  224. }
  225. $ok = `lynx -dump -head $versionurl`;
  226. if ($ok = ($ok =~ s/HTTP.*?200 //)) {
  227. $urlresult = `lynx -dump $versionurl`;
  228. $latest_version = parse_links($urlresult);
  229. last;
  230. } else {
  231. print "not found";
  232. }
  233. die unless $ok;
  234. }
  235. if ($latest_version) {
  236. print "ok\n";
  237. 1;
  238. }
  239. }
  240. my @versions = ();
  241. sub parse_links{
  242. # Take the html retrieved by lwp or lynx and look for the version numbers.
  243. my $text = shift;
  244. my $version = '';
  245. my $p = HTML::LinkExtor->new(\&cb);
  246. $p->parse($text) or die;
  247. foreach (@versions){
  248. my ($chkversion) = $_ =~ /^\/ledger-smb\/ledger-smb-(\d{1,3}\.\d{1,3}\.\d{1,3})\.tar\.gz$/;
  249. $version = $chkversion if ($chkversion gt $version);
  250. }
  251. return $version;
  252. }
  253. sub cb {
  254. # Callback function for LinkExtor
  255. my($tag, %attr) = @_;
  256. return if $tag ne 'a';
  257. return unless $attr{href} =~ /^\/ledger-smb\/ledger-smb-\d{1,3}\.\d{1,3}\.\d{1,3}\.tar\.gz$/;
  258. push(@versions, values %attr);
  259. }
  260. sub get_source_code {
  261. $err = 0;
  262. @order = ();
  263. push @order, $site;
  264. for (sort { $a <=> $b } keys %source) {
  265. push @order, $_;
  266. }
  267. if ($latest_version) {
  268. # download it
  269. chomp $latest_version;
  270. $latest_version = "ledger-smb-${latest_version}.tar.gz";
  271. print "\nStatus\n";
  272. print "Downloading $latest_version .... ";
  273. foreach $key (@order) {
  274. print "\n$source{$key}{site} .... ";
  275. if ($lwp) {
  276. $err = LWP::Simple::getstore("$source{$key}{url}/$latest_version", "$latest_version");
  277. $err -= 200;
  278. } else {
  279. $ok = `lynx -dump -head $source{$key}{url}/$latest_version`;
  280. $err = !($ok =~ s/HTTP.*?200 //);
  281. if (!$err) {
  282. $err = system("lynx -dump $source{$key}{url}/$latest_version > $latest_version");
  283. }
  284. }
  285. if ($err) {
  286. print "failed!";
  287. } else {
  288. last;
  289. }
  290. }
  291. } else {
  292. $err = -1;
  293. }
  294. if ($err) {
  295. die "Cannot get $latest_version";
  296. } else {
  297. print "ok!\n";
  298. }
  299. $latest_version;
  300. }
  301. sub install_smb {
  302. if ($filename) {
  303. $latest_version = $filename;
  304. } else {
  305. $latest_version = &get_source_code;
  306. }
  307. &decompress;
  308. if ($newinstall) {
  309. open(FH, "ledger-smb.conf.default");
  310. @f = <FH>;
  311. close(FH);
  312. unless ($latex) {
  313. grep { s/^\$latex.*/\$latex = 0;/ } @f;
  314. }
  315. open(FH, ">ledger-smb.conf");
  316. print FH @f;
  317. close(FH);
  318. $alias = $absolutealias = $ENV{'PWD'};
  319. $alias =~ s/.*\///g;
  320. $httpddir = `dirname $httpd`;
  321. if ($confd) {
  322. $httpddir = $confd;
  323. }
  324. chomp $httpddir;
  325. $filename = "ledger-smb-httpd.conf";
  326. # do we have write permission?
  327. if (!open(FH, ">>$httpddir/$filename")) {
  328. open(FH, ">$filename");
  329. $norw = 1;
  330. }
  331. $directives = qq|
  332. Alias /$alias $absolutealias/
  333. <Directory $absolutealias>
  334. AllowOverride All
  335. AddHandler cgi-script .pl
  336. Options ExecCGI Includes FollowSymlinks
  337. Order Allow,Deny
  338. Allow from All
  339. </Directory>
  340. <Directory $absolutealias/users>
  341. Order Deny,Allow
  342. Deny from All
  343. </Directory>
  344. |;
  345. print FH $directives;
  346. close(FH);
  347. print qq|
  348. This is a new installation.
  349. |;
  350. if ($norw) {
  351. print qq|
  352. Webserver directives were written to $filename
  353. Copy $filename to $httpddir
  354. |;
  355. if (!$confd) {
  356. print qq| and add
  357. # Ledger-SMB
  358. Include $httpddir/$filename
  359. to $httpd
  360. |;
  361. }
  362. print qq| and restart your webserver!\n|;
  363. if (!$permset) {
  364. print qq|
  365. WARNING: permissions for templates, users, css and spool directory
  366. could not be set. Login as root and set permissions
  367. # chown -hR :$webgroup users templates css spool
  368. # chmod 771 users templates css spool
  369. |;
  370. }
  371. } else {
  372. print qq|
  373. Webserver directives were written to
  374. $httpddir/$filename
  375. |;
  376. if (!$confd) {
  377. if (!(`grep "^# LedgerSMB" $httpd`)) {
  378. open(FH, ">>$httpd");
  379. print FH qq|
  380. # LedgerSMB
  381. Include $httpddir/$filename
  382. |;
  383. close(FH);
  384. }
  385. }
  386. if (!$>) {
  387. # send SIGHUP to httpd
  388. if ($f = `find /var -type f -name 'httpd.pid'`) {
  389. $pid = `cat $f`;
  390. chomp $pid;
  391. if ($pid) {
  392. system("kill -s HUP $pid");
  393. }
  394. }
  395. }
  396. }
  397. }
  398. # if this is not root, check if user is part of $webgroup
  399. if ($>) {
  400. if ($permset = ($) =~ getgrnam $webgroup)) {
  401. `chown -hR :$webgroup users templates css spool`;
  402. chmod 0771, 'users', 'templates', 'css', 'spool';
  403. `chown :$webgroup ledger-smb.conf`;
  404. }
  405. } else {
  406. # root
  407. `chown -hR 0:0 *`;
  408. `chown -hR $webowner:$webgroup users templates css spool`;
  409. chmod 0771, 'users', 'templates', 'css', 'spool';
  410. `chown $webowner:$webgroup ledger-smb.conf`;
  411. }
  412. chmod 0644, 'ledger-smb.conf';
  413. unlink "ledger-smb.conf.default";
  414. &cleanup;
  415. while ($a !~ /(Y|N)/) {
  416. print qq|\nDisplay README (Y/n) : |;
  417. $a = <STDIN>;
  418. chomp $a;
  419. $a = ($a) ? uc $a : 'Y';
  420. if ($a eq 'Y') {
  421. @args = ("more", "doc/README");
  422. system(@args);
  423. }
  424. }
  425. }
  426. sub decompress {
  427. die "Error: gzip not installed\n" unless ($gzip);
  428. die "Error: tar not installed\n" unless ($tar);
  429. &create_lockfile;
  430. # ungzip and extract source code
  431. print "Decompressing $latest_version ... ";
  432. if (system("gzip -df $latest_version")) {
  433. print "Error: Could not decompress $latest_version\n";
  434. &remove_lockfile;
  435. exit;
  436. } else {
  437. print "done\n";
  438. }
  439. # strip gz from latest_version
  440. $latest_version =~ s/\.gz//;
  441. # now untar it
  442. print "Unpacking $latest_version ... ";
  443. if (system("tar -xf $latest_version")) {
  444. print "Error: Could not unpack $latest_version\n";
  445. &remove_lockfile;
  446. exit;
  447. } else {
  448. # now we have a copy in ledger-smb
  449. if (system("tar -cf $latest_version -C ledger-smb .")) {
  450. print "Error: Could not create archive for $latest_version\n";
  451. &remove_lockfile;
  452. exit;
  453. } else {
  454. if (system("tar -xf $latest_version")) {
  455. print "Error: Could not unpack $latest_version\n";
  456. &remove_lockfile;
  457. exit;
  458. } else {
  459. print "done\n";
  460. print "cleaning up ... ";
  461. `rm -rf ledger-smb`;
  462. print "done\n";
  463. }
  464. }
  465. }
  466. }
  467. sub create_lockfile {
  468. if (-d "$userspath") {
  469. open(FH, ">$userspath/nologin");
  470. close(FH);
  471. }
  472. }
  473. sub cleanup {
  474. unlink "$latest_version";
  475. unlink "$userspath/members.default" if (-f "$userspath/members.default");
  476. &remove_lockfile;
  477. }
  478. sub remove_lockfile { unlink "$userspath/nologin" if (-f "$userspath/nologin") };