<?php

if(!defined('APP_INCLUDE')){ die('invalid inclusion'); }

class SiteProfile {
    var $profileid;				# The unique database identifier for this profile.    
    var $profilename;			# The identifier / name for the profile.
    var $profiletype;           # The type of profile (website, rollup, easylink, maybe others)
    var $confdomain;			# The domain name for this profile.
    var $equivdomains;			# Equivalent domains that are treated the same as the main domain.
    var $tablename;				# The database table name.
    var $defaultfile;			# The default file name (index.php / etc).
    var $logfilefullpath;		# Path to the log files.
    var $splitlogs;				# Are we using split log files.
    var $splitfilter;			# Filename filter if we have multiple file name.s
    var $trackermode;			# Are we using tracker mode?  (vs log files)
    var $skipips;				# List of IPs to skip
    var $skipfiles;				# List of files types to skip
    var $urlparamfilter;		# params in the url that we should ...
    var $urlparamfiltermode;	# "Include" or "Exclude"
    var $googleparams;          # a list of google parameters we care about. If not in the list, it will not be saved
    var $targetfiles;           # "Conversion" files.
    var $visitoridentmethod; 	# What method of user identification are we using?
    var $feedurl;               # the page where your feeds are
    var $feedburneruri;         # your feedburner account url
	var $lastused;				# Timestamp when the profile is last used
	var $facebooklogin;			# Your facebook login email adress	
	var $datamanagerDir;		# sets the data dir or a custom directory where the user wants to store his/her datafiles.
	var $datamanagerLimit;		# Sets the amount of months the profile should keep in the database (default no limit)
	var $datamanagerMaxStorage;	# Set a storage size in MB to keep datafiles at a max storage.  (default 5000)
	var $dateFormat;			# set the date format for the reports of that profile!	
	var $logparsertype;			# your log parser type    
    var $profileloaded;			# Is the profile loaded / found?    
    var $dieonsqlerror;			# If there's a sql error, call "die" and end.  Otherwise, just set the contents in $lastsqlerror and go on.
    var $lastsqlerror;			# If there was a sql error, stick it in this variable.    
    var $tableprefix;

    var $customreportsdir;      # Custom reports directory for this profile  
    var $customreportsonly;     # Only use custom reports for this profile

    var $created;             # is set to 0 or 1. lets you know if the profile is activated or not    
	var $activated;				# is set to 0 or 1. lets you know if the profile is activated or not	
    var $filehistory;
	var $update_status;
	var $sessioncounter;
	var $dashboards;
	
    # stats variables
    var $min_db_timestamp;      # this is the lowest timestamp in the database
    var $max_db_timestamp;      # this is the higgest timestamp in the database
    var $last_update_finished;  # this is the timestamp of the last time update was finished running
    var $firstRequestTimeEver;  # the very first timestamp ever recorded
    var $lastReportUpdate;      # last timestamp that the reports had been updated through update
    var $usage;     
    var $updatehistory;
    var $thirtyday_pageviews;

	var $other_settings;
    var $original;
	
    var $tablename_conversions;
    var $tablename_urls;
    var $tablename_urlparams;
    var $tablename_referrers;
    var $tablename_refparams;
    var $tablename_keywords;
    var $tablename_trackerlog;    
    var $tablename_useragents;    
    var $tablename_crawl;
    var $tablename_merge;
    var $tablename_vlength;
    var $tablename_tlength;
    
    var $targets_sql;
    var $targets;    
    var $importantURLParams;			# An array of records
    var $_importantURLParamsToDelete;	# An array of records to delete    
    var $animate;						# do we want to animate flash graphs ?
    
    var $timezone;                     
    var $loadedfromsession;
	
    var $structure_version;				# What structure version is the profile's data?    
    var $recursive;
    var $ftpserver;
    var $ftpuser;
    var $ftppasswd;
    var $ftpfullpath;
    var $ftpport;
    var $ftpmode;
    var $visittimeout;
	var $includebackup;
    var $caseinsensitiveurls;           # Set every url strtolower when read for import
    var $currency;                      # the currency code or symbol
    var $vidm_custom_cookie;             # a custom cookie to be used as the visitor identification method
    var $patternfilter;                 # if true visitors will be labeled a bot unkless they hit an image,script setc
    var $ipencoding;                    # if true the ipnumber will be anonymized
    
