
@sugarcrm_tables = (
	"accounts",
	"accounts_audit",
	"accounts_bugs",
	"accounts_cases",
	"accounts_contacts",
	"accounts_opportunities",
	"acl_actions",
	"acl_roles",
	"acl_roles_actions",
	"acl_roles_users",
	"bugs",
	"bugs_audit",
	"calls",
	"calls_contacts",
	"calls_users",
	"calls_leads",
	"campaign_log",
	"campaign_trkrs",
	"campaigns",
	"campaigns_audit",
	"cases",
	"cases_audit",
	"cases_bugs",
	"config",
	"contacts",
	"contacts_audit",
	"contacts_bugs",
	"contacts_cases",
	"contacts_users",
	"cron_remove_documents",
	"currencies",
	"custom_fields",
	"dashboards",
	"document_revisions",
	"documents",
	"documents_accounts",
	"documents_bugs",
	"documents_cases",
	"documents_contacts",
	"documents_opportunities",
	"eapm",
	"eapm_audit",
	"email_marketing",
	"email_marketing_prospect_lists",
	"email_templates",
	"emailman",
	"emails",
	"emails_accounts",
	"emails_bugs",
	"emails_cases",
	"emails_contacts",
	"emails_leads",
	"emails_opportunities",
	"emails_project_tasks",
	"emails_projects",
	"emails_prospects",
	"emails_tasks",
	"emails_users",
	"feeds",
	"fields_meta_data",
	"files",
	"iframes",
	"import_maps",
	"inbound_email",
	"inbound_email_autoreply",
	"job_queue",
	"leads",
	"leads_audit",
	"linked_documents",
	"meetings",
	"meetings_contacts",
	"meetings_users",
	"meetings_leads",
	"notes",
	"oauth_consumer",
	"oauth_nonce",
	"oauth_tokens",
	"opportunities",
	"opportunities_audit",
	"opportunities_contacts",
	"project",
	"project_relation",
	"project_task",
	"project_task_audit",
	"prospect_list_campaigns",
	"prospect_lists",
	"prospect_lists_prospects",
	"prospects",
	"relationships",
	"releases",
	"roles",
	"roles_modules",
	"roles_users",
	"saved_search",
	"schedulers",
	"schedulers_times",
	"sugarfeed",
	"tasks",
	"tracker",
	"upgrade_history",
	"user_preferences",
	"users",
	"users_feeds",
	"users_last_import",
	"users_password_link",
	"users_signatures",
	"vcals",
	"versions",
	"address_book",
	"email_addr_bean_rel",
	"email_addresses",
	"email_cache",
	"emails_beans",
	"emails_email_addr_rel",
	"emails_text",
	"folders",
	"folders_rel",
	"folders_subscriptions",
	"inbound_email_cache_ts",
	"outbound_email",
	"projects_accounts",
	"projects_bugs",
	"projects_cases",
	"projects_contacts",
	"projects_opportunities",
	"projects_products",
	);

# script_sugarcrm_desc()
sub script_sugarcrm_desc
{
return "SugarCRM";
}

sub script_sugarcrm_uses
{
return ( "php" );
}

sub script_sugarcrm_longdesc
{
return "A powerful open-source package for managing customer relationships";
}

# script_sugarcrm_versions()
sub script_sugarcrm_versions
{
return ( "6.5.26" );
}

sub script_sugarcrm_can_upgrade
{
local ($sinfo, $newver) = @_;
if ($newver >= 5.5 && $sinfo->{'version'} < 5.5) {
	return 0;
	}
return 1;
}

sub script_sugarcrm_category
{
return "Commerce";
}

sub script_sugarcrm_php_vers
{
return ( 5 );
}

sub script_sugarcrm_php_fullver
{
local ($d, $ver, $sinfo) = @_;
return "7.4";
}

sub script_sugarcrm_php_modules
{
return ("mysql", "curl");
}

sub script_sugarcrm_php_optional_modules
{
return ("imap");
}

sub script_sugarcrm_dbs
{
return ("mysql");
}

# script_sugarcrm_php_vars(&domain)
# Returns an array of extra PHP variables needed for this script
sub script_sugarcrm_php_vars
{
return ( [ 'safe_mode', 'Off' ],
	 [ 'allow_call_time_pass_reference', 'Off' ],
	 [ 'memory_limit', '64M', '+' ],
	 [ 'upload_max_filesize', '10M', '+' ],
	 [ 'max_execution_time', '120', '+' ] );
}

