<?php

class Utils {

	/**
	 * Download and extract the maxmind geolite DBs
	 * @param $f3 \Base
	 * @param string $type
	 * @return bool
	 */
	public static function GetGeoIPDB($f3, $type='country', $overwrite=true){

		$url = '';
		$filename = '';
		if ($type=='city'){
			if ((!$overwrite) && (file_exists($f3->get('TEMP').'GeoLiteCity.dat'))) return true;
			$url = 'http://bit.ly/mmcitylite';
			$filename = 'GeoLiteCity.dat.gz';
		} else {
			if ((!$overwrite) && (file_exists($f3->get('TEMP').'GeoIP.dat'))) return true;
			$url = 'http://bit.ly/mmcountrylite';
			$filename = 'GeoIP.dat.gz';
		}

		try {
			Utils::DownloadFile($url, $f3->get('TEMP').$filename);
		} catch (Exception $e){
			return false;
		}

		try {
			$buffer_size = 8192; // read 8kb at a time
			$out_file_name = str_replace('.gz', '', $f3->get('TEMP').$filename);
			// Open our files (in binary mode)
			$file = gzopen($f3->get('TEMP').$filename, 'rb');
			$out_file = fopen($out_file_name, 'wb');
			// Keep repeating until the end of the input file
			while(!gzeof($file)) {
				// Read buffer-size bytes
				// Both fwrite and gzread and binary-safe
				fwrite($out_file, gzread($file, $buffer_size));
			}
			// Files are done, close files
			fclose($out_file);
			gzclose($file);
		} catch (Exception $e){
			Utils::Logger('GetGeoIPDB:Error downloading file - '.$filename.' - '.$e);
			return false;
		}

		try {
			unlink($f3->get('TEMP').$filename);
		} catch (Exception $e){
			Utils::Logger('GetGeoIPDB:Error deleting temp file - '.$filename.' - '.$e);
		}

		return true;
	}


	/** Check for filestamps on GeoIP Databases and update if need be
	 * @return string Returns translated result of update check
	 */
	public static function CheckGeoIPDBUpdate(){

		$ok = true;
		$updated = false;
		$f3 = Base::instance();

		if (!file_exists($f3->get('TEMP').'GeoLiteCity.dat')){
			Utils::GetGeoIPDB($f3, 'city') ? $ok = true : $ok = false;
			if (!$ok) return ($f3->get('lang_there_was_a_problem_with_updating_the_geoip_databases__please_try_later_or_contact_support'));
			$updated = true;
		}

		if (!file_exists($f3->get('TEMP').'GeoIP.dat')){
			Utils::GetGeoIPDB($f3, 'country') ? $ok = true : $ok = false;
			if (!$ok) return ($f3->get('lang_there_was_a_problem_with_updating_the_geoip_databases__please_try_later_or_contact_support'));
			$updated = true;
		}

		//City check
		$localCity = filemtime($f3->get('TEMP').'GeoLiteCity.dat');
		$remoteCity = Utils::_getRemoteLastModified('http://bit.ly/mmcitylite');
		if ((empty($remoteCity)) || ($remoteCity > $localCity)){
			Utils::GetGeoIPDB($f3, 'city', true) ? $ok = true : $ok = false;
			if (!$ok) return ($f3->get('lang_there_was_a_problem_with_updating_the_geoip_databases__please_try_later_or_contact_support'));
			$updated = true;
		}

		//Country check
		$localCountry = filemtime($f3->get('TEMP').'GeoIP.dat');
		$remoteCountry = Utils::_getRemoteLastModified('http://bit.ly/mmcountrylite');
		if ((empty($remoteCountry)) || ($remoteCountry > $localCountry)){
			Utils::GetGeoIPDB($f3, 'country', true) ? $ok = true : $ok = false;
			if (!$ok) return ($f3->get('lang_there_was_a_problem_with_updating_the_geoip_databases__please_try_later_or_contact_support'));
			$updated = true;
		}

		if ($updated){
			return ($f3->get('lang_updated_to_the_latest_version'));
		} else {
			return ($f3->get('lang_you_already_have_the_latest_version'));
		}

	}