    # Constructor - if you pass a profile name to the constructor    
    function __construct( $ProfileName = null ) {
        global $mysqlprefix ,$session, $validUserRequired, $ipencoding;
        # Initialize the variables.
        $this->profilename = "";
        $this->profiletype = "website";
        $this->confdomain = "";                
        $this->equivdomains = "";
        $this->tablename = "";                
        $this->defaultfile = "";            
        $this->logfilefullpath = "";    
        $this->splitlogs = 0;                    
        $this->splitfilter = "";
        $this->splitfilternegative = "";            
        $this->trackermode = 0;                
        $this->skipips = "";                    
        $this->skipfiles = ".gif, .jpg, .jpeg, .js, .css, .txt, .ico, .swf, .xml, .png, .dll, .svg, .woff, .eot, logaholic/";    
        $this->targetfiles= "";                    
        $this->profileloaded = false;            
        $this->dieonsqlerror = true;        
        $this->lastsqlerror = "";                
        $this->original = [];
        $this->importantURLParams = [];
        $this->_importantURLParamsToDelete = [];
        $this->animate = 0;
        $this->timezone = (function_exists("date_default_timezone_get") ? date_default_timezone_get() : "Etc/GMT+0");
        $this->currency = "$";        
        $this->structure_version = 0;
        $this->visitoridentmethod = VIDM_IPPLUSAGENT;
        $this->vidm_custom_cookie="";
        $this->recursive = 0;  
        $this->caseinsensitiveurls = 0;  
        $this->ftpserver = "";  
        $this->ftpuser = "";  
        $this->ftppasswd = "";  
        $this->ftpfullpath = "";
        $this->ftpmode = 0;
        $this->ftpport = 21;
        $this->visittimeout= "20";
        $this->urlparamfilter= "";
        $this->urlparamfiltermode= "Exclude";
        $this->googleparams="q, start, gclid, as_q, as_epq, as_oq, as _eq, as_sitesearch, as_rq, as_lq";
        $this->feedurl= "";
        $this->feedburneruri= "";	
		$this->facebooklogin = "";
		$this->dateFormat = array(
			"format1" => "d",
			"seperator1" => " ",
			"format2" => "M",
			"seperator2" => " ",
			"format3" => "Y",
			"seperator3" => " ",
			"format4" => ""				
		);			
		$this->logparsertype = "";
		$this->lastused = 0;
		$this->includebackup = false;
        $this->loadedfromsession = false;
		
        $this->customreportsdir = "";
        $this->customreportsonly = 0;   

        $this->activated = 1;
		$this->filehistory = "";
		$this->update_status = "ready";
		$this->sessioncounter = 0;
		$this->dashboards = [];
        $this->other_settings = [];
		$this->updatehistory = [];
        $this->thirtyday_pageviews = 0;
		
		$this->datamanagerDir = getGlobalSetting("datamanagerDirectory",logaholic_dir()."data/");
		$this->datamanagerLimit = 0;	
		$this->datamanagerMaxStorage = 5000;
		 
		$this->tableprefix = $mysqlprefix;
        $this->patternfilter = "true";
        if ($ipencoding==true) {
            $this->ipencoding = 'true';
        } else {
            $this->ipencoding = 'false';
        }
        

		        
        if ($ProfileName) {
			if (@$_SESSION['profilename'] == $ProfileName && isset($_SESSION['profileobject'])) {

				$jp = json_decode($_SESSION['profileobject'], true);
                
				$progress_log = $this->datamanagerDir. $ProfileName ."/{$ProfileName}_update_progress.lwa.log";
                if(file_exists($progress_log)){
                    clearstatcache();
                    $progress_log_time = filemtime($progress_log);
                } else {
                    $progress_log_time = 0;
                }

                if (@$_SESSION['checksum'] != $progress_log_time) {
                    # reload it because data has changed
                    $_SESSION['checksum']= $progress_log_time;
                    $this->Load($ProfileName);                    
                } else {
                    foreach($jp as $key =>$val) {
    					$this->$key = $val;
    				}
    				$this->loadedfromsession = true;
    				$this->profileloaded = true;
                }
			} else {
				$this->Load($ProfileName);
				$this->LogUsage();
			}
		}
				
		if ($validUserRequired) {
			if (!$session->isAdmin() ) {                
				if ( ($session->canAddProfiles() || $session->canEditProfiles()) && ($this->profilename=="newcnf" ||  empty($this->profilename) )) {
					# it's ok
                    
				} else if(!in_array($this->profilename, $session->user_profiles) && !$session->allProfiles  ){                    
                    die('{ "Status" : "Errror" , "Message" : "'. _ACCESS_DENIED .'..." }');
				} else {
                    //die('hiero');
                }
			}
		}		
    }
	function updateLastUsed(){
		global $db;
		$dif = time() - $this->lastused;
		if($dif >= 3600){
			$db->Execute("UPDATE LOW_PRIORITY ".TBL_PROFILES." SET lastused=".time()." WHERE profilename='{$this->profilename}'");
		}
	}

    function SetUpdateStatus($status){
        global $db;
        if($status !== "ready" && $status !== "stop" && $status !== "running"){
            return false;
        }
        $this->update_status = $status;
        $db->Execute("UPDATE LOW_PRIORITY ". TBL_PROFILES . " SET `update_status` = ". $db->Quote($this->update_status) ." WHERE profileid = {$this->profileid}");        
        //$this->Save();
    }

    function GetUpdateStatus(){
        global $db;
        $r = $db->Execute("SELECT update_status FROM ". TBL_PROFILES . " WHERE profileid = {$this->profileid}");
        $data = $r->fetchRow();
        $this->update_status = $data['update_status'];
        return  $this->update_status;
    }

    function GetFromDB($field) {
        global $db;
        $r = $db->Execute("SELECT $field FROM ". TBL_PROFILES . " WHERE profileid = {$this->profileid}");
        $data = $r->fetchRow();
        return $data[$field];        
    }

    function SetInDB($field, $val) {
        global $db;
        $db->Execute("UPDATE LOW_PRIORITY ". TBL_PROFILES . " SET `$field` = ". $db->Quote($val) ." WHERE profileid = {$this->profileid}");
        return $val;
    }

    function SetOtherSettings($name ="",$value=""){
        if(!empty($name)){
            $this->other_settings[$name] = $value;
        }
        $this->Save();
    }

    function GetOtherSettings($name,$default = ""){
    	if(isset($this->other_settings[$name])){
			return $this->other_settings[$name];
		} else {
            return $default;
        }
    }

