Browse Source

dev 2020-11

Max F 5 years ago
parent
commit
4b49cfe302

+ 7 - 28
src/App/Middlewares/DebugBar.php

@@ -9,6 +9,7 @@ use \DebugBar\DataCollector\ConfigCollector;
 use \KarmaFW\App;
 use \KarmaFW\Http\Request;
 use \KarmaFW\Http\Response;
+use \KarmaFW\Http\UserAgent;
 use \KarmaFW\App\Middlewares\DebugBar\KarmaFwCollector;
 use \KarmaFW\App\Middlewares\DebugBar\SEOCollector;
 use \KarmaFW\App\Middlewares\DebugBar\SqlDbCollector;
@@ -52,13 +53,18 @@ class DebugBar
 			$constants = get_defined_constants(true);
 			$debugbar['config']->setData($constants['user']);
 
+
 			
 			// KarmaFW
 			if (isset($debugbar['KarmaFW'])) {
+				$ua_infos = UserAgent::analyseUserAgent( $request->getUserAgent() );
+
 				$data = [
 					'app' => App::getData('app'),
 					'request' => $request,
 					'response' => $response,
+					'user agent' => $ua_infos,
+					'client_ip' => $request->getClientIp(),
 				];
 				$debugbar['KarmaFW']->setData($data);
 			}
@@ -66,7 +72,7 @@ class DebugBar
 
 			// SEO
 			if (isset($debugbar['SEO'])) {
-				$seo_data = $this->seoParseContent($response);
+				$seo_data = $debugbar['SEO']->seoParseContent($request, $response);
 				$debugbar['SEO']->setData($seo_data);
 			}
 
@@ -89,31 +95,4 @@ class DebugBar
 	}
 
 
-	protected function seoParseContent(Response $response)
-	{
-		$content = $response->getBody();
-
-		preg_match('~<title(.*?)>(.*?)</title>~is', $content, $matches);
-		$title = empty($matches) ? '' : $matches[2];
-
-		preg_match('~<meta +name="description" +content="(.*?)" *>~is', $content, $matches);
-		$meta_desc = empty($matches) ? '' : $matches[1];
-
-		preg_match('~<h1(.*?)>(.*?)</h1>~is', $content, $matches);
-		$h1 = empty($matches) ? '' : $matches[2];
-
-		preg_match_all('/<a /is', $content, $matches);
-		$nb_links = empty($matches) ? 0 : count($matches[0]);
-
-		$data = [
-			'title' => $title,
-			'meta description' => $meta_desc,
-			'h1' => $h1,
-			'nb links' => $nb_links,
-			'content length' => formatSize(strlen($content)),
-		];
-
-		return $data;
-	}
-
 }

+ 49 - 0
src/App/Middlewares/DebugBar/SEOCollector.php

@@ -5,6 +5,8 @@ namespace KarmaFW\App\Middlewares\DebugBar;
 use \DebugBar\DataCollector\ConfigCollector;
 
 use \KarmaFW\App;
+use \KarmaFW\Http\Request;
+use \KarmaFW\Http\Response;
 
 
 class SEOCollector extends ConfigCollector
@@ -33,5 +35,52 @@ class SEOCollector extends ConfigCollector
         return parent::collect();
     }
 
+
+	public function seoParseContent(Request $request, Response $response)
+	{
+		$content = $response->getBody();
+
+		$url = $request->getFullUrl();
+
+		preg_match('~<title(.*?)>(.*?)</title>~is', $content, $matches);
+		$title = empty($matches) ? '' : $matches[2];
+
+		preg_match('~<meta +name="description" +content="(.*?)" *>~is', $content, $matches);
+		$meta_desc = empty($matches) ? '' : $matches[1];
+
+		preg_match('~<h1(.*?)>(.*?)</h1>~is', $content, $matches);
+		$h1 = empty($matches) ? '' : $matches[2];
+
+		preg_match_all('/<img /is', $content, $matches);
+		$nb_images = empty($matches) ? 0 : count($matches[0]);
+
+		preg_match_all('/<a /is', $content, $matches);
+		$nb_links = empty($matches) ? 0 : count($matches[0]);
+
+		preg_match_all('/<script ?/is', $content, $matches);
+		$nb_scripts = empty($matches) ? 0 : count($matches[0]);
+
+		preg_match_all('/<script (.*?)src="(.*?)>/is', $content, $matches);
+		$nb_scripts_external = empty($matches) ? 0 : count($matches[0]);
+
+		preg_match_all('/<link (.*?)rel="stylesheet"(.*?)>/is', $content, $matches);
+		$nb_stylesheets = empty($matches) ? 0 : count($matches[0]);
+
+		$data = [
+			'url' => $url,
+			'server ip' => $request->getServerIp(),
+			'title' => $title,
+			'meta description' => $meta_desc,
+			'h1' => $h1,
+			'nb images' => $nb_images,
+			'nb links' => $nb_links,
+			'nb stylesheets' => $nb_stylesheets,
+			'nb scripts' => $nb_scripts . " (" . ($nb_scripts-$nb_scripts_external) . " inline scripts + " . $nb_scripts_external . " external scripts)",
+			'content length' => formatSize(strlen($content)),
+		];
+
+		return $data;
+	}
+
 }
 