	/**
	 * Send mail via php mail or smtp
	 * @param string $message
	 * @param $subject
	 * @param $to
	 * @return bool
	 */
	public static function SendMail($message='', $subject, $to, $bcc=''){
		$config = new \Models\Config();
		$c = $config->load();

		if ($c->mail_type == 1){
			try {
				$bccHeader = empty($bcc) ? '' : 'Bcc: '.$bcc."\r\n";
				$result = mail($to, $subject, $message, 'From: ' . $c->mail_from_email . "\r\n" .
						'MIME-Version: 1.0' . "\r\n" .
						'Content-type: text/html; charset="UTF-8"' . "\r\n" .
						'Reply-To: ' . $c->mail_from_email . "\r\n" .
						$bccHeader .
						'X-Mailer: mySimpleAds');
			} catch (Exception $e){
				Utils::Logger('SendMail:PHPMail Error - '.$e);
				return false;
			}
			return ($result);
		}
		if (($c->mail_smtp_host == '') || ($c->mail_from_email == '')) return false;
		require_once(dirname(__FILE__).DIRECTORY_SEPARATOR.'../mail/PHPMailerAutoload.php');
		try {
			$mail = new PHPMailer();
			$mail->isSMTP();
			$mail->Host = ($c->mail_smtp_secure=='SSL') ? 'ssl://'.$c->mail_smtp_host : $c->mail_smtp_host;
			$mail->Port = $c->mail_smtp_port;
			$mail->SMTPAuth  = $c->mail_smtp_auth == 1 ? true : false;
			$mail->Username = $c->mail_smtp_username;
			$mail->Password = $c->mail_smtp_password;
			$mail->SMTPSecure = $c->mail_smtp_secure;
			$mail->setFrom($c->mail_from_email, $c->mail_from_name);
			$mail->addAddress($to);
			if (!empty($bcc)) $mail->addBCC($bcc);
			$mail->isHTML(true);
			$mail->Subject = $subject;
			$mail->Body = $message;


			if(!$mail->send()) {
				Utils::Logger('SendMail:PHPMailer Problem - '.$mail->ErrorInfo);
				return false;
			}

		} catch (Exception $e){
			Utils::Logger('SendMail:PHPMailer Error - '.$e);
			return false;
		}

		return true;
	}


	/** Backups database to f3 temp dir
	 * @return string Translated result
	 */
	public static function BackupDB(){

		$f3 = Base::instance();

		$fileName = 'mysql-'.date('Y-m-d-H-i-s').'.sql';
		$url = $f3->get('SCHEME').'://'.$f3->get('HOST').$f3->get('BASE').'/'.$f3->get('TEMP').$fileName.'.gz';

		$dumpSettings = array(
				'compress' => 'GZIP',
				'no-data' => false,
				'add-drop-database' => false,
				'add-drop-table' => true,
				'single-transaction' => false,
				'lock-tables' => false,
				'add-locks' => false,
				'extended-insert' => true,
				'disable-foreign-keys-check' => false
		);

		try {
			$dbDump = new \Mysqldump($f3->get('db_name'), $f3->get('db_username'), $f3->get('db_password'), $f3->get('db_host'), 'mysql', $dumpSettings);
			$dbDump->start($f3->get('TEMP').$fileName);
		} catch (Exception $e){
			Utils::Logger('[BackupDB]Error dumping database - '.$e);
			return ($f3->get('lang_there_was_a_problem_backing_up_the_database__please_try_later_or_contact_support'));
		}

		if (file_exists($f3->get('TEMP').$fileName.'.gz')){
			$return = $f3->get('lang_your_database_is_backed_up_'). ' : '.$f3->get('TEMP').$fileName.'.gz. ';
			$return .= $f3->get('lang_you_may_want_to_delete_the_file_from_your_server_for_security_reasons_');
			return ($return);
		} else {
			return ($f3->get('lang_there_was_a_problem_backing_up_the_database__please_try_later_or_contact_support'));
		}

	}