    function Load( $ProfileName ) {
        global $db, $mysqlprefix,$dateFormat, $running_from_command_line;
        
        $lastsqlerror = "";
        $query = "Select * from ".TBL_PROFILES." where profilename = " . $db->Quote($ProfileName);
        $result = $db->Execute($query) or $this->_sqlError("Couldn't query profile table: " . $db->ErrorMsg());
        
        if ($profile_row = $result->FetchRow()) {
            $this->profileloaded = true;
            $this->profileid = $profile_row["profileid"];
            $this->profilename = $profile_row["profilename"];
            $this->confdomain = $profile_row["confdomain"];
            $this->equivdomains = $profile_row["equivdomains"];
            $this->tablename = $profile_row["tablename"];
            $this->defaultfile = $profile_row["defaultfile"];
            $this->logfilefullpath = $profile_row["logfilefullpath"];
            $this->splitlogs = $profile_row["splitlogs"];
            $this->splitfilter = $profile_row["splitfilter"];
            $this->splitfilternegative = $profile_row["splitfilternegative"]; 
            $this->trackermode = $profile_row["trackermode"];
            $this->skipips = $profile_row["skipips"];
            $this->skipfiles = $profile_row["skipfiles"];
            $this->targetfiles = $profile_row["targetfiles"];
            $this->animate = $profile_row["animate"];
            $this->timezone = $profile_row["timezone"];
            $this->structure_version = $profile_row["structure_version"];
            $this->visitoridentmethod = $profile_row["visitoridentmethod"];
            $this->recursive = $profile_row["recursive"];
            $this->ftpserver = $profile_row["ftpserver"];
            $this->ftpuser = $profile_row["ftpuser"];
            $this->ftppasswd = $profile_row["ftppasswd"];
            $this->ftpfullpath = $profile_row["ftpfullpath"];
            $this->visittimeout = $profile_row["visittimeout"];
            $this->urlparamfilter = $profile_row["urlparamfilter"];
            $this->urlparamfiltermode = $profile_row["urlparamfiltermode"];
            $this->googleparams = $profile_row["googleparams"];
            $this->feedurl = $profile_row["feedurl"];
            $this->feedburneruri = $profile_row["feedburneruri"];
            $this->lastused = $profile_row["lastused"];            
            $this->activated = $profile_row["activated"];
            $this->filehistory = $profile_row["filehistory"];
            $this->update_status = $profile_row["update_status"];
            $this->sessioncounter = $profile_row["sessioncounter"];

			$this->dashboards = json_decode($profile_row["dashboards"],true);
            if(empty($this->dashboards)){
                $this->dashboards = [];
            }

            # protect against recursive == null bug in database
            if (is_null($this->recursive)) {
                $this->recursive = 0;
            }

            # This variable is private break it down for usage in the software 
            $stats = json_decode($profile_row["stats"],true);
            
            $this->min_db_timestamp = (empty($stats['min_db_timestamp'])) ? 0 : $stats['min_db_timestamp'];
            $this->max_db_timestamp = (empty($stats['max_db_timestamp'])) ? 0 : $stats['max_db_timestamp'];

            $this->last_update_finished = $stats['last_update_finished'];
            $this->firstRequestTimeEver = $stats['firstRequestTimeEver'];
            $this->lastReportUpdate = $stats['lastReportUpdate'];
            $this->usage = $stats['usage'];
            $this->created = (isset($stats['created'])) ? $stats['created'] : 0;
            $this->updatehistory = (empty($stats['updatehistory'])) ? [] : $stats['updatehistory'];
            $this->thirtyday_pageviews = (isset($stats['thirtyday_pageviews'])) ? $stats['thirtyday_pageviews'] : 0;
            # Unpack profile settings that used to be in the globalsettings table
			$this->other_settings = json_decode($profile_row["other_settings"],true);
            
			# Check if the following settings are set.. if not set a default setting for it.
            $this->facebooklogin = $this->GetOtherSettings('facebookLogin',false);
			$this->includebackup = $this->GetOtherSettings('includebackup',false);
            
			$this->datamanagerDir = $this->GetOtherSettings('datamanagerDirectory',getGlobalSetting("datamanagerDirectory",logaholic_dir()."data/"));
			$this->datamanagerLimit = $this->GetOtherSettings('datamanagersettings',0);
			$this->datamanagerMaxStorage = $this->GetOtherSettings('datamanagerStorageSize',5000);

            $this->customreportsdir = logaholic_dir()."files/{$this->profilename}_reports/";
            $this->customreportsonly = $this->GetOtherSettings('customreportsonly',0);

            $this->caseinsensitiveurls = $this->GetOtherSettings('caseinsensitiveurls', getGlobalSetting("ToggleUrlInsensitiveImport",0) );

            $this->logparsertype = $this->GetOtherSettings('logparsertype',"auto");
            $this->ftpmode = $this->GetOtherSettings('ftpmode',0);
            $this->ftpport = $this->GetOtherSettings('ftpport',21);
            
            $this->dateFormat = $this->GetOtherSettings('profileDateFormat',getGlobalSetting("profileDateFormat",$dateFormat));
            $this->dateFormat = json_decode($this->dateFormat, true);

            $this->currency = $this->GetOtherSettings('currency', '$');
            $this->vidm_custom_cookie = $this->GetOtherSettings('vidm_custom_cookie', '');
            $this->profiletype = $this->GetOtherSettings('profiletype', $this->profiletype);
            $this->patternfilter = $this->GetOtherSettings('patternfilter', $this->patternfilter);
            $this->ipencoding = $this->GetOtherSettings('ipencoding', $this->ipencoding);
		
			# Set the tablenames
			$this->tablename_conversions = $this->tablename . "_conversions";
            $this->tablename_urls = $this->tablename . "_urls";
            $this->tablename_urlparams = $this->tablename . "_urlparams";
            $this->tablename_referrers = $this->tablename . "_referrers";
            $this->tablename_refparams = $this->tablename . "_refparams";
            $this->tablename_keywords = $this->tablename . "_keyword";
            $this->tablename_visitorids = $this->tablename . "_visitorids";
            $this->tablename_trackerlog = $this->tablename . "_trackerlog";
            $this->tablename_screenres = $this->tablename . "_screenres";
            $this->tablename_colordepth = $this->tablename . "_colordepth";
            $this->tablename_useragents = $this->tablename . "_useragents";
            $this->tablename_crawl = $this->tablename . "_crawl";
            $this->tablename_merge = $this->tablename . "_merge";
            $this->tablename_gifdata = $this->tablename . "_gifdata";
            $this->tablename_vlength = $this->tablename . "_vlength";
            $this->tablename_tlength = $this->tablename . "_tlength";
			
            # Parse out the target page list so it can be used in a query.            
			$t = explode(",",$this->targetfiles);
            # clean up the array
			$this->targets = [];
			foreach ($t as $thistarget) {
                if ($thistarget > "") {
                    $this->targets[] = trim($thistarget);
                }
            }
						
			$this->targets_sql="";
            foreach ($this->targets as $thistarget) {
                if ($thistarget > "") {
                    $this->targets_sql .= " u.url=".$db->Quote(trim($thistarget))." or";
                }
            }
            if ($this->targets_sql > "") {
                $this->targets_sql="(".substr($this->targets_sql,0,-3).")";
            } else {
                # No targets, so don't return any rows when this is stuck into a query...
                $this->targets_sql = " (0) ";
            }
            $result->Close();
            
            # Load any important URL parameters.
            $this->importantURLParams = [];
			# Order it by the parameter ID to make things consistent
            $query = "Select * from ".TBL_IMPORTANT_URL_PARAMS." where profileid = {$this->profileid} order by paramid";
            $result = $db->Execute($query);
            
            while ($importantParamsRow = $result->FetchRow()) {
                $this->importantURLParams[] = $importantParamsRow;
            }
            $result->Close();
            $this->_importantURLParamsToDelete = [];
                       
            
        } else {
            $this->profilename = $ProfileName;
            $this->profileloaded = false;
            $this->profileid = null;
            $this->importantURLParams = [];
            $this->_importantURLParamsToDelete = [];
        }
		
		# save the profile object in the session for fast access
		foreach($this as $key => $val) {
			$p[$key] = $val;
		}
		if ($ProfileName!="newcnf" && !empty($this->profileid)) {
			$_SESSION['profilename'] = $ProfileName;		
			$_SESSION['profileobject'] = json_encode($p);
		}

		# update the last used timestamp to now
        if (!$running_from_command_line) {
		  $this->updateLastUsed();
        }
    }
    