+ 100 - 0
src/App/Tools.php

@@ -50,4 +50,104 @@ class Tools
 
         return $context;
     }
+
+
+
+    public static function removeAccents()
+    {
+        $foreign_characters = array(
+            '/ä|æ|ǽ/' => 'ae',
+            '/ö|œ/' => 'oe',
+            '/ü/' => 'ue',
+            '/Ä/' => 'Ae',
+            '/Ü/' => 'Ue',
+            '/Ö/' => 'Oe',
+            '/À|Á|Â|Ã|Ä|Å|Ǻ|Ā|Ă|Ą|Ǎ|Α|Ά|Ả|Ạ|Ầ|Ẫ|Ẩ|Ậ|Ằ|Ắ|Ẵ|Ẳ|Ặ|А/' => 'A',
+            '/à|á|â|ã|å|ǻ|ā|ă|ą|ǎ|ª|α|ά|ả|ạ|ầ|ấ|ẫ|ẩ|ậ|ằ|ắ|ẵ|ẳ|ặ|а/' => 'a',
+            '/Б/' => 'B',
+            '/б/' => 'b',
+            '/Ç|Ć|Ĉ|Ċ|Č/' => 'C',
+            '/ç|ć|ĉ|ċ|č/' => 'c',
+            '/Д/' => 'D',
+            '/д/' => 'd',
+            '/Ð|Ď|Đ|Δ/' => 'Dj',
+            '/ð|ď|đ|δ/' => 'dj',
+            '/È|É|Ê|Ë|Ē|Ĕ|Ė|Ę|Ě|Ε|Έ|Ẽ|Ẻ|Ẹ|Ề|Ế|Ễ|Ể|Ệ|Е|Э/' => 'E',
+            '/è|é|ê|ë|ē|ĕ|ė|ę|ě|έ|ε|ẽ|ẻ|ẹ|ề|ế|ễ|ể|ệ|е|э/' => 'e',
+            '/Ф/' => 'F',
+            '/ф/' => 'f',
+            '/Ĝ|Ğ|Ġ|Ģ|Γ|Г|Ґ/' => 'G',
+            '/ĝ|ğ|ġ|ģ|γ|г|ґ/' => 'g',
+            '/Ĥ|Ħ/' => 'H',
+            '/ĥ|ħ/' => 'h',
+            '/Ì|Í|Î|Ï|Ĩ|Ī|Ĭ|Ǐ|Į|İ|Η|Ή|Ί|Ι|Ϊ|Ỉ|Ị|И|Ы/' => 'I',
+            '/ì|í|î|ï|ĩ|ī|ĭ|ǐ|į|ı|η|ή|ί|ι|ϊ|ỉ|ị|и|ы|ї/' => 'i',
+            '/Ĵ/' => 'J',
+            '/ĵ/' => 'j',
+            '/Ķ|Κ|К/' => 'K',
+            '/ķ|κ|к/' => 'k',
+            '/Ĺ|Ļ|Ľ|Ŀ|Ł|Λ|Л/' => 'L',
+            '/ĺ|ļ|ľ|ŀ|ł|λ|л/' => 'l',
+            '/М/' => 'M',
+            '/м/' => 'm',
+            '/Ñ|Ń|Ņ|Ň|Ν|Н/' => 'N',
+            '/ñ|ń|ņ|ň|ʼn|ν|н/' => 'n',
+            '/Ò|Ó|Ô|Õ|Ō|Ŏ|Ǒ|Ő|Ơ|Ø|Ǿ|Ο|Ό|Ω|Ώ|Ỏ|Ọ|Ồ|Ố|Ỗ|Ổ|Ộ|Ờ|Ớ|Ỡ|Ở|Ợ|О/' => 'O',
+            '/ò|ó|ô|õ|ō|ŏ|ǒ|ő|ơ|ø|ǿ|º|ο|ό|ω|ώ|ỏ|ọ|ồ|ố|ỗ|ổ|ộ|ờ|ớ|ỡ|ở|ợ|о/' => 'o',
+            '/П/' => 'P',
+            '/п/' => 'p',
+            '/Ŕ|Ŗ|Ř|Ρ|Р/' => 'R',
+            '/ŕ|ŗ|ř|ρ|р/' => 'r',
+            '/Ś|Ŝ|Ş|Ș|Š|Σ|С/' => 'S',
+            '/ś|ŝ|ş|ș|š|ſ|σ|ς|с/' => 's',
+            '/Ț|Ţ|Ť|Ŧ|τ|Т/' => 'T',
+            '/ț|ţ|ť|ŧ|т/' => 't',
+            '/Þ|þ/' => 'th',
+            '/Ù|Ú|Û|Ũ|Ū|Ŭ|Ů|Ű|Ų|Ư|Ǔ|Ǖ|Ǘ|Ǚ|Ǜ|Ũ|Ủ|Ụ|Ừ|Ứ|Ữ|Ử|Ự|У/' => 'U',
+            '/ù|ú|û|ũ|ū|ŭ|ů|ű|ų|ư|ǔ|ǖ|ǘ|ǚ|ǜ|υ|ύ|ϋ|ủ|ụ|ừ|ứ|ữ|ử|ự|у/' => 'u',
+            '/Ý|Ÿ|Ŷ|Υ|Ύ|Ϋ|Ỳ|Ỹ|Ỷ|Ỵ|Й/' => 'Y',
+            '/ý|ÿ|ŷ|ỳ|ỹ|ỷ|ỵ|й/' => 'y',
+            '/В/' => 'V',
+            '/в/' => 'v',
+            '/Ŵ/' => 'W',
+            '/ŵ/' => 'w',
+            '/Ź|Ż|Ž|Ζ|З/' => 'Z',
+            '/ź|ż|ž|ζ|з/' => 'z',
+            '/Æ|Ǽ/' => 'AE',
+            '/ß/' => 'ss',
+            '/IJ/' => 'IJ',
+            '/ij/' => 'ij',
+            '/Œ/' => 'OE',
+            '/ƒ/' => 'f',
+            '/ξ/' => 'ks',
+            '/π/' => 'p',
+            '/β/' => 'v',
+            '/μ/' => 'm',
+            '/ψ/' => 'ps',
+            '/Ё/' => 'Yo',
+            '/ё/' => 'yo',
+            '/Є/' => 'Ye',
+            '/є/' => 'ye',
+            '/Ї/' => 'Yi',
+            '/Ж/' => 'Zh',
+            '/ж/' => 'zh',
+            '/Х/' => 'Kh',
+            '/х/' => 'kh',
+            '/Ц/' => 'Ts',
+            '/ц/' => 'ts',
+            '/Ч/' => 'Ch',
+            '/ч/' => 'ch',
+            '/Ш/' => 'Sh',
+            '/ш/' => 'sh',
+            '/Щ/' => 'Shch',
+            '/щ/' => 'shch',
+            '/Ъ|ъ|Ь|ь/' => '',
+            '/Ю/' => 'Yu',
+            '/ю/' => 'yu',
+            '/Я/' => 'Ya',
+            '/я/' => 'ya'
+        );
+
+    }
+
 }

