Location: PHPKode > scripts > Omsnplus > omsnplus/Omsnplus.php
<?php
/*################################################
 *	Omsnplus class 1.0 
 * Done by   : Saanina
* My Name : Abdulrahman Muhammad Alshawaiee 
* From  KSA
 * You can Find Me At :
 * 	- moffed.com
 *	- issc.ws
 * My email : hide@address.com
 *
 * Class Description: 
 *	emulator of Messenger Plus But for web pages :)
 *
*Class license :
* 	- GPL for Non-Commerical 
* 	- You can call me at my email if you want to use it in any thing commerical .. 
###############################################*/


class Omsnplus 
{
	
	//folder of msn smiles
	//Download all the emoticons (*.gif and don't rename) from http://messenger.msn.com/Resource/Emoticons.aspx
	var $smiles_folder =  'smiles/';
	
	//pre-definded colors 
	//source : http://www.emesene.org
	//emesene is a linux program for msn in python 
	var $dirty_colors = array(
					'ffffff','000000','00007F','009300','FF0000','7F0000','9C009C','FC7F00',
					'FFFF00','00FC00','009393','00FFFF','0000FC','FF00FF','7F7F7F','D2D2D2',
					'E7E6E4','CFCDD0','FFDEA4','FFAEB9','FFA8FF','B4B4FC','BAFBE5','C1FFA3',
					'FAFDA2','B6B4B7','A2A0A1','F9C152','FF6D66','FF62FF','6C6CFF','68FFC3',
					'8EFF67','F9FF57','858482','6E6D7B','FFA01E','F92611','FF20FF','202BFF',
					'1EFFA5','60F913','FFF813','5E6464','4B494C','D98812','EB0505','DE00DE',
					'0000D3','03CC88','59D80D','D4C804','333335','18171C','944E00','9B0008',
					'980299','01038C','01885F','389600','9A9E15','473400','4D0000','5F0162',
					'000047','06502F','1C5300','544D05'
					);
					
	//all copyrights of these smiles and thier shorts return to microzoft.
	//but with time those smiles were very popular, so we have some of the copyrights :)
	//if you hate microsoft remove this codes, if microzoft hate you, you can leave it.
	//Download all the emoticons (*.gif and don't rename) from http://messenger.msn.com/Resource/Emoticons.aspx
	var $msn_smiles = array(
							':-( :('	=> 'sad_smile.gif',
							':-) :)'	=> 'regular_smile.gif',
							':-O :o'	=> 'omg_smile.gif',
							':-D :d'	=> 'teeth_smile.gif',
							':-P :p'	=> 'tongue_smile.gif',
							';-) ;)'	=> 'wink_smile.gif',
							':-S :s'	=> 'confused_smile.gif',
							':\'('		=> 'cry_smile.gif',
							'(H) (h)'	=> 'shades_smile.gif',
							'(A) (a)'	=> 'angel_smile.gif',
							'(C) (c)'	=> 'coffee.gif',
							'(Y) (y)'	=> 'thumbs_up.gif',
							'(N) (n)'	=> 'thumbs_down.gif',
							'(L) (l)'	=> 'heart.gif',
							'(U) (u)'	=> 'broken_heart.gif',
							'(K) (k)'	=> 'kiss.gif',
							'(G) (g)'	=> 'present.gif',
							'(F) (f)'	=> 'rose.gif',
							'(W) (w)'	=> 'wilted_rose.gif',
							'(P) (p)'	=> 'camera.gif',
							'(T) (t)'	=> 'phone.gif',
							'(I) (i)'	=> 'lightbulb.gif',
							'(E) (e)'	=> 'envelope.gif',
							'(O) (o)'	=> 'clock.gif',
							'(M) (m)'	=> 'messenger.gif',
							'(~)'		=> 'film.gif',
							'(B) (b)'	=> 'beer_mug.gif',//bad smile
							'(D) (d)'	=> 'martini.gif',//bad smile
							'(X) (x)'	=> 'girl.gif',//I beileive that girls not like
							'(Z) (z)'	=> 'guy.gif',//Boys and Boys not like girls, X:horizotanl axis Y:vertiacl axis
							'({}'		=> 'guy_hug.gif',
							'())'		=> 'girl_hug.gif',
							':-#'		=> '47_47.gif', 
							':-| :|'	=> 'what_smile.gif',
							':-$ :$'	=> 'red_smile.gif',
							':-@ :@'	=> 'angry_smile.gif',
							'(6)'		=> 'devil_smile.gif',
							'8o|'		=> '48_48.gif',
							'8-|'		=> '49_49.gif',
							'^o)'		=> '50_50.gif',
							':-*'		=> '51_51.gif',
							'+o('		=> '52_52.gif',
							':^)'		=> '71_71.gif',
							'*-)'		=> '72_72.gif',
							'<:o)'		=> '74_74.gif',
							'8-)'		=> '75_75.gif',
							'|-)'		=> '77_77.gif',
							'|-)'		=> '77_77.gif',
							':-[ :['	=> 'bat.gif',
							'(^)'		=> 'cake.gif',
							'(@)'		=> 'cat.gif',
							'(&)'		=> 'dog.gif',
							'(8)'		=> 'note.gif',
							'(S)'		=> 'moon.gif',
							'(*)'		=> 'star.gif',
							'(sn)'		=> '53_53.gif',
							'(bah)'		=> '70_70.gif',
							'(pl)'		=> '55_55.gif',
							'(||)'		=> '56_56.gif',
							'(pi)'		=> '57_57.gif',
							'(so)'		=> '58_58.gif',
							'(au)'		=> '59_59.gif',
							'(ap)'		=> '60_60.gif',
							'(um)'		=> '61_61.gif',
							'(ip)'		=> '62_62.gif',
							'(co)'		=> '63_63.gif',
							'(mp)'		=> '64_64.gif',
							'(st)'		=> '66_66.gif',
							'(li)'		=> '73_73.gif',
							'(mo)'		=> '69_69.gif',
							//additional smiles , and you can add more  as item from the external variable :  $this->msn_smiles['short'] = 'img path';
							//bla bla bla
							);
							