    function _sqlError($errorMessage) {
        $this->lastsqlerror = $errorMessage;
        if ($this->dieonsqlerror) { die($errorMessage); }
    }
    
    # Private method that saves or inserts.
    function _privateSave($newRecord) {
        global $db;

        # Build the assignment stuff.
        $record["profilename"] = $this->profilename;
        $record["confdomain"] = $this->confdomain;
        $record["equivdomains"] = $this->equivdomains;
        $record["tablename"] = $this->tablename;
        $record["defaultfile"] = $this->defaultfile;
        $record["logfilefullpath"] = $this->logfilefullpath;
        
		if (is_dir($this->logfilefullpath)) {
			$this->splitlogs = 1;	
		}
        $record["splitlogs"] = $this->splitlogs;
        $record["splitfilter"] = $this->splitfilter;
        $record["splitfilternegative"] = $this->splitfilternegative;
        $record["trackermode"] = $this->trackermode;
        $record["skipips"] = $this->skipips;
        $record["skipfiles"]= $this->skipfiles;
        $record["targetfiles"] = $this->targetfiles;
        $record["animate"] = $this->animate;
        $record["timezone"] = $this->timezone;
        $record["structure_version"] = $this->structure_version;
        $record["visitoridentmethod"] = $this->visitoridentmethod;
        $record["recursive"] = $this->recursive;
        $record["ftpserver"] = $this->ftpserver;
        $record["ftpuser"] = $this->ftpuser;
        $record["ftppasswd"] = $this->ftppasswd; 
        $record["ftpfullpath"] = $this->ftpfullpath;
        $record["visittimeout"] = $this->visittimeout;
        $record["urlparamfilter"] = $this->urlparamfilter;
        $record["urlparamfiltermode"] = $this->urlparamfiltermode;
        $record["googleparams"] = $this->googleparams;
        $record["feedurl"] = $this->feedurl;
        $record["feedburneruri"] = $this->feedburneruri;  
        $record["activated"] = $this->activated;  
        $record["filehistory"] = $this->filehistory;  
        $record["update_status"] = $this->update_status;  
        $record["sessioncounter"] = $this->sessioncounter;  

        if (isset($this->usage)) {
            if( count( json_decode($this->usage) ) > 200 ){
                $this->usage = "[]";
            }
        }

        # if new add created to stats
        if ($newRecord) {
            $this->created = time();
        }

        $record["stats"] = json_encode(array(
            'min_db_timestamp' => $this->min_db_timestamp,
            'max_db_timestamp' => $this->max_db_timestamp,
            'last_update_finished' => $this->last_update_finished, 
            'firstRequestTimeEver' => $this->firstRequestTimeEver,
            'lastReportUpdate' => $this->lastReportUpdate, 
            'usage' => $this->usage,
            'created' => $this->created,
            'updatehistory' => $this->updatehistory,
            'thirtyday_pageviews' => $this->thirtyday_pageviews
        ));  

        $this->other_settings["logparsertype"] = @$this->logparsertype;
        $this->other_settings["includebackup"] = $this->includebackup;

        $this->other_settings["ftpmode"] = $this->ftpmode;
        $this->other_settings["ftpport"] = $this->ftpport;

        $this->other_settings["customreportsonly"] = $this->customreportsonly;
        $this->other_settings["caseinsensitiveurls"] = $this->caseinsensitiveurls;

        $this->other_settings["currency"] = $this->currency;
        $this->other_settings["vidm_custom_cookie"] = $this->vidm_custom_cookie;
        $this->other_settings["profiletype"] = $this->profiletype;
        $this->other_settings["patternfilter"] = $this->patternfilter;
        $this->other_settings["ipencoding"] = $this->ipencoding;

        $record["other_settings"] = json_encode($this->other_settings);  
        
        $record["dashboards"] = json_encode($this->dashboards);  
		
        if ($newRecord) {
            if (!empty($record["tablename"])) {
				$this->TablenameCheck();
				$record["tablename"] = $this->tablename;
			}

            try{
                @$r = $db->AutoExecute(TBL_PROFILES, $record, "INSERT");
                if(!$r){
                    throw new Exception($db->ErrorMsg());
                }

            } catch (Exception $e) {
                $msg = $e->getMessage();
                # Overwrite the message if it is one we are expecting to be possible
                if($msg == "Duplicate entry '{$this->profilename}' for key '_logaholic_Profiles_profilename'"){
                    $msg = "Profile <b>{$this->profilename}</b> already exists.";
                }

                die(json_encode(array("Status" => "Error", "Message" => $msg)));
            }

            $this->profileid = $db->Insert_ID();
            if (empty($record["tablename"])) {
                $this->tablename = $this->tableprefix."p".$this->profileid;
                $this->_privateSave(false);
                
                # create datafiles reports directory
                $dir1 = $this->datamanagerDir.$this->profilename;
                $dir2 = $dir1 ."/reports";
            
                if (!file_exists($dir1)) {
                    if (@_LOGAHOLIC_EDITION == 4 || LOGAHOLIC_BASE_EDITION == "cPanel Edition") {
                        SwitchSystemUser("cpanellogaholic");
                    }
                    mkdir($dir1); 
                    set_permissions($dir1);
                }
                if (!file_exists($dir2)) {   
                    if (@_LOGAHOLIC_EDITION == 4 || LOGAHOLIC_BASE_EDITION == "cPanel Edition") {
                        SwitchSystemUser("cpanellogaholic");
                    }
                    mkdir($dir2); 
                    set_permissions($dir2);
                }

                $this->setDefaultDashboard();
                return;
            }
        } else {
		
			# check if the new profilename doesnt already exists
			$name_check = $db->Execute("SELECT profilename FROM ".TBL_PROFILES." WHERE profilename =".$db->Quote($this->profilename)." AND profileid != {$this->profileid} LIMIT 1");
            $exist = $name_check->fetchRow();
			
			if(!empty($exist)){
				$this->_sqlError("Can't overwrite a profilename that already exists!");
				return;
			} else {			
				# Pre check and actions if profilename is changed.
				$id_check = $db->Execute("SELECT profilename FROM ".TBL_PROFILES." WHERE profileid = " . $this->profileid);
				while($n = $id_check->fetchRow()){
					if($this->profilename == $n["profilename"]){
						# No change in name.. Nothing to do here..
					} else {
						# Change in name. Rename all settings..
						$this->RenameAllProfileSettings($n["profilename"],$this->profilename);

                        # Some settings might have changed now so reset those records
                        $record["dashboards"] = json_encode($this->dashboards);
					}
				}	
			}		
			
			# Check the tablename
			$this->TablenameCheck();
			$record["tablename"] = $this->tablename;
			
            if (!$this->profileid) { $this->_sqlError("Can't save profile - no profile id."); }
            $db->AutoExecute(TBL_PROFILES, $record, "UPDATE", "profileid = " . $this->profileid);
            $affected_row_count = $db->Affected_Rows();
            if ($affected_row_count != 1) { 
                # If no rows were affected, then it may be because no changes were made.  Let's just 
                # do a quick and dirty check to make sure that we can actually find our record, though,
                # because maybe the record can't be found.
                $exist_check = $db->Execute("select profileid from ".TBL_PROFILES." where profileid = ".$this->profileid);
                if ($exist_check->RecordCount() != 1) {
                    $this->_sqlError("Error updating profile, profile ID ".$this->profileid." can't be found.");
                }
            }
            # now lets check to see if the profile was RENAMED, if so, we might need to rename the tables as well
            if (isset($_REQUEST['editconf'])) {
                if ($_REQUEST['editconf']!=$this->profilename) {
                    # the name has changed. Is the tablename the same as the profilename ? 
                    # if so, we have to rename the tables to the new name. If tablename is 'pX' based (which it is on all modern installs), we can skip this
                    if ($this->profilename == $this->tablename) {
                        $this->renameTables($_REQUEST['editconf'],$this->profilename);                        
                    }
                }
            }  
            
        }
        
        # Don't use foreach to iterate object lists.
        for ($param_loop = 0; $param_loop < $this->getUrlParamCount(); $param_loop ++) {
            
            $this_record = &$this->getUrlParamByIndex($param_loop);
            
            # Build the assignment stuff.
            $record = [];
            $record["profileid"] = $this->profileid;
            $record["filename"] = $this_record["filename"];
            $record["nameisregex"] = ($this_record["nameisregex"] ? "1" : "0");
            $record["importantparams"] = $this_record["importantparams"];
            
            if (!$this_record["paramid"]) {
                if ($this_record["filename"]) {
                    $db->AutoExecute(TBL_IMPORTANT_URL_PARAMS, $record, "INSERT");
                    $this_record["paramid"] = $db->Insert_ID();
                }
            } else {
                # Do a paramid + profileid check, just to make sure that someone can't update a different profile's settings by changing paramids.
                $db->AutoExecute(TBL_IMPORTANT_URL_PARAMS, $record, "UPDATE", "paramid = " . $this_record["paramid"] . " and profileid = " . $this->profileid);
                $affected_row_count = $db->Affected_Rows();
                if ($affected_row_count != 1) { 
                    # If no rows were affected, then it may be because no changes were made.  Let's just 
                    # do a quick and dirty check to make sure that we can actually find our record, though,
                    # because maybe the record can't be found.
                    $exist_check = $db->Execute("select profileid, paramid from ".TBL_IMPORTANT_URL_PARAMS." where paramid = ".$this_record["paramid"]);
                    if ($exist_check->RecordCount() != 1) {
                        $this->_sqlError("Error updating important URL parameters, param ID ".$this_record["paramid"]." can't be found.");
                    }
                }
            }
        }
		
        # Delete all the appropriate ones.
        # Don't use foreach to iterate object lists.
        for ($param_loop = 0; $param_loop < count($this->_importantURLParamsToDelete); $param_loop ++) {
            $this_record = &$this->_importantURLParamsToDelete[$param_loop];
			if(!empty($this_record["paramid"])){
				$query = "DELETE from ".TBL_IMPORTANT_URL_PARAMS." where paramid = " . $this_record["paramid"] . " and profileid = " . $this->profileid;            
				$db->Execute($query);
			}
        }
        
        # insert the default segmentation filters if we haven't already done so.
        $this->insertDefaultSegments();
		
		
        if (!$this->lastsqlerror) {
            $this->Load($this->profilename);
        }
    }
    