# script_sugarcrm_params(&domain, version, &upgrade-info)
# Returns HTML for table rows for options for installing SugarCRM
sub script_sugarcrm_params
{
local ($d, $ver, $upgrade) = @_;
local $rv;
local $hdir = &public_html_dir($d, 1);
if ($upgrade) {
	# Options are fixed when upgrading
	local ($dbtype, $dbname) = split(/_/, $upgrade->{'opts'}->{'db'}, 2);
	$rv .= &ui_table_row("Database for SugarCRM tables", $dbname);
	local $dir = $upgrade->{'opts'}->{'dir'};
	$dir =~ s/^$d->{'home'}\///;
	$rv .= &ui_table_row("Install directory", $dir);
	}
else {
	# Show editable install options
	local @dbs = &domain_databases($d, [ "mysql" ]);
	$rv .= &ui_table_row("Database for SugarCRM tables",
		     &ui_database_select("db", undef, \@dbs, $d, "sugarcrm"));
	$rv .= &ui_table_row("Install sub-directory under <tt>$hdir</tt>",
			     &ui_opt_textbox("dir", &substitute_scriptname_template("sugarcrm", $d), 30, "At top level"));
	$rv .= &ui_table_row("Install demo data?",
			     &ui_yesno_radio("demo", 1));
	$rv .= &ui_table_row("Skip install wizard?",
			     &ui_yesno_radio("nowizard", 0));
	}
return $rv;
}