	//the codes for msn. plus 
	var $codes = array(
						//solve some thing in begining
						
						//text decoration 
						'!\[(\/|)(b||u|s|i)\]!is'		=> '<$1$2>', 
						//'!\[\/(b||u|s|i)\]!is'		=> '</$1>', 
						'!\·\#(.*?)\·\#!s'			=> '<span style="font-weight:bold">$1</span>',
						'!\·\#!s'					=> '<span style="font-weight:bold">',
						'!\·\&(.*?)\·\&!s'			=> '<span style="font-style:italic">$1</span>',
						'!\·\&!s'					=> '<span style="font-style:italic">',
						'!\·\'(.*?)\·\'!s'			=> '<span style="text-decoration: line-through">$1</span>',
						'!\·\'!s'					=> '<span style="text-decoration: line-through">',
						'!\·\@(.*?)\·\@!s'			=> '<span style="text-decoration:underline">$1</span>',
						'!\·\@!s'					=> '<span style="text-decoration:underline">',
						'!\·0!s'					=> '</span>',//idont know what the porpuse of terminate till now , but i will try to know
						'!\[\/[a|c]\]!is'				=> '</span>',
						//colors for all methods 
							//predefined number
							//hex 
						'!\·\$(\#[0-9A-Fa-f]{2,6}|[a-z]+)(?: |)\,(?: |)(\#[0-9A-Fa-f]{2,6}|[a-z]+)!'	=> '<span style="color:$1;background-color:$2">',
						'!\·\$(?: |)\,(?: |)([0-9]{1,3})!e'				=> '"<span style=\"background-color:#" . $this->dirty_colors[$1] . "\">"',
						'!\·\$(?: |)\,(?: |)(\#[0-9A-Fa-f]{2,6}|[a-z]+)!'		=> '<span style="background-color:$1">',
						'!\·\$([0-9]{1,3})(?: |),(?: |)([0-9]{1,3})!e'	=> '"<span style=\"color:#" . $this->dirty_colors[$1] . ";background-color:#" . $this->dirty_colors[$2] . "\">"',
						'!\·\$([0-9]{1,3})!e'			=> '"<span style=\"color:" . $this->dirty_colors[$1] . "\">"',
						'!\·\$(\#[0-9A-Fa-f]{2,6}|[a-z]+)!'		=> '<span style="color:$1">',
							//rgb , not hex ·$(255,000,128)  alone ... 
						'!\·\$(?: |),(?: |)(\([0-9]{1,3}\,[0-9]{1,3}\,[0-9]{1,3}\))!'		=> '<span style="background-color:rgb$1">',	
						'!\·\$(\([0-9]{1,3}\,[0-9]{1,3}\,[0-9]{1,3}\))(?: |),(?: |)(\([0-9]{1,3}\,[0-9]{1,3}\,[0-9]{1,3}\))!'	=> '<span style="color:rgb$1;background-color:rgb$2">',
						'!\·\$(?: |)(\([0-9]{1,3}\,[0-9]{1,3}\,[0-9]{1,3}\))!'		=> '<span style="color:rgb$1">',	
						//at end , dirty solutions
						'!\<span(.*?)\>(\s+)\<!ie'	=> '$this->clean_spaces(\'$2\', "$1")',		
						'!\<span(.*?)\>\s(\w)!i'	=> '<span$1>&nbsp;$2',		
						'!(\w)\s\<\/span\>!i'	=> '$1&nbsp;</span>',	
						'!\·\$!'				=> '</span></span></span></span>', // ·$

					);
	