	function TablenameCheck(){	
		preg_match('/^[a-zA-Z0-9_]{1,64}$/', $this->tablename,$matches);
		if(empty($matches)){
			$this->tablename = $this->tableprefix."p".$this->profileid;
			return false;
		} else {
			return true;
		}
	}
	
    function Save() {
        $cd = logaholic_dir();
        //session_save_path("{$cd}files/sessions");
        @session_start();
        
        if ($this->profileid) {
            $this->_privateSave(false);
        } else {
            $this->_privateSave(true);
        }
        @session_write_close();
    }
    
    function SaveAsNewProfile() {
        $this->_privateSave(true);
    }
    
    /**
    * create a new parameter / url set in the array.
    */     
    function &getUrlParamNew() {
        $this->importantURLParams[] = array("paramid" => null, "filename" => null, "nameisregex" => null, "importantparams" => null);
        return $this->importantURLParams[$this->getUrlParamCount()-1];
    }
    
    /**
    * Return the count of important URLParams
    */     
    function getUrlParamCount() {
        return count($this->importantURLParams);
    }
    
    
    /**
    * Return a *reference* to the array index passed in.  If you do a byreference variable assignment of this
    * function, then you can edit the values of the returned array and they will automatically be saved.
    * @param integer Index The 0-based index of which record to return.
    */     
    function &getUrlParamByIndex($index) {
        return $this->importantURLParams[$index];
    }
    