+ 8 - 1
src/Commands/ModelCommand.php

@@ -84,7 +84,14 @@ class ' . $class_name . ' extends SqlTableModel
 }
 ';
 
-		echo $tpl;		
+		echo $tpl;
+
+		if (false) {
+			$model_filepath = APP_DIR . "/src/Models/" . $class_name . ".php";
+			if (! is_file($model_filepath)) {
+				file_put_contents($model_filepath, $tpl);
+			}
+		}
 	}
 	
 }

+ 15 - 0
src/Http/Request.php

@@ -92,6 +92,10 @@ class Request
 			$request->SERVER['SERVER_NAME'] = $request->SERVER['HTTP_X_FORWARDED_HOST'];
 		}
 
+		if (empty($request->SERVER['SERVER_ADDR'])) {
+			$request->SERVER['SERVER_ADDR'] = '127.0.0.1';
+		}
+
 		// Set Client User-Agent
 		$user_agent = isset($request->SERVER['HTTP_USER_AGENT']) ? $request->SERVER['HTTP_USER_AGENT'] : null;
 		$request->setUserAgent($user_agent);
@@ -110,6 +114,12 @@ class Request
 	}
 
 
+	public function getFullUrl()
+	{
+		$scheme = $this->isSecure() ? 'https://' : 'http:';
+		return $scheme . $this->SERVER['SERVER_NAME'] . $this->url;
+	}
+
 	public function getUrl()
 	{
 		return $this->url;
@@ -130,6 +140,11 @@ class Request
 		return ($this->method == 'POST');
 	}
 