	/*
	 * clean_spaces
	 * for correct if nothing in span tag except spaces
	 * */
	function clean_spaces($text, $style)
	{
			return '<span'.$style.'>' . str_replace(' ', '&nbsp;', $text).'<';
	}
	
	/*This function will complie codes and output it
	 *as msn. plus format ..
	 * */
	function ps($text)
	{
		//nobody chalenge saanina !
		//convert some chars to html 
		$text =  str_replace('&amp;', '&', htmlspecialchars($text,ENT_QUOTES));
		//$text = str_replace(array('&middot;','&epsilon;','&sigma;','&amp;'), array('·','&#949;','&#963;','&'),htmlentities($text, ENT_NOQUOTES)); // support only latin letters  :( and with ( .., "UTF-8") also dosnt work
		
		//smiles
		$text = $this->replace_smiles($text);
		//plus codes
		$text = preg_replace('!\·\$([0-9]{1,3})(?: |)\,(?: |)\#!e', '"·$#" . $this->dirty_colors[$1] . ",#"', $text);//fixs
		$text = preg_replace('!\·\$(\#[0-9A-Fa-f]{2,6})\,(?: |)([0-9]{1,3})!e', '"·$$1,#" . $this->dirty_colors[$2] . ""', $text);//fixs
		$text = preg_replace_callback('!\[c\=(.*?)\](.*?)\[\/c\=(.*?)\]!is', array(&$this,"apply_color") , $text);
		$text = preg_replace_callback('!\[c\=(.*?)\]!is', array(&$this,"apply_color") , $text);
		$text = preg_replace_callback('!\[a\=(.*?)\](.*?)\[\/a\=(.*?)\]!is', array(&$this,"apply_background") , $text);
		$text = preg_replace_callback('!\[a\=(.*?)\]!is', array(&$this,"apply_background") , $text);
		$text = preg_replace(array_keys($this->codes), array_values($this->codes), $text);
				
		return $this->close_dangling_tags($text);
	}
	
	/*Replace short text of smiles by images  
	 *the default msn smiles
	 * */
	function replace_smiles($text)
	{
		//smiles at last .. i m using loop for my specail reasons !
		$smiles_match = $smiles_rep = array();
		foreach($this->msn_smiles as $txt=>$img)
		{
					//space ! there, ok, do u know 'strpos' better than 'explode' 
					if(strpos($txt, ' ') !== false)
					{
						$txts = explode(' ', $txt);
						foreach($txts as $t)
						{
							$smiles_match[] = "#" . preg_quote($t, '#') . "#m";	
							$smiles_rep[] =  '<img src="' . $this->smiles_folder . $img . '" alt="' . str_replace('.gif', '', $img) . '" />';
						}
					}
					else
					{
							$smiles_match[] = "#" . preg_quote($txt, '#') . "#m";	
							$smiles_rep[] =  '<img src="' . $this->smiles_folder  . $img . '" alt="' . str_replace('.gif', '', $img) . '" />';
					}
		}
		//preg_replace faster as they said than str_replace !
		return preg_replace($smiles_match, $smiles_rep, $text);	
	}
	
	/*clean color and return it as hex one
	 * this function its not that fully one ...
	 * */
	function return_good_color($color)
	{
		$color_is = '';
		if(is_numeric($color) && strlen($color) < 5)
			$color_is = '' . (!$this->dirty_colors[$color] ?  $color : $this->dirty_colors[$color]);
		else
			$color_is = htmlspecialchars(str_replace('#', '',$color));
			
		return $color_is;
	}
	
	/*The color of text in Plus done by many format ..  
	 * this fucntion will know what color will be 
	 * */
	function apply_color($match)
	{
		$color1 = $this->return_good_color($match[1]);
		$color2 = ($match[3]) ? $this->return_good_color($match[3]) : false;

		if($color2 == false)
			return '<span style="color:#' . $color1 .'">' . ($match[2] ?  $match[2] . '</span>' : '');
		else
			return  $this->grad($color1, $color2, $match[2]);
	}
	
	/*As color function but for backgrounds
	 * style css will change only !
	 * */
	function apply_background($match)
	{
		$color1 = $this->return_good_color($match[1]);
		$color2 = ($match[3]) ? $this->return_good_color($match[3]) : false;
			
		if($color2 == false)
			return '<span style="background-color:#' . $color1 .'">' . ($match[2] ?  $match[2] . '</span>' : '');
		else
			return  $this->grad($color1, $color2, $match[2], 'background-color');
	}
	