    /**
    * Delete a record for the important url parameters list.
    * @param integer Index The 0-based index of which record to delete.
    */     
    function deleteUrlParams($index) {
        $this->_importantURLParamsToDelete[] = $this->getUrlParamByIndex($index);  # not by reference, since we're about to kill it.
        for ($param_loop = $index+1; $param_loop < $this->getUrlParamCount(); $param_loop ++) {
            $this->importantURLParams[$param_loop-1] = $this->importantURLParams[$param_loop]; # not by reference.
        }
        array_pop($this->importantURLParams);
    }
    
    function insertDefaultSegments() {
        global $db;
        $check = "select * from `".TBL_TRAFFIC_SOURCES."` where profileid = '{$this->profileid}' and sourcename='New Visitors'";
        $result = $db->Execute($check);
        if ($data = $result->FetchRow()) {
            # we have something , we'll assume we already did this  
        } else {
            # lets insert the default segmentation filters
            $start  = "INSERT INTO `".TBL_TRAFFIC_SOURCES."` SET profileid = '{$this->profileid}', ";
            $db->Execute($start. "sourcename = 'Google Adwords Ad', sourcecondition = 'params LIKE \'?gclid=%\'', category='Marketing Campaigns'");
            $db->Execute($start. "sourcename = 'Google Search Ad', sourcecondition = 'params LIKE \'%gclid=%\' AND referrer LIKE \'https://www.google.%\'', category='Marketing Campaigns'"
            );
            $db->Execute($start. "sourcename = 'Google Content Ad', sourcecondition = 'referrer LIKE \'[G]%\'', category='Marketing Campaigns'");
            $db->Execute($start. "sourcename = 'Yahoo Search Marketing', sourcecondition = 'params LIKE \'?OVRAW=%\'', category='Marketing Campaigns'");
            
            $db->Execute($start. "sourcename = 'New Visitors', sourcecondition = 'url =\'x\'', category='Visitor Profiling'");
            $db->Execute($start. "sourcename = 'Return Visitors', sourcecondition = 'url =\'x\'', category='Visitor Profiling'");
            $db->Execute($start. "sourcename = 'Mobile Visitors', sourcecondition = 'is_mobile =\'1\'', category='Visitor Profiling'");
            
            $db->Execute($start. "sourcename = 'US Visitors', sourcecondition = 'country =\'US\'', category='Geographic Segments'");
            $db->Execute($start. "sourcename = 'Rest of World', sourcecondition = 'country !=\'US\'', category='Geographic Segments'");
        }
        
    }
    
    /**
    * @desc This function renames the profiles mysql tables when a profile gets renamed
    */
    function renameTables($old,$new) {
        global $db;
		
		if (!$this->isValidSQLResourceName($old) || !$this->isValidSQLResourceName($new)) {
            echo "Invalid Table";
            exit();
        }
        
        # first rename the main table
        $q = "RENAME TABLE $old to $new";
        $db->Execute($q);
        
        # now get the other tables and rename them
        $tables = $db->Execute("show tables like '{$old}\_%'");
        while ($table=$tables->FetchRow()) {
            # old table name
            $ot = $table[0];
            # new table name
            $nt = str_ireplace($old,$new,$ot);
            # rename it
            $q = "RENAME TABLE $ot to $nt"; 
            $db->Execute($q);  
        }
        
    }    
    
	function isValidSQLResourceName($input) {
		$regex = '/[^a-zA-Z0-9_]/';
		return (preg_match($regex, $input)) ? false : true;
	}
	