# script_sugarcrm_parse(&domain, version, &in, &upgrade-info)
# Returns either a hash ref of parsed options, or an error string
sub script_sugarcrm_parse
{
local ($d, $ver, $in, $upgrade) = @_;
if ($upgrade) {
	# Options are always the same
	return $upgrade->{'opts'};
	}
else {
	local $hdir = &public_html_dir($d, 0);
	$in{'dir_def'} || $in{'dir'} =~ /\S/ && $in{'dir'} !~ /\.\./ ||
		return "Missing or invalid installation directory";
	local $dir = $in{'dir_def'} ? $hdir : "$hdir/$in{'dir'}";
	local ($newdb) = ($in->{'db'} =~ s/^\*//);
	return { 'db' => $in->{'db'},
		 'newdb' => $newdb,
	 	 'demo' => $in->{'demo'},
	 	 'nowizard' => $in->{'nowizard'},
	         'dir' => $dir,
		 'path' => $in{'dir_def'} ? "/" : "/$in{'dir'}", };
	}
}

# script_sugarcrm_check(&domain, version, &opts, &upgrade-info)
# Returns an error message if a required option is missing or invalid
sub script_sugarcrm_check
{
local ($d, $ver, $opts, $upgrade) = @_;
$opts->{'dir'} =~ /^\// || return "Missing or invalid install directory";
$opts->{'db'} || return "Missing database";
if (-r "$opts->{'dir'}/install.php") {
	return "SugarCRM appears to be already installed in the selected directory";
	}
local ($dbtype, $dbname) = split(/_/, $opts->{'db'}, 2);
foreach my $t (@sugarcrm_tables) {
	local $clash = &find_database_table($dbtype, $dbname, $t);
	$clash && return "SugarCRM appears to be already using the selected database (table $clash)";
	}
$opts->{'demo'} = 1 if (!defined($opts->{'demo'}));
return undef;
}

# script_sugarcrm_files(&domain, version, &opts, &upgrade-info)
# Returns a list of files needed by SugarCRM, each of which is a hash ref
# containing a name, filename and URL
sub script_sugarcrm_files
{
local ($d, $ver, $opts, $upgrade) = @_;
local @files = ( { 'name' => "source",
	   'file' => "SugarCE-$ver.zip",
	   'url' => "http://scripts.virtualmin.com/SugarCE-$ver.zip",
	   'virtualmin' => 1 });
return @files;
}

sub script_sugarcrm_commands
{
return ("unzip", "wget");
}

# script_sugarcrm_install(&domain, version, &opts, &files, &upgrade-info)
# Actually installs SugarCRM, and returns either 1 and an informational
# message, or 0 and an error
sub script_sugarcrm_install
{
local ($d, $version, $opts, $files, $upgrade, $domuser, $dompass) = @_;

# Reject upgrades that cannot be done via Virtualmin, such as 5.5.0a to 5.5.1
if ($upgrade &&
    &compare_versions($upgrade->{'version'}, '5.5.0') >= 0 &&
    &compare_versions($version, '5.5.0') >= 0) {
	return (0, "Minor version upgrades must be done within SugarCRM");
	}

local ($out, $ex);
if ($opts->{'newdb'} && !$upgrade) {
	local $err = &create_script_database($d, $opts->{'db'});
	return (0, "Database creation failed : $err") if ($err);
	}
local ($dbtype, $dbname) = split(/_/, $opts->{'db'}, 2);
local $dbuser = $dbtype eq "mysql" ? &mysql_user($d) : &postgres_user($d);
local $dbpass = $dbtype eq "mysql" ? &mysql_pass($d) : &postgres_pass($d, 1);
local $dbphptype = $dbtype eq "mysql" ? "mysql" : "psql";
local $dbhost = &get_database_host($dbtype, $d);
local $dberr = &check_script_db_connection($dbtype, $dbname, $dbuser, $dbpass);
return (0, "Database connection failed : $dberr") if ($dberr);

# Preserve old config file
local $cfile = "$opts->{'dir'}/config.php";
local $oldcfile = &transname();
if ($upgrade) {
	&copy_source_dest($cfile, $oldcfile);
	}

# Extract tar file to temp dir and copy to target
local $temp = &transname();
local $err = &extract_script_archive($files->{'source'}, $temp, $d,
                                     $opts->{'dir'}, "SugarCE-Full-$ver");
$err && return (0, "Failed to extract source : $err");

# Make sub-directories writable
foreach my $sd ("cache", "custom", "data", "modules") {
	&make_file_php_writable($d, "$opts->{'dir'}/$sd");
	}

local $url = &script_path_url($d, $opts);
if ($upgrade) {
	# Put back original config file
	&copy_source_dest_as_domain_user($d, $oldcfile, $cfile);
	}
else {
	# Make config.php writable
	&make_file_php_writable($d, $cfile);
	$sugarcrm_session_cookie = undef;

	if (!$opts->{'nowizard'}) {
		# First wizard page (language)
		local @params = ( [ "language", "en_us" ] );
		local $err = &call_sugarcrm_wizard_page(\@params, 0, $d, $opts);
		return (-1, "SugarCRM language wizard failed : $err") if ($err);

		# Second page (system check)
		local @params = ( );
		local $err = &call_sugarcrm_wizard_page(\@params, 1, $d, $opts);
		return (-1, "SugarCRM check wizard failed : $err") if ($err);

		# Third page (licence)
		local @params = ( [ "setup_license_accept", 1 ] );
		local $err = &call_sugarcrm_wizard_page(\@params, 2, $d, $opts);
		return (-1, "SugarCRM license wizard failed : $err") if ($err);

		# Fourth page (install type)
		local @params = ( [ "install_type", "Typical" ] );
		local $err = &call_sugarcrm_wizard_page(\@params, 3, $d, $opts);
		return (-1, "SugarCRM install wizard failed : $err") if ($err);

		# Fifth page (Db type)
		local @params = ( [ "setup_db_type", "mysql" ] );
		local $err = &call_sugarcrm_wizard_page(\@params, 4, $d, $opts);
		return (-1, "SugarCRM DB type wizard failed : $err") if ($err);

		# Sixth page (Db connection)
		local @params = ( [ "setup_db_drop_tables", "false" ],
				  [ "setup_db_database_name", $dbname ],
				  [ "setup_db_host_name", $dbhost ],
				  [ "setup_db_admin_user_name", $dbuser ],
				  [ "setup_db_admin_password", $dbpass ],
				  [ "dbUSRData", "provide" ],
				  [ "setup_db_sugarsales_user", $dbuser ],
				  [ "setup_db_sugarsales_password", $dbpass ],
				  [ "setup_db_sugarsales_password_retype", $dbpass ],
				  [ "demoData", $opts->{'demo'} ? "yes" : "no" ],
				  [ "checkDBSettings", "true" ],
				  [ "to_pdf", 1 ],
				  [ "sugar_body_only", 1 ],
				  [ "confirm_drop_tables", "true" ],
				 );
		local $err = &call_sugarcrm_wizard_page(\@params, 5, $d, $opts);
		return (-1, "SugarCRM DB connection wizard failed : $err") if ($err);

		# Seventh page (site config)
		local $surl = $url;
		$surl =~ s/\/$//;
		local @params = ( [ "setup_site_admin_user_name", "admin" ],
				  [ "setup_site_admin_password", $dompass ],
				  [ "setup_site_admin_password_retype", $dompass ],
				);
		local $err = &call_sugarcrm_wizard_page(\@params, 6, $d, $opts);
		return (-1, "SugarCRM site wizard failed : $err") if ($err);

		# Eighth page (confirmation save)
		local @params = ( );
		local $err = &call_sugarcrm_wizard_page(\@params, 7, $d, $opts);
		return (-1, "SugarCRM confirmation wizard failed : $err") if ($err);

		# Fix .htaccess again, as it gets created by the previous step
		&fix_script_htaccess_files($d, $opts->{'dir'});

		# Nineth page (DB creation)
		local @params = ( );
		local $err = &call_sugarcrm_wizard_page(\@params, 8, $d, $opts);
		return (-1, "SugarCRM DB creation wizard failed : $err") if ($err);
		}

	# Setup the Cron job
	if (defined(&create_script_php_cron)) {
		&create_script_php_cron($d, $opts->{'dir'}."/cron.php",
					$opts->{'phpver'}, '*', '*');
		}
	else {
		&create_script_wget_job($d, $url."cron.php", '*', '*');
		}

	if (!$opts->{'nowizard'}) {
		# Allow referrers from Virtualmin
		my $host = $ENV{'HTTP_HOST'};
		$host =~ s/:\d+$//;
		$host ||= $d->{'dom'};
		&open_tempfile_as_domain_user($d, CONFIG,
			">$opts->{'dir'}/config_override.php");
		&print_tempfile(CONFIG, "<?php\n");
		&print_tempfile(CONFIG, "\$sugar_config['http_referer']['list'][] = '$host';\n");
		&print_tempfile(CONFIG, "?>\n");
		&close_tempfile(CONFIG);
		}
	}

# Tell the user about the new install
local $rp = $opts->{'dir'};
$rp =~ s/^$d->{'home'}\///;
return (1, "Initial SugarCRM installation complete. Go to <a target=_blank href='$url'>$url</a> to complete the configuration process.", "Under $rp using $dbtype database $dbname", $url, 'admin', $dompass);
}

# call_sugarcrm_wizard_page(&parameters, step-no, &domain, &opts)
sub call_sugarcrm_wizard_page
{
local ($params, $step, $d, $opts) = @_;
local $params = join("&", map { $_->[0]."=".&urlize($_->[1]) }
			  ( @$params,
			    [ "current_step", $step ],
			    [ "goto", "Next" ] ));
local $ipage = $opts->{'path'}."/install.php";

local ($iout, $ierror);
local (%headers, %gotheaders);
if ($sugarcrm_session_cookie) {
	$headers{'Cookie'} = $sugarcrm_session_cookie;
	}
&post_http_connection($d, $ipage, $params, \$iout, \$ierror, \%headers,
		      \%gotheaders);
if (!$sugarcrm_session_cookie &&
    $gotheaders{'set-cookie'} =~ /(PHPSESSID=\S+);/) {
	$sugarcrm_session_cookie = $1;
	}
if ($ierror) {
	return $ierror;
	}

# This call may have create a .htaccess file with bad permissions .. fix it
&set_permissions_as_domain_user($d, 0755, "$opts->{'dir'}/.htacces");

return undef;
}

# script_sugarcrm_uninstall(&domain, version, &opts)
# Un-installs a SugarCRM installation, by removing it's files
# Returns 1 on success and a message, or 0 on failure and an error
sub script_sugarcrm_uninstall
{
local ($d, $version, $opts) = @_;

# Remove sugarcrm tables from the database
&cleanup_script_database($d, $opts->{'db'}, \@sugarcrm_tables);

# Remove the contents of the target directory
local $derr = &delete_script_install_directory($d, $opts);
return (0, $derr) if ($derr);

# Take out the DB
if ($opts->{'newdb'}) {
	&delete_script_database($d, $opts->{'db'});
	}

# Find and remove the Cron job
&delete_script_wget_job($d, $sinfo->{'url'}."cron.php");
if (defined(&delete_script_php_cron)) {
	&delete_script_php_cron($d, $sinfo->{'dir'}."/cron.php");
	}

return (1, "Deleted SugarCRM directory and tables.");
}

sub script_sugarcrm_stop
{
local ($d, $sinfo) = @_;
&delete_script_wget_job($d, $sinfo->{'url'}."cron.php");
}

sub script_sugarcrm_site
{
return 'http://www.sugarcrm.com/';
}

sub script_sugarcrm_passmode
{
return 2;
}

# script_sugarcrm_realversion(&domain, &opts)
# Returns the real version number of some script install, or undef if unknown
sub script_sugarcrm_realversion
{
local ($d, $opts, $sinfo) = @_;
local $lref = &read_file_lines("$opts->{'dir'}/sugar_version.php", 1);
foreach my $l (@$lref) {
	if ($l =~ /sugar_version\s*=\s*'([0-9A-Za-z\.]+)'/) {
		return $1;
		}
	}
return undef;
}

sub script_sugarcrm_disabled
{
return 1;
}

1;