	/*Make grardient for text, i know its complicated feature but 
	 *this function is the simplest way to know why i hate PLUS 
	 * */
	function grad($first_color, $second_color, $text, $span_style='color')
	{
		
		$text = str_replace(array('&nbsp;'), array(' '), $text);//fix
		$texts = $this->str_split_php4_utf8($text);
		$text_length = sizeof($texts);
		$r1 = hexdec(substr($first_color, 0, 2));
		$g1 = hexdec(substr($first_color, 2, 2));
		$b1 = hexdec(substr($first_color, 4, 2));
		$res_r = ($r1 - hexdec(substr($second_color, 0, 2))) / ($text_length - 1);
		$res_g = ($g1 - hexdec(substr($second_color, 2, 2))) / ($text_length - 1);
		$res_b = ($b1 - hexdec(substr($second_color, 4, 2))) / ($text_length - 1);
		
		$colors = array();
		$return_text = '';
		$h = $w = false; 
		foreach(range(0, $text_length) as $i)
		{
			//open tags
			if(in_array($texts[$i], array('[','<')))
			{
				if($texts[$i] == '[')
				{
					$pos_h = strpos($text, ']');
					if($pos_h === false && $pos_h-$i > 10 && $pos_h-$i < 1)
						$h = false;
					else 
						$h = true;	
				}
				else
				{
					$pos_w = strpos($text, '>');
					if($pos_w === false && $pos_w-$i > 10 && $pos_w-$i < 1)
						$w = false;
					else 
						$w = true;	
				}
			}
			
			//close tags
			if($h == true && $texts[$i] != ']')
					$return_text .=  $texts[$i] == ' ' ? '&nbsp;' : $texts[$i];
			else if($w == true  && $texts[$i] != '>') 
				$return_text .= $texts[$i] == ' ' ? '&nbsp;' : $texts[$i];
			 else
			 {
			 	if(in_array($texts[$i],array(']','>')))
			 	{
			 		$return_text .= $texts[$i] == ' ' ? '&nbsp;' : $texts[$i];
			 		($texts[$i] == ']' ? $h = false : $w = false);
			 	}
			 	else
			 	{
					$colors['r'] = sprintf('%02x', floor($r1 - ($res_r*$i)));
					$colors['g'] = sprintf('%02x', floor($g1 - ($res_g*$i)));
					$colors['b'] = sprintf('%02x', floor($b1 - ($res_b*$i))); 
					$return_text .= $texts[$i] == ' ' ?  '&nbsp;' : '<span style="' . $span_style . ':#' . implode(null,$colors)  . '">' . $texts[$i] . '</span>';
				}
			}
		}
		return $return_text;
	}
	
	/*split text to letters in array !
	 * but in utf8 !
	 * code by :saeedco
	 * */
	function str_split_php4_utf8($str)
	{
		$split=1;
		$array = array();
		for ($i=0; $i < strlen($str); )
		{
			$value = ord($str[$i]);
			if($value > 127)
			{
				if($value >= 192 && $value <= 223)
					$split=2;
				elseif($value >= 224 && $value <= 239)
					$split=3;
				elseif($value >= 240 && $value <= 247)
					$split=4;
			}
			else
			{
				$split=1;
			}
				$key = NULL;
			for ($j = 0; $j < $split; $j++, $i++)
			{
				$key .= $str[$i];
			}
			array_push( $array, $key );
		}
		return $array;
	}  
	
	/*
	 * Colse opened html tags .. before output it
	 * @code by jamiew , link : http://codesnippets.joyent.com/posts/show/959
	 */
	function close_dangling_tags($html)
	{
		#put all opened tags into an array
		preg_match_all("#<([a-z]+)( .*)?(?!/)>#iU",$html,$result);
		$openedtags=$result[1];
		#put all closed tags into an array
		preg_match_all("#</([a-z]+)>#iU",$html,$result);
		$closedtags=$result[1];
		$len_opened = count($openedtags);
		# all tags are closed
		if(count($closedtags) == $len_opened)
			return $html;
		
		$openedtags = array_reverse($openedtags);
		# close tags
		for($i=0;$i < $len_opened;$i++) 
		{
			if (!in_array($openedtags[$i],$closedtags))
				$html .= '</' . $openedtags[$i] . '>';
			else 
				unset($closedtags[array_search($openedtags[$i], $closedtags)]);
		}
		
		return $html;
	}

}

?>
Return current item: Omsnplus