    /**
    * @desc This function copies a profile
    */
    function copyProfile($target,$copy_data=false) {
        
        # first check if we've provided a new name
        if ($this->profilename==$target) {
            echo "You must provide a different name!";
            exit();                
        } elseif (!$this->isValidSQLResourceName($target)) {
            echo "Invalid profile target.";
            exit();
        }
        
        # get rid of the profileid
        unset($this->profileid);
        
        # change the name        
        $this->profilename=$target;
        
        # remember the old tablename in case we need to copy the data
        $source = $this->tablename;
        
        # clear the tablename
        $this->tablename="";
        
        # save it
        $this->_privateSave(true);
        
        # copy data or just create tables
        if ($copy_data==true) {
            $this->copyDataTables($source,$target);    
        } else {
            $newprofile = new SiteProfile($target);
            createDataTable($newprofile);
        }          
    }
    
    
    /**
    * @desc This function makes a copy of all of a profiles mysql tables
    */
    function copyDataTables($source,$target) {
        global $db;
        set_time_limit(86400);
        ob_start();
                
		if (!$this->isValidSQLResourceName($target) || !$this->isValidSQLResourceName($source)) {
            echo "Invalid Table";
            exit();
        }
		
        # first copy the main table
        $q = "CREATE OR REPLACE TABLE  $target LIKE $source";
        $db->Execute($q);
        echo "<hr>".$q."<br>"; lgflush();
        $this->copyTable($source,$target);
        
        
        //$q = "ALTER TABLE $target DISABLE KEYS";
        //$db->Execute($q);
        //echo "<hr>".$q."<br>"; lgflush(); 
        
        //$this->copyTable($source,$target);      
        
        //$q = "ALTER TABLE $target ENABLE KEYS";
        //$db->Execute($q);
        //echo "<hr>".$q."<br>"; lgflush();        
        //exit();
        # now get the other tables and copy them
        echo "show tables like '{$source}\_%'";
        $tables = $db->Execute("show tables like '{$source}\_%'");
        while ($table=$tables->FetchRow()) {
            # old table name
            $ot = $table[0];
            # new table name
            $nt = str_replace($source,$target,$ot);
            # copy it
            $q = "CREATE TABLE $nt LIKE $ot";
            $db->Execute($q);
            echo "<hr>".$q."<br>"; lgflush();
            
            $this->copyTable($ot,$nt);
        }
    }
	
        
    function copyTable($source,$target) {
        global $db;
        $q = "SELECT COUNT(*) FROM $source";
        $result = $db->Execute($q);
        $data = $result->FetchRow();
        $rows = $data[0];           
        $i=0;
        $limit=50000;
        while ($i <= $rows) {
            echo "inserting $i to ".($i+$limit)." in $target...<br>\n";
            $db->Execute("INSERT INTO $target SELECT * FROM $source limit $i,$limit"); lgflush();
            $i=$i+$limit;                            
        }
            
    }
	
	# rename profilename from bla to bleh
	function RenameAllProfileSettings($old,$new){
		global $db;
		# Rename global settings should no longer be needed because it is saved in the profile table row 
		
		# Edit the upload dir
		$dir = getGlobalSetting("upload_dir", logaholic_dir()."files/");
		if(file_exists($dir.$old)){
			rename($dir.$old, $dir.$new);
		}
		
		$dataManDir = getGlobalSetting("datamanagerDirectory",logaholic_dir()."data/");
		if(file_exists($dataManDir."/".$old)){
			rename($dataManDir.$old, $dataManDir.$new);
		}
		
		$dur = "_update_duration.lwa.log";
		if(file_exists($dataManDir.$new."/".$old.$dur)){
			rename($dataManDir.$new."/".$old.$dur, $dataManDir.$new."/".$new.$dur);
		}
		
		$pro = "_update_progress.lwa.log";
		if(file_exists($dataManDir.$new."/".$old.$pro)){
			rename($dataManDir.$new."/".$old.$pro, $dataManDir.$new."/".$new.$pro);
		}

        # rename profilename in dashboards
        foreach ($this->dashboards as $name => $options) {
            if($options['Profile'] == $old){
                $vals = json_decode($options['Value'],true);
                foreach ($vals['reports'] as $rk => $row) {
                    foreach ($row as $k => $r) {
                        $str = str_replace("reports.php?", "",$r['url']);
                        parse_str($str, $output);

                        $output['conf'] = $new;

                        # overwrite profileselector setting?
                        if(!empty($output['profileselector']) && $output['profileselector'] == $old){
                            $output['profileselector'] = $new;
                        }

                        $new_params = http_build_query($output);
                        $vals['reports'][$rk][$k]['url'] = "reports.php?" . $new_params;
                    }
                }

                $this->dashboards[$name]['Value'] = json_encode($vals);
                $this->dashboards[$name]['Profile'] = $new;
            }
        }
	}
	