	public static function getNotifications($lastTime, $account){
		$web = \Web::instance()->engine('stream');
		$web = \Web::instance()->request('https://www.clippersoft.net/dl/index.php?notifications&'.$lastTime.'&'.urlencode($account) );
		if ((empty($web)) || (empty($web['body']))) return null;

		$notifications = json_decode($web['body']);

		if (empty($notifications)) return null;
		if (count($notifications) <= 0 ) return null;

		$msg = \FlashMessage::instance();
		$lastNotificationTime = null;
		foreach($notifications as $notification){
			$msg->addMessage(date('Y-m-d',$notification->note_date).' : '.$notification->notification, 'info');
			$lastNotificationTime = $notification->note_date;
		}

		return $lastNotificationTime;
	}


	public static function getMysaUpdate(){
		$f3 = Base::instance();
		$config = new \Models\Config();
		$config->load(array('_id=?',1), null, 3600);
		$purchase_account = $config->purchase_account;
		if (empty($purchase_account)) return ($f3->get('lang_the_purchasing_account_code_not_be_verified_').' '.$f3->get('lang_please_contact_support_'));

		$zipFilepath= $f3->get('TEMP').md5($purchase_account).'.zip';
		if (file_exists($zipFilepath)) return ($f3->get('lang_it_looks_like_there_is_already_an_update_file_ready_to_be_run_').' <a href="index.php?install">'.$f3->get('lang_click_to_go_to_the_install_page').'</a>.');

		$curl_exist = function_exists('curl_version');
		if (empty($curl_exist)) return ($f3->get('lang_your_server_host_does_not_have_curl_installed__please_download_the_latest_update_from_clippersoft_net_'));

		set_time_limit(300); // 5 minutes
		$ch = curl_init();
		$source = 'https://www.clippersoft.net/dl/index.php?up&'.str_replace('_','',$f3->get('VERSION')).'&'.urlencode($purchase_account);

		curl_setopt($ch, CURLOPT_URL, $source);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_USERAGENT, empty($_SERVER['HTTP_USER_AGENT']) ? '' : $_SERVER['HTTP_USER_AGENT']);
		curl_setopt($ch, CURLOPT_REFERER, 'http' . (isset($_SERVER['HTTPS']) ? 's' : '') . '://' . "{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}");
		$data = curl_exec ($ch);
		$type = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
		curl_close ($ch);
		if (!empty($type)) $type = strtolower($type);

		if ($type == 'application/zip'){
			try {
			$destination = $zipFilepath;
			$file = fopen($destination, "w+");
			fputs($file, $data);
			fclose($file);
			} catch (Exception $e){
				Utils::Logger('[getMysaUpdate]Error saving update - '.$e);
				return ($f3->get('lang_there_was_a_problem_saving_the_update_').' '.$f3->get('lang_please_contact_support_'));
			}
		} elseif (stristr($type, 'text') !== false) {
			return ($data);
		} else {
			return ($f3->get('lang_there_was_a_problem_getting_the_update_').' '.$f3->get('lang_please_contact_support_'));
		}