+	public function getServerIp()
+	{
+		return $this->SERVER['SERVER_ADDR'];
+	}
+
 	public function getClientIp()
 	{
 		return $this->client_ip;

+ 250 - 0
src/Http/UserAgent.php

@@ -6,6 +6,211 @@ namespace KarmaFW\Http;
 class UserAgent
 {
 
+	protected static $platforms = array(
+		'windows nt 10.0'	=> 'Windows 10',
+		'windows nt 6.3'	=> 'Windows 8.1',
+		'windows nt 6.2'	=> 'Windows 8',
+		'windows nt 6.1'	=> 'Windows 7',
+		'windows nt 6.0'	=> 'Windows Vista',
+		'windows nt 5.2'	=> 'Windows 2003',
+		'windows nt 5.1'	=> 'Windows XP',
+		'windows nt 5.0'	=> 'Windows 2000',
+		'windows nt 4.0'	=> 'Windows NT 4.0',
+		'winnt4.0'			=> 'Windows NT 4.0',
+		'winnt 4.0'			=> 'Windows NT',
+		'winnt'				=> 'Windows NT',
+		'windows 98'		=> 'Windows 98',
+		'win98'				=> 'Windows 98',
+		'windows 95'		=> 'Windows 95',
+		'win95'				=> 'Windows 95',
+		'windows phone'		=> 'Windows Phone',
+		'windows'			=> 'Unknown Windows OS',
+		'android'			=> 'Android',
+		'blackberry'		=> 'BlackBerry',
+		'iphone'			=> 'iOS',
+		'ipad'				=> 'iOS',
+		'ipod'				=> 'iOS',
+		'os x'				=> 'Mac OS X',
+		'ppc mac'			=> 'Power PC Mac',
+		'freebsd'			=> 'FreeBSD',
+		'ppc'				=> 'Macintosh',
+		'linux'				=> 'Linux',
+		'debian'			=> 'Debian',
+		'sunos'				=> 'Sun Solaris',
+		'beos'				=> 'BeOS',
+		'apachebench'		=> 'ApacheBench',
+		'aix'				=> 'AIX',
+		'irix'				=> 'Irix',
+		'osf'				=> 'DEC OSF',
+		'hp-ux'				=> 'HP-UX',
+		'netbsd'			=> 'NetBSD',
+		'bsdi'				=> 'BSDi',
+		'openbsd'			=> 'OpenBSD',
+		'gnu'				=> 'GNU/Linux',
+		'unix'				=> 'Unknown Unix OS',
+		'symbian' 			=> 'Symbian OS'
+	);
+
+
+	// The order of this array should NOT be changed. Many browsers return
+	// multiple browser types so we want to identify the sub-type first.
+	protected static $browsers = array(
+		'OPR'			=> 'Opera',
+		'Flock'			=> 'Flock',
+		'Edge'			=> 'Spartan',
+		'Chrome'		=> 'Chrome',
+		// Opera 10+ always reports Opera/9.80 and appends Version/<real version> to the user agent string
+		'Opera.*?Version'	=> 'Opera',
+		'Opera'			=> 'Opera',
+		'MSIE'			=> 'Internet Explorer',
+		'Internet Explorer'	=> 'Internet Explorer',
+		'Trident.* rv'	=> 'Internet Explorer',
+		'Shiira'		=> 'Shiira',
+		'Firefox'		=> 'Firefox',
+		'Chimera'		=> 'Chimera',
+		'Phoenix'		=> 'Phoenix',
+		'Firebird'		=> 'Firebird',
+		'Camino'		=> 'Camino',
+		'Netscape'		=> 'Netscape',
+		'OmniWeb'		=> 'OmniWeb',
+		'Safari'		=> 'Safari',
+		'Mozilla'		=> 'Mozilla',
+		'Konqueror'		=> 'Konqueror',
+		'icab'			=> 'iCab',
+		'Lynx'			=> 'Lynx',
+		'Links'			=> 'Links',
+		'hotjava'		=> 'HotJava',
+		'amaya'			=> 'Amaya',
+		'IBrowse'		=> 'IBrowse',
+		'Maxthon'		=> 'Maxthon',
+		'Ubuntu'		=> 'Ubuntu Web Browser'
+	);
+
+	protected static $mobiles = array(
+		// legacy array, old values commented out
+		'mobileexplorer'	=> 'Mobile Explorer',
+	//  'openwave'			=> 'Open Wave',
+	//	'opera mini'		=> 'Opera Mini',
+	//	'operamini'			=> 'Opera Mini',
+	//	'elaine'			=> 'Palm',
+		'palmsource'		=> 'Palm',
+	//	'digital paths'		=> 'Palm',
+	//	'avantgo'			=> 'Avantgo',
+	//	'xiino'				=> 'Xiino',
+		'palmscape'			=> 'Palmscape',
+	//	'nokia'				=> 'Nokia',
+	//	'ericsson'			=> 'Ericsson',
+	//	'blackberry'		=> 'BlackBerry',
+	//	'motorola'			=> 'Motorola'
+
+		// Phones and Manufacturers
+		'motorola'		=> 'Motorola',
+		'nokia'			=> 'Nokia',
+		'palm'			=> 'Palm',
+		'iphone'		=> 'Apple iPhone',
+		'ipad'			=> 'iPad',
+		'ipod'			=> 'Apple iPod Touch',
+		'sony'			=> 'Sony Ericsson',
+		'ericsson'		=> 'Sony Ericsson',
+		'blackberry'	=> 'BlackBerry',
+		'cocoon'		=> 'O2 Cocoon',
+		'blazer'		=> 'Treo',
+		'lg'			=> 'LG',
+		'amoi'			=> 'Amoi',
+		'xda'			=> 'XDA',
+		'mda'			=> 'MDA',
+		'vario'			=> 'Vario',
+		'htc'			=> 'HTC',
+		'samsung'		=> 'Samsung',
+		'sharp'			=> 'Sharp',
+		'sie-'			=> 'Siemens',
+		'alcatel'		=> 'Alcatel',
+		'benq'			=> 'BenQ',
+		'ipaq'			=> 'HP iPaq',
+		'mot-'			=> 'Motorola',
+		'playstation portable'	=> 'PlayStation Portable',
+		'playstation 3'		=> 'PlayStation 3',
+		'playstation vita'  	=> 'PlayStation Vita',
+		'hiptop'		=> 'Danger Hiptop',
+		'nec-'			=> 'NEC',
+		'panasonic'		=> 'Panasonic',
+		'philips'		=> 'Philips',
+		'sagem'			=> 'Sagem',
+		'sanyo'			=> 'Sanyo',
+		'spv'			=> 'SPV',
+		'zte'			=> 'ZTE',
+		'sendo'			=> 'Sendo',
+		'nintendo dsi'	=> 'Nintendo DSi',
+		'nintendo ds'	=> 'Nintendo DS',
+		'nintendo 3ds'	=> 'Nintendo 3DS',
+		'wii'			=> 'Nintendo Wii',
+		'open web'		=> 'Open Web',
+		'openweb'		=> 'OpenWeb',
+
+		// Operating Systems
+		'android'		=> 'Android',
+		'symbian'		=> 'Symbian',
+		'SymbianOS'		=> 'SymbianOS',
+		'elaine'		=> 'Palm',
+		'series60'		=> 'Symbian S60',
+		'windows ce'	=> 'Windows CE',
+
+		// Browsers
+		'obigo'			=> 'Obigo',
+		'netfront'		=> 'Netfront Browser',
+		'openwave'		=> 'Openwave Browser',
+		'mobilexplorer'	=> 'Mobile Explorer',
+		'operamini'		=> 'Opera Mini',
+		'opera mini'	=> 'Opera Mini',
+		'opera mobi'	=> 'Opera Mobile',
+		'fennec'		=> 'Firefox Mobile',
+
+		// Other
+		'digital paths'	=> 'Digital Paths',
+		'avantgo'		=> 'AvantGo',
+		'xiino'			=> 'Xiino',
+		'novarra'		=> 'Novarra Transcoder',
+		'vodafone'		=> 'Vodafone',
+		'docomo'		=> 'NTT DoCoMo',
+		'o2'			=> 'O2',
+
+		// Fallback
+		'mobile'		=> 'Generic Mobile',
+		'wireless'		=> 'Generic Mobile',
+		'j2me'			=> 'Generic Mobile',
+		'midp'			=> 'Generic Mobile',
+		'cldc'			=> 'Generic Mobile',
+		'up.link'		=> 'Generic Mobile',
+		'up.browser'	=> 'Generic Mobile',
+		'smartphone'	=> 'Generic Mobile',
+		'cellphone'		=> 'Generic Mobile'
+	);
+
+	// There are hundreds of bots but these are the most common.
+	protected static $robots = array(
+		'googlebot'		=> 'Googlebot',
+		'msnbot'		=> 'MSNBot',
+		'baiduspider'		=> 'Baiduspider',
+		'bingbot'		=> 'Bing',
+		'slurp'			=> 'Inktomi Slurp',
+		'yahoo'			=> 'Yahoo',
+		'ask jeeves'		=> 'Ask Jeeves',
+		'fastcrawler'		=> 'FastCrawler',
+		'infoseek'		=> 'InfoSeek Robot 1.0',
+		'lycos'			=> 'Lycos',
+		'yandex'		=> 'YandexBot',
+		'mediapartners-google'	=> 'MediaPartners Google',
+		'CRAZYWEBCRAWLER'	=> 'Crazy Webcrawler',
+		'adsbot-google'		=> 'AdsBot Google',
+		'feedfetcher-google'	=> 'Feedfetcher Google',
+		'curious george'	=> 'Curious George',
+		'ia_archiver'		=> 'Alexa Crawler',
+		'MJ12bot'		=> 'Majestic-12',
+		'Uptimebot'		=> 'Uptimebot'
+	);
+
+
+
 	protected static $bots_users_agents = [
 		"Googlebot/2.1 (+http://www.google.com/bot.html)",
 		"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
@@ -932,10 +1137,55 @@ class UserAgent
 		"Mozilla/5.0 (compatible; +http://tweetedtimes.com)",
 	];
 
+
 	public static function isBot($user_agent) 
 	{
 		return in_array($user_agent, self::$bots_users_agents);
 	}
 
 
+	public static function analyseUserAgent($user_agent) 
+	{
+		$ua_platform = null;
+		$ua_browser = null;
+		$ua_mobile = null;
+		$ua_robot = null;
+
+		foreach (self::$platforms as $k => $v) {
+			if (preg_match('/' . $k . '/i', $user_agent)) {
+				$ua_platform = $v;
+				break;
+			}
+		}
+
+		foreach (self::$browsers as $k => $v) {
+			if (preg_match('/' . $k . '/i', $user_agent)) {
+				$ua_browser = $v;
+				break;
+			}
+		}
+
+		foreach (self::$mobiles as $k => $v) {
+			if (preg_match('/' . $k . '/i', $user_agent)) {
+				$ua_mobile = $v;
+				break;
+			}
+		}
+
+		foreach (self::$robots as $k => $v) {
+			if (preg_match('/' . $k . '/i', $user_agent)) {
+				$ua_robot = $v;
+				break;
+			}
+		}
+
+		return [
+			'platform' => $ua_platform,
+			'browser' => $ua_browser,
+			'mobile' => $ua_mobile,
+			'robot' => $ua_robot,
+			'user_agent' => $user_agent,
+		];
+	}
+
 }