	function setDefaultDashboard() {
        global $cm;
		$value = '{
            "name":"Default"
            ,"description":"This is an default desktop"
            ,"icon":"00"
            ,"startup":"on"
            ,"minis": ["_MINI_TOTAL_VISITS","_MINI_CONVERSION_RATE","_MINI_NEW_VS_RETURNING","_MINI_BOUNCE_RATE"]
            ,"reports":[
                [],
                [
                    {
                        "label":"_VISITORS_PER_DAY"
                        ,"name":"'. _VISITORS_PER_DAY .'"
                        ,"url":"reports.php?conf='.$this->profilename.'&labels=_VISITORS_PER_DAY&trafficsource=0"
                    },
                    {
                        "label":"_TOP_COUNTRIES_CITIES"
                        ,"name":"'. _TOP_COUNTRIES_CITIES .'"
                        ,"url":"reports.php?conf='.$this->profilename.'&labels=_TOP_COUNTRIES_CITIES&trafficsource=0&limit=10"
                    },
                    {
                        "label":"_TOP_PAGES"
                        ,"name":"'. _TOP_PAGES .'"
                        ,"url":"reports.php?conf='.$this->profilename.'&labels=_TOP_PAGES&trafficsource=0&searchmode=like&search=&limit=10"
                    },
                    {
                        "label":"_TOP_KEYWORDS","name":"'. _TOP_KEYWORDS .'"
                        ,"url":"reports.php?conf='.$this->profilename.'&labels=_TOP_KEYWORDS&trafficsource=0&searchmode=like&search=&limit=10"
                    }
                ],
                [
                    {
                        "label":"_TRAFFIC_BREAKDOWN"
                        ,"name":"'. _TRAFFIC_BREAKDOWN .'"
                        ,"url":"reports.php?conf='.$this->profilename.'&labels=_TRAFFIC_BREAKDOWN"
                    },
                    {
                        "label":"_TOP_CONTINENTS"
                        ,"name":"'. _TOP_CONTINENTS .'"
                        ,"url":"reports.php?conf='.$this->profilename.'&labels=_TOP_CONTINENTS"
                    },
                    {
                        "label":"_OVERALL_PERFORMANCE","name":"'. _OVERALL_PERFORMANCE .'"
                        ,"url":"reports.php?conf='.$this->profilename.'&labels=_OVERALL_PERFORMANCE"
                    },
                    {
                        "label":"_TOP_REFERRERS"
                        ,"name":"'. _TOP_REFERRERS .'"
                        ,"url":"reports.php?conf='.$this->profilename.'&labels=_TOP_REFERRERS&trafficsource=0&searchmode=like&search=&limit=10"
                    },
                    {
                        "label":"_COMPARE_DAYS"
                        ,"name":"'. _COMPARE_DAYS .'"
                        ,"url":"reports.php?conf='.$this->profilename.'&labels=_COMPARE_DAYS&trafficsource=0"
                    }
                ]
            ]
        }';
        if(!empty($cm) && method_exists($cm,'setDefaultDashboard') ){
            $value = $cm->setDefaultDashboard($this->profilename);
        }

		$this->dashboards[$this->profilename.".dashboards.Default"] = array(
            "Name" => $this->profilename.".dashboards.Default"
            ,"Profile" => $this->profilename
            ,"Value" => $value
        );
        $this->Save();
        $this->AddNewsDashboard();
	}

    function AddNewsDashboard() {        
        $value = '{
            "name":"'._NEWS.'"
            ,"description":"News on changes in your traffic based on trends"
            ,"icon":"00"
            ,"startup":"off"
            ,"minis": ["_MINI_VISITS_TRENDS","_MINI_CONVERSION_RATE","_MINI_PAGES_PER_USER","_MINI_BOUNCE_RATE"]
            ,"reports":[
                [],
                [
                    {
                        "label":"_NEWS"
                        ,"name":"'. _NEWS .'"
                        ,"url":"reports.php?conf='.$this->profilename.'&labels=_NEWS"
                    }                    
                ],
                [
                     {
                        "label":"_VISITORS_PER_DAY"
                        ,"name":"'. _VISITORS_PER_DAY .'"
                        ,"url":"reports.php?conf='.$this->profilename.'&labels=_VISITORS_PER_DAY&trafficsource=0"
                    },
                    {
                        "label":"_PERFORMANCE_TRENDS"
                        ,"name":"'. _PERFORMANCE_TRENDS.'"
                        ,"url":"reports.php?conf='.$this->profilename.'&labels=_PERFORMANCE_TRENDS"
                    },
                    {
                        "label":"_COUNTRY_TRENDS"
                        ,"name":"'. _COUNTRY_TRENDS .'"
                        ,"url":"reports.php?conf='.$this->profilename.'&labels=_COUNTRY_TRENDS"
                    },
                    {
                        "label":"_OVERALL_PERFORMANCE"
                        ,"name":"'. _OVERALL_PERFORMANCE .'"
                        ,"url":"reports.php?conf='.$this->profilename.'&labels=_OVERALL_PERFORMANCE"
                    },
                    {
                        "label":"_PAGE_LOAD_TIME"
                        ,"name":"'. _PAGE_LOAD_TIME .'"
                        ,"url":"reports.php?conf='.$this->profilename.'&labels=_PAGE_LOAD_TIME"
                    },
                    {
                        "label":"_PAGE_SCROLL_DEPTH"
                        ,"name":"'. _PAGE_SCROLL_DEPTH .'"
                        ,"url":"reports.php?conf='.$this->profilename.'&labels=_PAGE_SCROLL_DEPTH"
                    }
                ]
            ]
        }';

        $this->dashboards[$this->profilename.".dashboards.News"] = array(
            "Name" => $this->profilename.".dashboards.News"
            ,"Profile" => $this->profilename
            ,"Value" => $value
        );
        $this->Save();
    }
	
	function LogUsage() {
		$usage = (isset($this->usage)) ? $this->usage : "[]";
		$usage = json_decode($usage, true);
		
		if(!is_array($usage)) {
			$usage = [];
		}
		
		if(in_array(date('Ymd'), $usage) == false) {
			$usage[] = date('Ymd');			
			$usage = json_encode($usage);
			$this->usage = $usage;
		}
	}
	
	function ProfileActiveCheck(){		
		# Check if the profile has been activated( if not kill the script).
		if($this->activated == 0){
			echo  '{"Status": "Error", "Message": "This profile must be activated first."}';
            //   "{}<script> $(document).ready( function(){ $( \"#profileactiveNotice\" ).dialog('open'); });</script>";	
            $this->SetUpdateStatus('ready');
			return false;
		}
		return true;
	}
	
	# this returns an array of the ID's of the target pages
	function GetTargetIDs() {
		$target_ids = [];
		foreach ($this->targets as $thistarget) {
			if ($thistarget > "") {
				$tid = getID($thistarget, "urls", $this->tablename);
				if ($tid!==false) { $target_ids[] =  $tid; }
			}
		}
		return $target_ids;
	}
}
?>