		return ($f3->get('lang_the_latest_version_has_been_downloaded_and_is_ready_to_be_installed_').' <a href="index.php?install">'.$f3->get('lang_click_to_go_to_the_install_page').'</a>.');
	}


	public static function CleanCache(){
		$f3 = Base::instance();
		try {
			glob(dirname(__FILE__)."/../../../f3/cache/*.sql") ? array_map('unlink', glob(dirname(__FILE__)."/../../../f3/cache/*.sql")) : false;
			glob(dirname(__FILE__)."/../../../f3/cache/*.code") ? array_map('unlink', glob(dirname(__FILE__)."/../../../f3/cache/*.code")) : false;
			glob(dirname(__FILE__)."/../../../f3/cache/*.dash*") ? array_map('unlink', glob(dirname(__FILE__)."/../../../f3/cache/*.dash*")): false;
			glob(dirname(__FILE__)."/../../../f3/cache/*geo*") ? array_map('unlink', glob(dirname(__FILE__)."/../../../f3/cache/*geo*")) : false;
			glob(dirname(__FILE__)."/../../../f3/cache/*.s_processing") ? array_map('unlink', glob(dirname(__FILE__)."/../../../f3/cache/*s_processing")) : false;
		} catch (Exception $e){
			Utils::Logger('[CleanCache]Error cleaning cache - '.$e);
			return ($f3->get('lang_could_not_clear_the_cache_files'));
		}
		return ($f3->get('lang_cache_files_cleared'));
	}


	public static function Encrypt($string){
		$encoded = '';

		if (extension_loaded('mcrypt')){
			try {
				$encrypt = serialize($string);
				$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), MCRYPT_DEV_URANDOM);
				$key = pack('H*', '32BB57D556948CFD4E53F7DFA5263213296C6F4BBCB43C1B20800EBA9F3EB6B0');
				$mac = hash_hmac('sha256', $encrypt, substr(bin2hex($key), -32));
				$passcrypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $encrypt.$mac, MCRYPT_MODE_CBC, $iv);
				$encoded = base64_encode($passcrypt).'|'.base64_encode($iv);
				return ($encoded);
			} catch (Exception $e){
				Utils::Logger('Encrypt:Error encrypting - '.$e);
			}
		} else {
			return (base64_encode($string));
		}

		return ($encoded);
	}


	public static function Decrypt($string){
		$decrypted = '';

		if (extension_loaded('mcrypt')){
			try {
				$decrypt = explode('|', $string);
				if (count($decrypt) <= 1) return (base64_decode($string));
				$decoded = base64_decode($decrypt[0]);
				$iv = base64_decode($decrypt[1]);
				$key = pack('H*', '32BB57D556948CFD4E53F7DFA5263213296C6F4BBCB43C1B20800EBA9F3EB6B0');
				$decrypted = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $decoded, MCRYPT_MODE_CBC, $iv));
				$mac = substr($decrypted, -64);
				$decrypted = substr($decrypted, 0, -64);
				$calcmac = hash_hmac('sha256', $decrypted, substr(bin2hex($key), -32));
				if($calcmac!==$mac){ return false; }
				$decrypted = unserialize($decrypted);
				return ($decrypted);
			} catch (Exception $e){
				Utils::Logger('Decrypt:Error decrypting - '.$e);
			}
		} else {
			return (base64_decode($string));
		}

		return ($decrypted);
	}

		/**
	 * Generates a filename for uploads including timestamp
	 * @param string $filename
	 */

	public static function GenerateSlugFilename($filename){
		if (empty($filename)) return $filename;

		$fileInfo = pathinfo($filename);
		$extension = $fileInfo['extension'];
		$baseName = $fileInfo['basename'];

		$file = trim(strtolower(preg_replace('/([^\pL\pN])+/u','-',
			trim(strtr(str_replace('\'','',$baseName),
			array(
				'Ǎ'=>'A','А'=>'A','Ā'=>'A','Ă'=>'A','Ą'=>'A','Å'=>'A',
				'Ǻ'=>'A','Ä'=>'Ae','Á'=>'A','À'=>'A','Ã'=>'A','Â'=>'A',
				'Æ'=>'AE','Ǽ'=>'AE','Б'=>'B','Ç'=>'C','Ć'=>'C','Ĉ'=>'C',
				'Č'=>'C','Ċ'=>'C','Ц'=>'C','Ч'=>'Ch','Ð'=>'Dj','Đ'=>'Dj',
				'Ď'=>'Dj','Д'=>'Dj','É'=>'E','Ę'=>'E','Ё'=>'E','Ė'=>'E',
				'Ê'=>'E','Ě'=>'E','Ē'=>'E','È'=>'E','Е'=>'E','Э'=>'E',
				'Ë'=>'E','Ĕ'=>'E','Ф'=>'F','Г'=>'G','Ģ'=>'G','Ġ'=>'G',
				'Ĝ'=>'G','Ğ'=>'G','Х'=>'H','Ĥ'=>'H','Ħ'=>'H','Ï'=>'I',
				'Ĭ'=>'I','İ'=>'I','Į'=>'I','Ī'=>'I','Í'=>'I','Ì'=>'I',
				'И'=>'I','Ǐ'=>'I','Ĩ'=>'I','Î'=>'I','Ĳ'=>'IJ','Ĵ'=>'J',
				'Й'=>'J','Я'=>'Ja','Ю'=>'Ju','К'=>'K','Ķ'=>'K','Ĺ'=>'L',
				'Л'=>'L','Ł'=>'L','Ŀ'=>'L','Ļ'=>'L','Ľ'=>'L','М'=>'M',
				'Н'=>'N','Ń'=>'N','Ñ'=>'N','Ņ'=>'N','Ň'=>'N','Ō'=>'O',
				'О'=>'O','Ǿ'=>'O','Ǒ'=>'O','Ơ'=>'O','Ŏ'=>'O','Ő'=>'O',
				'Ø'=>'O','Ö'=>'Oe','Õ'=>'O','Ó'=>'O','Ò'=>'O','Ô'=>'O',
				'Œ'=>'OE','П'=>'P','Ŗ'=>'R','Р'=>'R','Ř'=>'R','Ŕ'=>'R',
				'Ŝ'=>'S','Ş'=>'S','Š'=>'S','Ș'=>'S','Ś'=>'S','С'=>'S',
				'Ш'=>'Sh','Щ'=>'Shch','Ť'=>'T','Ŧ'=>'T','Ţ'=>'T','Ț'=>'T',
				'Т'=>'T','Ů'=>'U','Ű'=>'U','Ŭ'=>'U','Ũ'=>'U','Ų'=>'U',
				'Ū'=>'U','Ǜ'=>'U','Ǚ'=>'U','Ù'=>'U','Ú'=>'U','Ü'=>'Ue',
				'Ǘ'=>'U','Ǖ'=>'U','У'=>'U','Ư'=>'U','Ǔ'=>'U','Û'=>'U',
				'В'=>'V','Ŵ'=>'W','Ы'=>'Y','Ŷ'=>'Y','Ý'=>'Y','Ÿ'=>'Y',
				'Ź'=>'Z','З'=>'Z','Ż'=>'Z','Ž'=>'Z','Ж'=>'Zh','á'=>'a',
				'ă'=>'a','â'=>'a','à'=>'a','ā'=>'a','ǻ'=>'a','å'=>'a',
				'ä'=>'ae','ą'=>'a','ǎ'=>'a','ã'=>'a','а'=>'a','ª'=>'a',
				'æ'=>'ae','ǽ'=>'ae','б'=>'b','č'=>'c','ç'=>'c','ц'=>'c',
				'ċ'=>'c','ĉ'=>'c','ć'=>'c','ч'=>'ch','ð'=>'dj','ď'=>'dj',
				'д'=>'dj','đ'=>'dj','э'=>'e','é'=>'e','ё'=>'e','ë'=>'e',
				'ê'=>'e','е'=>'e','ĕ'=>'e','è'=>'e','ę'=>'e','ě'=>'e',
				'ė'=>'e','ē'=>'e','ƒ'=>'f','ф'=>'f','ġ'=>'g','ĝ'=>'g',
				'ğ'=>'g','г'=>'g','ģ'=>'g','х'=>'h','ĥ'=>'h','ħ'=>'h',
				'ǐ'=>'i','ĭ'=>'i','и'=>'i','ī'=>'i','ĩ'=>'i','į'=>'i',
				'ı'=>'i','ì'=>'i','î'=>'i','í'=>'i','ï'=>'i','ĳ'=>'ij',
				'ĵ'=>'j','й'=>'j','я'=>'ja','ю'=>'ju','ķ'=>'k','к'=>'k',
				'ľ'=>'l','ł'=>'l','ŀ'=>'l','ĺ'=>'l','ļ'=>'l','л'=>'l',
				'м'=>'m','ņ'=>'n','ñ'=>'n','ń'=>'n','н'=>'n','ň'=>'n',
				'ŉ'=>'n','ó'=>'o','ò'=>'o','ǒ'=>'o','ő'=>'o','о'=>'o',
				'ō'=>'o','º'=>'o','ơ'=>'o','ŏ'=>'o','ô'=>'o','ö'=>'oe',
				'õ'=>'o','ø'=>'o','ǿ'=>'o','œ'=>'oe','п'=>'p','р'=>'r',
				'ř'=>'r','ŕ'=>'r','ŗ'=>'r','ſ'=>'s','ŝ'=>'s','ș'=>'s',
				'š'=>'s','ś'=>'s','с'=>'s','ş'=>'s','ш'=>'sh','щ'=>'shch',
				'ß'=>'ss','ţ'=>'t','т'=>'t','ŧ'=>'t','ť'=>'t','ț'=>'t',
				'у'=>'u','ǘ'=>'u','ŭ'=>'u','û'=>'u','ú'=>'u','ų'=>'u',
				'ù'=>'u','ű'=>'u','ů'=>'u','ư'=>'u','ū'=>'u','ǚ'=>'u',
				'ǜ'=>'u','ǔ'=>'u','ǖ'=>'u','ũ'=>'u','ü'=>'ue','в'=>'v',
				'ŵ'=>'w','ы'=>'y','ÿ'=>'y','ý'=>'y','ŷ'=>'y','ź'=>'z',
				'ž'=>'z','з'=>'z','ż'=>'z','ж'=>'zh'
			)+Base::instance()->get('DIACRITICS'))))),'-');

		$file .= date("-YmdHis").'.'.$extension;
		return ($file);
	}
	
	
	/**
	 * Logger - only if in debug mode
	 * @param $entry
	 * @param string $log
	 */
	public static function Logger($entry, $log='error'){
		/** @var $f3 \Base */
		$f3=Base::instance();
		if ($f3->get('DEBUG') > 0){
			$logger = new \Log($log .'.log');
			$logger->write($entry);
		}
	}



	/**
	 * Download a file from a url
	 * @param $url
	 * @param $savepath
	 */
	private static function DownloadFile($url, $savepath){
		$in=    fopen($url, "rb");
		$out=   fopen($savepath, "wb");
		while ($chunk = fread($in,8192))
		{
			fwrite($out, $chunk, 8192);
		}
		fclose($in);
		fclose($out);
	}


	/** get remote file last modification date (returns unix timestamp)
	 * @param $uri
	 * @return int|string
	 */
	private static function _getRemoteLastModified( $uri ){
		// default
		$unixtime = 0;

		$fp = fopen( $uri, "r" );
		if( !$fp ) {return '';}

		$MetaData = stream_get_meta_data( $fp );

		foreach( $MetaData['wrapper_data'] as $response )
		{
			// case: redirection
			if( substr( strtolower($response), 0, 10 ) == 'location: ' )
			{
				$newUri = substr( $response, 10 );
				fclose( $fp );
				return Utils::_getRemoteLastModified( $newUri );
			}
			// case: last-modified
			elseif( substr( strtolower($response), 0, 15 ) == 'last-modified: ' )
			{
				$unixtime = strtotime( substr($response, 15) );
				break;
			}
		}
		fclose( $fp );
		return $unixtime;
	}

}