Yeti iPhone Case

yeit-iphone-case

#bendgate

Posted in Uncategorized | Leave a comment

Jop Posting: Applications/SharePoint Software Developer – Hurlburt Field, FL, United States (Fort Walton Beach, Navarre, Destin, Niceville)

SUMMARY: Performs software design, development, integration, testing, and documentation. .

ESSENTIAL JOB FUNCTIONS: Provides software development support for the Air Force Special Operations Command (AFSOC) SharePoint portal farms utilizing Microsoft based technologies. Specifically:

Actively participate throughout the entire life cycle of developed products.
Interact with clients to collect requirements for needed capabilities.
Manage tasks in Team Foundation Server (TFS).
Develop SharePoint application pages and webparts to create a solution providing desired capability for clients.
Work with team members to research and integrate new capabilities to be used in solution development.
Review code and tests functionality of work accomplished by other team members.
Create supporting documentation for solutions to include installation instructions and user manuals.
Provide tier III support to users for created products.
Perform all phases of Software Development Life Cycle: requirements and specifications, design coding, testing and implementation.
Participate in the development/automating of the current SCRUM process to include Microsoft TFS, maintaining and testing new software product.
Other duties as assigned.

LOCATION: This full-time position is located at Hurlburt Field, FL with duty hours typically from 8:00 am to 5:00 pm, Monday through Friday.

QUALIFICATIONS: Four years experience in a relevant discipline or associated operational experience and two years directly applicable experience in development, operations, testing, integration, or fielding of systems are required. Also, required is a current SECRET clearance and eligible for higher level clearances as government requirements dictate. A Bachelor’s degree or equivalent experience and COMP TIA Security + is preferred. Desirable and current experience in C#.Net web and ASP.Net programming, developing with MS SQL Server 2008 or later, using Visual Studio 2010/1012, Team Foundation Server, working with the SCRUM Agile Methodology and Ajax, JQuery, JSON, JavaScript, LINQ, HTML, HTML5, CSS/CSS3, XSL, XML, UML, interacting with SharePoint lists and libraries through code, SharePoint Object Model development, using SharePoint Designer development, deploying, securing, and customizing SharePoint site collections, SharePoint Security Model, Events, Alerts, and Workflows, Microsoft Office Development, knowledge of the SharePoint APIs and libraries. Ability to identify technology gaps in current capabilities and processes. Detailed understanding of current and future technology trends. Must be able to work both independently and in a team environment. Effectively understand and communicate orally, in writing, and interpersonally with various customers. Convey technical information to non-technical individuals.

Please mention how you found this job when you apply or contact me directly.
bit.ly/1pWjbb9

Posted in Uncategorized | Leave a comment

WCF Notes

=======================================================
SOAP VS REST
=======================================================

http://restpatterns.org/

http://restpatterns.org/@api/deki/files/3/http-headers-status.jpg?origin=mt-web

http://msdn.microsoft.com/en-us/library/ff798366.aspx

Multiple factors need to be considered when choosing a particular type of Web service, that is between REST and SOAP. The table below breaks down the features of each Web service based on personal experience.

REST
•The RESTful Web services are completely stateless. This can be tested by restarting the server and checking if the interactions are able to survive.
•Restful services provide a good caching infrastructure over HTTP GET method (for most servers). This can improve the performance, if the data the Web service returns is not altered frequently and not dynamic in nature.
•The service producer and service consumer need to have a common understanding of the context as well as the content being passed along as there is no standard set of rules to describe the REST Web services interface.
•REST is particularly useful for restricted-profile devices such as mobile and PDAs for which the overhead of additional parameters like headers and other SOAP elements are less.
•REST services are easy to integrate with the existing websites and are exposed with XML so the HTML pages can consume the same with ease. There is hardly any need to refactor the existing website architecture. This makes developers more productive and comfortable as they will not have to rewrite everything from scratch and just need to add on the existing functionality.
•REST-based implementation is simple compared to SOAP.

SOAP
•The Web Services Description Language (WSDL) contains and describes the common set of rules to define the messages, bindings, operations and location of the Web service. WSDL is a sort of formal contract to define the interface that the Web service offers.
•SOAP requires less plumbing code than REST services design, (i.e., transactions, security, coordination, addressing, trust, etc.) Most real-world applications are not simple and support complex operations, which require conversational state and contextual information to be maintained. With the SOAP approach, developers need not worry about writing this plumbing code into the application layer themselves.
•SOAP Web services (such as JAX-WS) are useful in handling asynchronous processing and invocation.
•SOAP supports several protocols and technologies, including WSDL, XSDs, SOAP, WS-Addressing

So this means areas that REST works really well for are:
•Limited bandwidth and resources; remember the return structure is really in any format (developer defined). Plus, any browser can be used because the REST approach uses the standard GET, PUT, POST, and DELETE verbs. Again, remember that REST can also use the XMLHttpRequest object that most modern browsers support today, which adds an extra bonus of AJAX.
•Totally stateless operations; if an operation needs to be continued, then REST is not the best approach and SOAP may fit it better. However, if you need stateless CRUD (Create, Read, Update, and Delete) operations, then REST is it.
•Caching situations; if the information can be cached because of the totally stateless operation of the REST approach, this is perfect.

That covers a lot of solutions in the above three. So why would I even consider SOAP? Again, SOAP is fairly mature and well-defined and does come with a complete specification. The REST approach is just that, an approach and is wide open for development, so if you have the following then SOAP is a great solution:
•Asynchronous processing and invocation; if your application needs a guaranteed level of reliability and security then SOAP 1.2 offers additional standards to ensure this type of operation. Things like WSRM – WS-Reliable Messaging.
•Formal contracts; if both sides (provider and consumer) have to agree on the exchange format then SOAP 1.2 gives the rigid specifications for this type of interaction.
•Stateful operations; if the application needs contextual information and conversational state management then SOAP 1.2 has the additional specification in the WS* structure to support those things (Security, Transactions, Coordination, etc). Comparatively, the REST approach would make the developers build this custom plumbing.

http://msdn.microsoft.com/en-us/library/ee391967.aspx

——————————————————————————–
WCF BEST PRACTICES

http://wcfsecurity.codeplex.com/wikipage?title=Questions%20and%20Answers&referringTitle=Home

—————————-
Host WCF in WAS

http://msdn.microsoft.com/en-us/library/ms733109(v=vs.110).aspx

—————————-
Host WCF in Windows Services

http://msdn.microsoft.com/en-us/library/ms733069(v=vs.110).aspx

http://msdn.microsoft.com/en-us/library/ff649818.aspx

http://www.codeproject.com/Articles/653493/WCF-Hosting-with-Windows-Service

—————————-
Binary Encoding over HTTP
TCP is the fastest binding for two-way communications between servers. However, TCP bindings do not perform well in load-balanced environments.
If only WCF clients consume your services, it is possible to get the performance benefits of a TCP binding without incurring its drawbacks by
using a binary encoding over HTTP. WCF does not provide this binding, but you can create your own. The following XML code shows this custom binding.

http://msdn.microsoft.com/en-us/library/vstudio/hh323713(v=vs.100).aspx

http://msdn.microsoft.com/en-us/magazine/cc163394.aspx

Concerns:
NetTcBbinding requires a port to be availible through all firewalls/networks

=======================================================
REST PROXY FOR .NET CLIENT APPS
=======================================================

There’s no standard way of creating a proxy for a WCF REST service (there’s no WSDL for REST, one emerging standard, WADL, isn’t widely adopted, and WCF doesn’t support it).

USE SVCUTIL.EXE [URL TO .SVC] TO GENERATE DATA STRUCTURE CLASS FILES. THE WEB METHODS WILL BE CALLED USING standard .NET HttpWebRequest and StreamReader objects

svcutil.exe documentation:

http://msdn.microsoft.com/en-us/library/aa347733(v=vs.110).aspx

then cast into the classes generated by the svcutil.exe tool.

http://stackoverflow.com/questions/6625525/svcutil-doest-generate-config-file

http://blogs.msdn.com/b/carlosfigueira/archive/2012/03/26/mixing-add-service-reference-and-wcf-web-http-a-k-a-rest-endpoint-does-not-work.aspx

——————————————————-
PS: It MAY be possible in a Sharepoint web service: http://msdn.microsoft.com/en-us/library/ff798366.aspx but not in a regular WCF Web Service.

=======================================================
WCF Compression
=======================================================

http://www.codewrecks.com/blog/index.php/2012/09/11/wcf-over-https-compression-binary-binding-and-some-measurement/

http://www.hanselman.com/blog/EnablingDynamicCompressionGzipDeflateForWCFDataFeedsODataAndOtherCustomServicesInIIS7.aspx

http://architects.dzone.com/articles/wcf-over-https-compression-and

=======================================================
Max URL Length
=======================================================

http://stackoverflow.com/questions/15004232/wcf-get-url-length-limit-issue-bad-request-invalid-url

http://support.microsoft.com/kb/820129

=======================================================
SECURITY AUTHENTICATION AND AUTHORIZATION
=======================================================

http://www.codemag.com/article/0611051

http://msdn.microsoft.com/en-us/library/ff648863.aspx

HTTPWEBREQUEST ssl…

http://stackoverflow.com/questions/3562979/making-a-web-request-to-a-web-page-which-requires-windows-authentication

Troubleshooting the WCF WEB HTTP Programming Model
——————————————————-.
Because the WCF WEB HTTP programming model does not support the WS-* protocols, the only way to secure a WCF WEB HTTP service is to expose the service over HTTPS using SSL.

source: http://msdn.microsoft.com/en-us/library/bb412172(v=vs.110).aspx

————————-
•webHttpBinding is the REST-style binding, where you basically just hit a URL and get back a truckload of XML or JSON from the web service
•basicHttpBinding and wsHttpBinding are two SOAP-based bindings which is quite different from REST. SOAP has the advantage of having WSDL and XSD to describe the service,
its methods, and the data being passed around in great detail (REST doesn’t have anything like that – yet). On the other hand, you can’t just browse to a wsHttpBinding
endpoint with your browser and look at XML – you have to use a SOAP client, e.g. the WcfTestClient or your own app.

Source: http://stackoverflow.com/questions/2650785/basichttpbinding-vs-wshttpbinding-vs-webhttpbinding

=======================================================
VALIDATION (via DATAMEMEBER attributes)
=======================================================

http://kevincornwell.com/p/?url=http://www.technofattie.com/2011/10/05/recursive-validation-using-dataannotations.html

http://stackoverflow.com/questions/5368672/validator-tryvalidateobject-not-validating-rangeattribute/5368809#5368809

http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations(v=vs.100).aspx

http://kevincornwell.com/p/?url=http://www.neovolve.com/post/2008/04/07/implementing-ierrorhandler.aspx

=======================================================
EXCEPTIONS AND HANDLING
=======================================================

http://blogs.msdn.com/b/carlosfigueira/archive/2011/06/07/wcf-extensibility-ierrorhandler.aspx

http://stackoverflow.com/questions/3036692/ierrorhandler-doesnt-seem-to-be-handling-my-errors-in-wcf-any-ideas

http://stackoverflow.com/questions/1272877/returning-error-details-from-ajax-enabled-wcf-service

400 Bad request deserilization errors…

http://kevincornwell.com/p/?url=http://kenneththorman.blogspot.com/2011/02/wcf-rest-exception-handling_27.html

http://pieterderycke.wordpress.com/2011/04/30/wcf-rest-tip-2-webfaultexception/

http://stackoverflow.com/questions/417632/what-is-the-best-way-to-return-errors-from-a-wcf-service-in-a-restful-way

http://pieterderycke.wordpress.com/2011/04/30/wcf-rest-tip-2-webfaultexception/

http://msdn.microsoft.com/en-us/library/ee942778.aspx

http://blogs.msdn.com/b/endpoint/archive/2010/01/21/error-handling-in-wcf-webhttp-services-with-webfaultexception.aspx

OutgoingWebResponseContext response = WebOperationContext.Current.OutgoingResponse;
response.StatusCode = HttpStatusCode.Forbidden;
response.StatusDescription = “A Big fat error occurred”;
return null;

——————————————————
Handling invalid operations (bad uri’s) 404′s

http://stackoverflow.com/questions/6371856/handling-404-in-wcf-rest-service

=======================================================
DEFINING ATTRIBUTES ON METHODS (decorations etc) [DataContract]…..
=======================================================

http://msdn.microsoft.com/en-us/library/System.Runtime.Serialization(v=vs.110).aspx

=======================================================
Max values and Throttling in WCF
=======================================================

http://blogs.msdn.com/b/wenlong/archive/2009/07/26/wcf-4-higher-default-throttling-settings-for-wcf-services.aspx

=======================================================
USING PUT.. DETELTE, ETC in REST …
=======================================================

http://msdn.microsoft.com/en-us/library/dd203052.aspx

http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5

The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI. If a new resource is created, the origin server MUST inform the user agent via the 201 (Created) response. If an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate successful completion of the request. If the resource could not be created or modified with the Request-URI, an appropriate error response SHOULD be given that reflects the nature of the problem. The recipient of the entity MUST NOT ignore any Content-* (e.g. Content-Range) headers that it does not understand or implement and MUST return a 501 (Not Implemented) response in such cases.

If the request passes through a cache and the Request-URI identifies one or more currently cached entities, those entries SHOULD be treated as stale. Responses to this method are not cacheable.

The fundamental difference between the POST and PUT requests is reflected in the different meaning of the Request-URI. The URI in a POST request identifies the resource that will handle the enclosed entity. That resource might be a data-accepting process, a gateway to some other protocol, or a separate entity that accepts annotations. In contrast, the URI in a PUT request identifies the entity enclosed with the request — the user agent knows what URI is intended and the server MUST NOT attempt to apply the request to some other resource. If the server desires that the request be applied to a different URI,

it MUST send a 301 (Moved Permanently) response; the user agent MAY then make its own decision regarding whether or not to redirect the request.

Posted in REST, SOAP, WCF | Leave a comment

SCRUM

http://scrum.org/

http://channel9.msdn.com/events/TechEd/NorthAmerica/2012/DEV212

Posted in Uncategorized | Leave a comment

Visual Studio Bug (if followed by a try catch causes debugger stepping error)

http://whileicompile.wordpress.com/2010/07/02/visual-studio-bug-if-followed-by-a-try-catch-causes-debugger-stepping-error/

http://stackoverflow.com/questions/4368331/visual-studio-2010-debugger-steps-into-an-if-statement-despite-condition-fal

Posted in Uncategorized | Leave a comment

Basic HTML5 Page Layout Structure And Notes

The basic structure is…

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
Hello World
</body>
</html>

Notes:

HTML5 assumes all script types are “text/javaScript” and all stylesheet types are “text/css”.

So...
<script type="text/javascript" src="foo.js"></script>
<link rel="stylesheet" type="text/css" href="bar.css">
Is the same as...
<script src="foo.js"></script>
<link rel="stylesheet" href="bar.css">

Posted in HTML5, Uncategorized | Leave a comment

Freestyle Disk Frisbee: “Touch Free Hovering” Trick

Here is a trick I invented. As far as I know, I am the first and only person to do this…

Posted in Frisbee Disk | Leave a comment

Henderson State Park Time Lapse Videos (Destin FL)

Here are a few time lapse videos I made using my Droid Bionic phone.

Posted in Weather | Tagged | Leave a comment

Waterspout over Choctawhatchee Bay

Posted in Weather | Leave a comment

PHP POP3MAIL Email Telnet Class (without php_imap.dll)

I needed a POP3 client that would retrieve mail from POP3 server to a shared hosting account on Godaddy. As you may know, godaddy disables the php_imap.dll for php. This effectively makes the retrieval of email very difficult. Until now… :) I have mashed up some scripts from phpclasses.com and come up with a POP3MAIL class that retrieves emails and parses the email structure into a php object. The magic is done with Telnet commands sent over a fsockopen() connection. The code is not perfect but it serves the purpose I needed (to retrieve all images in emails). I have posted it here to help anyone who might need POP3 access from Goddady shared hosting. Please see the POP3MAIL.TEST.PHP file for a working example of the script.

POP3MAIL.TEST.PHP:

<?php
 
        //  EDIT THE FOLLOWING 4 VARS....
	$pop3ServerAddress = "";
	$pop3ServerPort = "";
	$pop3UserName = "";
	$pop3UserPass = "";
 
	error_reporting(E_ALL ^ E_DEPRECATED);
	$time_start = microtime(true);		
	include_once("POP3MAIL.CLASS.PHP");
	set_time_limit(120);
 
	$left = "";
	$right = "";
	$footer = "";	
	$footer .= "<br>Max Execution Time: " . ini_get('max_execution_time');
 
	$pop3 = new POP3MAIL();
 
	//////////////////////////////////////////////////////////////////////////
	// OPEN CONNECTION
	if($pop3->open($pop3ServerAddress, $pop3ServerPort))
	{
		$left .= "<br>Connection Opened";
	}
	else
	{
		$left .= "<br>Problem Opening Connection: " . $pop3->getError();
		exit;
	} 
 
	//////////////////////////////////////////////////////////////////////////
	// LOG IN
	if ($pop3->login($pop3UserName, $pop3UserPass))
	{
		$left .= "<br>Log In Successful";
	}
	else
	{
		$left .= "<br>Problem Logging In<br>" . $pop3->error;
		exit;
	}
 
	//////////////////////////////////////////////////////////////////////////
	// MESSAGE COUNT
	$msgCount=$pop3->getEmailCount();
	$left .= "<br>Message Count: " . $msgCount;
	$left .= $pop3->getError();	
 
	//////////////////////////////////////////////////////////////////////////
	// DELETE EMAIL
	if (isset($_GET["delete_msg"]))
	{
		$response = $pop3->deleteMessage($_GET["delete_msg"]);
 
		if ($response != false)
			$right .= "<script>alert('Message Deleted');</script>";
		else
			$right .= "<br>".$pop3->getError();
	}	
 
	//////////////////////////////////////////////////////////////////////////
	// NOOP
	//$response=$pop3->noop();
	//$right .= "<hr>NOOP: ".$response;
	//$right .= $pop3->getError();
 
	//////////////////////////////////////////////////////////////////////////
	// STATUS
	//$response=$pop3->getStatus();
	//$right .= "<hr>STAT: ".$response;
	//$right .= $pop3->getError();
 
	//////////////////////////////////////////////////////////////////////////
	// LIST
	//$response=$pop3->getList();
	//$right .= "<hr>LIST: ".$response;
	//$right .= $pop3->getError();
 
	//////////////////////////////////////////////////////////////////////////
	// MAKE EMAILS CLICKABLE
	$response=$pop3->getList();
	$res_arr = explode("\n", $response);
 
	for ($i = 1; $i < count($res_arr) - 2; $i++)
	{
		$bytes = explode(" " ,trim($res_arr[$i]));
		$left .= "<br><a href='?delete_msg=$i' onclick='return confirm(\"Delete Email #$i?\");'>Delete</a>";
		$left .= " <a href='?view_msg=$i'>View Email #$i (".formatBytes($bytes[1]).")</a> ";
	}
 
	//////////////////////////////////////////////////////////////////////////
	// GET EMAIL
	if (isset($_GET["view_msg"]))
	{
		if ($response = $pop3->getEmail($_GET["view_msg"]))
		{		
			$right .= "<hr><b>Email #: ".$_GET["view_msg"]."</b>";				
			//$right .= "<br><textarea cols=80 rows=10>$response</textarea><br>";
 
			$mimedecoder=new MIMEDECODE($response);								
			//$right .= "<br><textarea cols=80 rows=10>".print_r($mimedecoder, true)."</textarea><br>";
 
			$right .= "<br><b>To:</b> ".$mimedecoder->get_header("to");
			$right .= "<br><b>From:</b> ".$mimedecoder->get_header("from");
			$right .= "<br><b>From Email:</b> ".$mimedecoder->getFromEmail();
			$right .= "<br><b>Date:</b> ".$mimedecoder->get_header("date");
			$right .= "<br><b>Subject:</b> ".$mimedecoder->get_header("subject");
			$right .= "<br><b>Body:</b><br> ".$mimedecoder->getBody();
 
			$right .= "<br><b>Images:</b>";
 
			$image_arr = $mimedecoder->getImageObjects();			
 
			foreach($image_arr as $obj)
			{				
				$right .= "<br>".formatImageName($mimedecoder->getImageName($obj));
				$right .= "<br>".$mimedecoder->saveImageToDisk($obj, createRandomString(8) . "__" . formatImageName($mimedecoder->getImageName($obj)));
			}		
 
			//$right .= "<br><textarea cols='80' rows='10'>";
			//$right .= var_dump($image_arr);
			//$right .= "</textarea>";							
		}
		else
		{
			echo $pop3->getError();
			exit;
		}
	}
 
	if (!$pop3->close())
		$right .= "<hr>ERROR: Problem Closing Connection!!";
 
 
 
	////////////////////////////////////////////////////////////////////
	// FUNCTIONS
 
	function formatBytes($bytes, $precision = 2) { 
		$units = array('B', 'KB', 'MB', 'GB', 'TB'); 
 
		$bytes = max($bytes, 0); 
		$pow = floor(($bytes ? log($bytes) : 0) / log(1024)); 
		$pow = min($pow, count($units) - 1); 
 
		// Uncomment one of the following alternatives
		$bytes /= pow(1024, $pow);
		//$bytes /= (1 << (10 * $pow)); 
 
		return round($bytes, $precision) . ' ' . $units[$pow]; 
	} 
 
	function createRandomString($length) 
	{ 	
		$chars = "abcdefghijkmnopqrstuvwxyz023456789"; 
		srand((double)microtime()*1000000); 
		$i = 0; 
		$str = '' ; 
 
		while ($i < $length) 
		{ 
			$num = rand() % 33; 
			$tmp = substr($chars, $num, 1); 
			$str .= $tmp; 
			$i++; 
		} 
		return $str; 
	}	
 
	function formatImageName($name)
	{
		return preg_replace('@[^0-9a-z\.]+@i', '_', $name);
	}	
 
	$time_end = microtime(true);
	$time = $time_end - $time_start;
	$footer .= "<br>Execution Time: $time seconds\n";
?>
<html>
<head>
<title>POP3MAIL for PHP</title>
<style>
	body{margin:3px;padding:0px;}
	hr{margin:2px;padding:0px;border:0px;border-top:1px solid black;margin-left:0px;margin-right:0px;}
	div#wrap{width:1000px;border:2px solid black;position:relative;left:50%;margin-left:-504px;margin-top:5px;}
	div#header{width:100%;text-align:center;border:0px;border-bottom:1px solid black;}
	div#left{position:relative;float:left;width:200px;border:0px;padding:3px;}
	div#right{position:relative;float:right;width:787px;min-height:500px;padding:3px;border-left:1px solid black;}
	div#footer{clear:both;border:0px;border-top:1px solid black;text-align:center;}
</style>
</head>
<body style='font-size:12px;'>
<div id="wrap">
	<div id="header">
		<p>
			<h3 style='padding:4px;margin:0px;'>POP3MAIL for PHP</h3>
			(without php_imap.dll)
		</p>
	</div>
	<div id="left">
		<a href='?'>Home</a>
		<? echo $left; ?>
	</div>
	<div id="right">	
		<? echo $right; ?>
	</div>
	<div id="footer">
		<p>
			POP3MAIL by <a href='http://www.kevincornwell.com'>Kevin Cornwell</a>
			<? echo $footer; ?>
		</p>	
	</div>
</div>
TODO:
-body is returning the text twice
-handle pdf and other non image attachments
-render html emails as such	
</body>
</html>

POP3MAIL.CLASS.PHP

<?php
 
//  This class is based upon telnet protocols to pop3 server.
//  http://techhelp.santovec.us/pop3telnet.htm
 
	class POP3MAIL
	{
		var $host;  		// host like 127.0.0.1 or mail.yoursite.com
		var $port;  		// port default is 110 or 143
		var $user;  		// user for logon
		var $password;  	// user paswword
		var $state;   		// variable define diffrent state of connection
		var $connection; 	// handle to a open connection
		var $error;  		// error string
 
		############################################################################
		function POP3MAIL()
		{
			$this->host=NULL;
			$this->port=110;
			$this->user="";
			$this->password="";
			$this->state="DISCONNECTED";
			$this->connection=null;
			$this->error="";
		}
 
		############################################################################
		// Set host.  example: setHost("pop.yoursite.com") */	
		function setHost($host)
		{
			$this->host=$host;
		}
 
		############################################################################
		// This function set the portt example setPort(110)
		function setPort($port)
		{
			$this->port=$port;
		}
 
		############################################################################
		////This function is to retrieve the error of last operation 
		////example popmail::getError()
		function getError()
		{
			if($this->error)
				return $this->error;
		}
 
		############################################################################
		////This function is to retrieve the state of connection. 
		function getState()
		{
			return $this->state;
		}
 
		############################################################################
		///Function is used to open connection
		function open($host="",$port="")
		{
			if(!empty($host))
				$this->host=$host;
			if(!empty($port))
				$this->port=$port;
			return $this->openConnection();
		}
 
		############################################################################
		// Close the active connection
		function close()
		{
			$this->logout();
			@fclose($this->connection);
			$this->connection=null;
			$this->state="DISCONNECTED";
			return true;
		}
 
		############################################################################
		////This function is to open the connection to the server 
		function openConnection()
		{
			if($this->state!="DISCONNECTED")
			{
				$this->error = "Error: Already Connected.";
				return false;
			}
			if(empty($this->host) || empty($this->port))			
			{
				$this->error = "Error: Either HOST or PORT is undifined.";
				return false;
			}
			$this->connection = fsockopen($this->host,$this->port,$errno,$errstr);
			if(!$this->connection)
			{
				$this->error= "Could not make a connection to server , Error : $errstr ($errno)";
				return false;
			}
			$respone=$this->getLine();	
			$this->state = "AUTHORIZATION";
			return true;
		}			
 
		############################################################################
		// Send telnet command and return response string 
		// else on -ERR from server, set error message 
		// and return false.
		function SendCommand($cmd, $delimiter="\r\n")
		{	
			if($this->state=="DISCONNECTED")
			{
				$this->error= "Error(0): No Connection Found.";
				return false;
			}		
			if($this->state=="AUTHORIZATION")
			{
				$this->error = "SendCommand Error(1): User is not authorised or logged in.";
				return false;
			}
			if($this->putLine($cmd))
			{
				$response=$this->getServerResponse($delimiter);
 
				if(!$this->isOK($response))
				{
					$this->error= "SendCommand Error(2) with '$cmd': $response";
					return false;
				}
			}
			else
			{
				$this->error= "SendCommand Error(3) with '$cmd': Could not send request.";
				return false;
			}
			return $response;			
		}
 
		############################################################################
		////This function is to send the command to server
		function putLine($msg)
		{
			return @fputs($this->connection,"$msg\r\n");
		}
 
		############################################################################
		////This function is to retrieve the full response message from server
		function getServerResponse($delimeter="\r\n")
		{
			$response = "";			
			$i = 0;
 
			while($i++ < 10000000) // limit to prevent infinite loop (could be a problem for insainly large emails.
			{
				$response.=$this->getLine();
				if (strpos($response, $delimeter)>0)  //if(substr($response,strpos($response,$this->tag),strlen($this->tag))==$this->tag)
					break;
			}
			return $response;
		}
 
		############################################################################
		// This function is used to get response line from server
		function getLine()
		{
			$line = "";
 
			while(!feof($this->connection))
			{
				$line.=fgets($this->connection);
				if(strlen($line)>=2 && substr($line,-2)=="\r\n")
					return $line; //return(substr($line,0,-2));
			}
		}
 
		############################################################################
		// Function to check for "+OK" response code.	
		function isOK($rsp)
		{
			//note that we are checking against OK and not +OK
			$pos = strpos($rsp, "OK");			
 
			if ($pos === 1)  // OK must be at index position 1.
				return true;
			else
				return false;
		}
 
		############################################################################
		// Login into server
		function login($user,$pwd)
		{
			if($this->state=="DISCONNECTED")
			{
				$this->error= "Error Login(1): No Connection Found.";
				return false;
			}
 
			if($this->state=="AUTHENTICATED")
			{
				$this->error= "Error Login(2): Already Authenticated.";
				return false;
			}
			// Send USER
			if($this->putLine("USER $user"))
			{
				$response=$this->getServerResponse();
 
				if(!$this->isOK($response))
				{
					$this->error = "Error Login(3): in USER command: $response";
					return false;
				}
			}
			else
			{
				$this->error= "Error Login(4): Could not send User request.";
				return false;
			}			
			// Send PASS
			if($this->putLine("PASS $pwd"))
			{
				$response=$this->getServerResponse();
 
				if(!$this->isOK($response))
				{
					$this->error= "Error Login(5):in PASS command: $response";
					return false;
				}
			}
			else
			{
				$this->error= "Error Login(6): Could not send User request.";
				return false;
			}			
			$this->state="AUTHENTICATED";
			return true;
		}
 
		############################################################################
		/* The logout function informs the server that the client is done with the connection. */
		function logout()
		{
			return $this->SendCommand("QUIT", "\r\n");
		}
 
		############################################################################
		// Gets total number of messages on pop3 server and bytes.
		function getStatus()
		{
			return $this->SendCommand("STAT", "\r\n");
		}	
 
		############################################################################
		// Returns the list of emails and size.
		function getList()
		{
			return $this->SendCommand("LIST", "\r\n.\r\n");
		}
 
		############################################################################
		// Periodic poll.  Only return +OK if connection is still valid.
		function getEmailCount()
		{
			$rsp = $this->SendCommand("STAT", "\r\n");
			$arr = explode(" ", $rsp);
			return trim($arr[1]);
		}		
 
		############################################################################
		// Periodic poll command.  Returns "+OK" if connection is still valid.
		function noop()
		{
			return $this->SendCommand("NOOP", "\r\n");
		}		
 
		############################################################################
		//	Returns a raw email by number.
		function getEmail($msgno)
		{
			return $this->SendCommand("RETR $msgno", "\r\n.\r\n");
		}
 
		############################################################################
		// Delete message.
		function deleteMessage($msgno)
		{
			return $this->SendCommand("DELE $msgno", "\r\n");
		}	
	}
?>
 
<?php
 
	class MIMEDECODE 
	{
		//kevin
		var $_mailObjectDecoded;
	    /**
	     * The raw email to decode
	     * @var    string
	     */
	    var $_input;
 
	    /**
	     * The header part of the input
	     * @var    string
	     */
	    var $_header;
 
	    /**
	     * The body part of the input
	     * @var    string
	     */
	    var $_body;
 
	    /**
	     * If an error occurs, this is used to store the message
	     * @var    string
	     */
	    var $_error;
 
	    /**
	     * Flag to determine whether to include bodies in the
	     * returned object.
	     * @var    boolean
	     */
	    var $_include_bodies;
 
	    /**
	     * Flag to determine whether to decode bodies
	     * @var    boolean
	     */
	    var $_decode_bodies;
 
	    /**
	     * Flag to determine whether to decode headers
	     * @var    boolean
	     */
	    var $_decode_headers;
 
	    /**
	    * If invoked from a class, $this will be set. This has problematic
	    * connotations for calling decode() statically. Hence this variable
	    * is used to determine if we are indeed being called statically or
	    * via an object.
	    */
	    var $mailMimeDecode;
 
	    /**
	     * Constructor.
	     *
	     * Sets up the object, initialise the variables, and splits and
	     * stores the header and body of the input.
	     *
	     * @param string The input to decode
	     * @access public
	     */
	    function MIMEDECODE($input)
	    {
	        list($header, $body)   = $this->_split_body_header($input);
 
	        $this->_input          = $input;
	        $this->_header         = $header;
	        $this->_body           = $body;
	        $this->_decode_bodies  = true;
	        $this->_include_bodies = true;
 
	        $this->mailMimeDecode  = true;
			//kevin edit
			$this->_mailObjectDecoded = $this->decode();
	    }
 
	    /**
	     * Begins the decoding process. If called statically
	     * it will create an object and call the decode() method
	     * of it.
	     *
	     * @param array An array of various parameters that determine
	     *              various things:
	     *              include_bodies - Whether to include the body in the returned
	     *                               object.
	     *              decode_bodies  - Whether to decode the bodies
	     *                               of the parts. (Transfer encoding)
	     *              decode_headers - Whether to decode headers
	     *              input          - If called statically, this will be treated
	     *                               as the input
	     * @return object Decoded results
	     * @access public
	     */
	    function decode($params = null)
	    {
 
	        // Have we been called statically? If so, create an object and pass details to that.
	        if (!isset($this->mailMimeDecode) AND isset($params['input'])) {
 
	            $obj = new MIMEDECODE($params['input']);
	            $structure = $obj->decode($params);
 
	        // Called statically but no input
	        } elseif (!isset($this->mailMimeDecode)) {
	            return $this->_error='Called statically and no input given';
 
	        // Called via an object
	        } else {
 
	            //$this->_include_bodies = isset($params['include_bodies'])  ? $params['include_bodies']  : false;
	            //$this->_decode_bodies  = isset($params['decode_bodies'])   ? $params['decode_bodies']   : false;
	            //$this->_decode_headers = isset($params['decode_headers'])  ? $params['decode_headers']  : false;
 
	            $structure = $this->_decode($this->_header, $this->_body);
	            if ($structure === false) {
	                $structure = $this->_error;
	            }
	        }
	        return $structure;
	    }
 
	    /**
	     * Performs the decoding. Decodes the body string passed to it
	     * If it finds certain content-types it will call itself in a
	     * recursive fashion
	     *
	     * @param string Header section
	     * @param string Body section
	     * @return object Results of decoding process
	     * @access private
	     */
	    function _decode($headers, $body, $default_ctype = 'text/plain')
	    {
	        $return = new stdClass;
	        $headers = $this->_parseHeaders($headers);
 
	        foreach ($headers as $value) {
	            if (isset($return->headers[strtolower($value['name'])]) AND !is_array($return->headers[strtolower($value['name'])])) {
	                $return->headers[strtolower($value['name'])]   = array($return->headers[strtolower($value['name'])]);
	                $return->headers[strtolower($value['name'])][] = $value['value'];
 
	            } elseif (isset($return->headers[strtolower($value['name'])])) {
	                $return->headers[strtolower($value['name'])][] = $value['value'];
 
	            } else {
	                $return->headers[strtolower($value['name'])] = $value['value'];
	            }
	        }
 
	        reset($headers);
	        while (list($key, $value) = each($headers)) {
	            $headers[$key]['name'] = strtolower($headers[$key]['name']);
	            switch ($headers[$key]['name']) {
 
	                case 'content-type':
	                    $content_type = $this->_parseHeaderValue($headers[$key]['value']);
 
	                    if (preg_match('/([0-9a-z+.-]+)\/([0-9a-z+.-]+)/i', $content_type['value'], $regs)) {
	                        $return->ctype_primary   = $regs[1];
	                        $return->ctype_secondary = $regs[2];
	                    }
 
	                    if (isset($content_type['other'])) {
	                        while (list($p_name, $p_value) = each($content_type['other'])) {
	                            $return->ctype_parameters[$p_name] = $p_value;
	                        }
	                    }
	                    break;
 
	                case 'content-disposition';
	                    $content_disposition = $this->_parseHeaderValue($headers[$key]['value']);
	                    $return->disposition   = $content_disposition['value'];
	                    if (isset($content_disposition['other'])) {
	                        while (list($p_name, $p_value) = each($content_disposition['other'])) {
	                            $return->d_parameters[$p_name] = $p_value;
	                        }
	                    }
	                    break;
 
	                case 'content-transfer-encoding':
	                    $content_transfer_encoding = $this->_parseHeaderValue($headers[$key]['value']);
	                    break;
	            }
	        }
 
	        if (isset($content_type)) {
	            switch (trim(strtolower($content_type['value']))) {
	                case 'text/plain':
	                    $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit';
	                    $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $encoding) : $body) : null;
	                    break;
	                case 'text/html':
	                    $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit';
	                    $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $encoding) : $body) : null;
					    break;
 
	                case 'multipart/parallel':
	                case 'multipart/report': // RFC1892
	                case 'multipart/signed': // PGP
	                case 'multipart/digest':
	                case 'multipart/alternative':
	                case 'multipart/related':
	                case 'multipart/mixed':
	                    if(!isset($content_type['other']['boundary'])){
	                        $this->_error = 'No boundary found for ' . $content_type['value'] . ' part';
	                        return false;
	                    }
 
	                    $default_ctype = (strtolower($content_type['value']) === 'multipart/digest') ? 'message/rfc822' : 'text/plain';
 
	                    $parts = $this->_boundarySplit($body, $content_type['other']['boundary']);
	                    for ($i = 0; $i < count($parts); $i++) {
	                        list($part_header, $part_body) = $this->_split_body_header($parts[$i]);
	                        $part = $this->_decode($part_header, $part_body, $default_ctype);
	                        if($part === false)
	                            $part = $this->raiseError($this->_error);
	                        $return->parts[] = $part;
	                    }
	                    break;
 
	                case 'message/rfc822':
	                    $obj = &new MIMEDECODE($body);
	                    $return->parts[] = $obj->decode(array('include_bodies' => $this->_include_bodies));
	                    unset($obj);
	                    break;
 
	                default:
	                    if(!isset($content_transfer_encoding['value']))
	                        $content_transfer_encoding['value'] = '7bit';
	                    $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $content_transfer_encoding['value']) : $body) : null;
	                    break;
	            }
 
	        } else {
	            $ctype = explode('/', $default_ctype);
	            $return->ctype_primary   = $ctype[0];
	            $return->ctype_secondary = $ctype[1];
	            $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body) : $body) : null;
	        }
 
	        return $return;
	    }
 
	    /**
	     * Given the output of the above function, this will return an
	     * array of references to the parts, indexed by mime number.
	     *
	     * @param  object $structure   The structure to go through
	     * @param  string $mime_number Internal use only.
	     * @return array               Mime numbers
	     */
	    function &getMimeNumbers(&$structure, $no_refs = false, $mime_number = '', $prepend = '')
	    {
	        $return = array();
	        if (!empty($structure->parts)) {
	            if ($mime_number != '') {
	                $structure->mime_id = $prepend . $mime_number;
	                $return[$prepend . $mime_number] = &$structure;
	            }
	            for ($i = 0; $i < count($structure->parts); $i++) {
 
 
	                if (!empty($structure->headers['content-type']) AND substr(strtolower($structure->headers['content-type']), 0, 8) == 'message/') {
	                    $prepend      = $prepend . $mime_number . '.';
	                    $_mime_number = '';
	                } else {
	                    $_mime_number = ($mime_number == '' ? $i + 1 : sprintf('%s.%s', $mime_number, $i + 1));
	                }
 
	                $arr = &MIMEDECODE::getMimeNumbers($structure->parts[$i], $no_refs, $_mime_number, $prepend);
	                foreach ($arr as $key => $val) {
	                    $no_refs ? $return[$key] = '' : $return[$key] = &$arr[$key];
	                }
	            }
	        } else {
	            if ($mime_number == '') {
	                $mime_number = '1';
	            }
	            $structure->mime_id = $prepend . $mime_number;
	            $no_refs ? $return[$prepend . $mime_number] = '' : $return[$prepend . $mime_number] = &$structure;
	        }
 
	        return $return;
	    }
 
	    /**
	     * Given a string containing a header and body
	     * section, this function will split them (at the first
	     * blank line) and return them.
	     *
	     * @param string Input to split apart
	     * @return array Contains header and body section
	     * @access private
	     */
	    function _split_body_header($input)
	    {
	        if (preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $input, $match)) {
	            return array($match[1], $match[2]);
	        }
	        $this->_error = 'Could not split header and body';
	        return false;
	    }
 
	    /**
	     * Parse headers given in $input and return
	     * as assoc array.
	     *
	     * @param string Headers to parse
	     * @return array Contains parsed headers
	     * @access private
	     */
	    function _parseHeaders($input)
	    {
 
	        if ($input !== '') {
	            // Unfold the input
	            $input   = preg_replace("/\r?\n/", "\r\n", $input);
	            $input   = preg_replace("/\r\n(\t| )+/", ' ', $input);
	            $headers = explode("\r\n", trim($input));
 
	            foreach ($headers as $value) {
	                $hdr_name = substr($value, 0, $pos = strpos($value, ':'));
	                $hdr_value = substr($value, $pos+1);
	                if($hdr_value[0] == ' ')
	                    $hdr_value = substr($hdr_value, 1);
 
	                $return[] = array(
	                                  'name'  => $hdr_name,
	                                  'value' => $this->_decode_headers ? $this->_decodeHeader($hdr_value) : $hdr_value
	                                 );
	            }
	        } else {
	            $return = array();
	        }
 
	        return $return;
	    }
 
	    /**
	     * Function to parse a header value,
	     * extract first part, and any secondary
	     * parts (after ;) This function is not as
	     * robust as it could be. Eg. header comments
	     * in the wrong place will probably break it.
	     *
	     * @param string Header value to parse
	     * @return array Contains parsed result
	     * @access private
	     */
	    function _parseHeaderValue($input)
	    {
 
	        if (($pos = strpos($input, ';')) !== false) {
 
	            $return['value'] = trim(substr($input, 0, $pos));
	            $input = trim(substr($input, $pos+1));
 
	            if (strlen($input) > 0) {
 
	                // This splits on a semi-colon, if there's no preceeding backslash
	                // Can't handle if it's in double quotes however. (Of course anyone
	                // sending that needs a good slap).
	                $parameters = preg_split('/\s*(?<!\\\\);\s*/i', $input);
 
	                for ($i = 0; $i < count($parameters); $i++) {
	                    $param_name  = substr($parameters[$i], 0, $pos = strpos($parameters[$i], '='));
	                    $param_value = substr($parameters[$i], $pos + 1);
	                    if ($param_value[0] == '"') {
	                        $param_value = substr($param_value, 1, -1);
	                    }
	                    $return['other'][$param_name] = $param_value;
	                    $return['other'][strtolower($param_name)] = $param_value;
	                }
	            }
	        } else {
	            $return['value'] = trim($input);
	        }
 
	        return $return;
	    }
 
	    /**
	     * This function splits the input based
	     * on the given boundary
	     *
	     * @param string Input to parse
	     * @return array Contains array of resulting mime parts
	     * @access private
	     */
	    function _boundarySplit($input, $boundary)
	    {
			$boundary=trim($boundary);
			if(substr($boundary,-1)=='"')
		     	$boundary=substr_replace($boundary,"" ,-1 );
			if(substr($boundary,0,1)=='"')
		     	$boundary=substr_replace($boundary,"" ,0,1);
			$boundary=trim($boundary);
		    $tmp = explode('--'.$boundary,$input);//boundary
	        for ($i=1; $i<count($tmp)-1; $i++) {
	            $parts[] = $tmp[$i];
	        }
 
	        return $parts;
	    }
 
	    /**
	     * Given a header, this function will decode it
	     * according to RFC2047. Probably not *exactly*
	     * conformant, but it does pass all the given
	     * examples (in RFC2047).
	     *
	     * @param string Input header value to decode
	     * @return string Decoded header value
	     * @access private
	     */
	    function _decodeHeader($input)
	    {
	        // Remove white space between encoded-words
	        $input = preg_replace('/(=\?[^?]+\?(q|b)\?[^?]*\?=)(\s)+=\?/i', '\1=?', $input);
 
	        // For each encoded-word...
	        while (preg_match('/(=\?([^?]+)\?(q|b)\?([^?]*)\?=)/i', $input, $matches)) {
 
	            $encoded  = $matches[1];
	            $charset  = $matches[2];
	            $encoding = $matches[3];
	            $text     = $matches[4];
 
	            switch (strtolower($encoding)) {
	                case 'b':
	                    $text = base64_decode($text);  //base64_decode_fix()
	                    break;
 
	                case 'q':
	                    $text = str_replace('_', ' ', $text);
	                    preg_match_all('/=([a-f0-9]{2})/i', $text, $matches);
	                    foreach($matches[1] as $value)
	                        $text = str_replace('='.$value, chr(hexdec($value)), $text);
	                    break;
	            }
 
	            $input = str_replace($encoded, $text, $input);
	        }
 
	        return $input;
	    }
 
	    /**
	     * Given a body string and an encoding type,
	     * this function will decode and return it.
	     *
	     * @param  string Input body to decode
	     * @param  string Encoding type to use.
	     * @return string Decoded body
	     * @access private
	     */
	    function _decodeBody($input, $encoding = '7bit')
	    {
			//echo "<hr>Encoding:$encoding";
 
	        switch (strtolower($encoding)) {
	            case '7bit':
	                return $input;
	                break;
 
	            case 'quoted-printable':
	                return $this->_quotedPrintableDecode($input);
	                break;
 
	            case 'base64':
	                $temp = base64_decode($input, true);  //base64_decode_fix()  // use this?
					// Kevin note: some weird things happen here.  some are already base64 decoded and as such we will get false returned from certain emails.
					if ($temp != false)
						return $temp;
					else
						return $input;
	                break;
 
	            default:
	                return $input;
	        }
	    }
 
		// TODO: not in use at the moment.  Placed in code for people with other less recent versions of PHP.
		// This is a workaround for bug in php 4.3.11 through 4.4.7, 5.1.2 through 5.2.4 and perhaps others (http://bugs.php.net/bug.php?id=37244) 
		function  base64_decode_fix( $data, $strict = false ) 
		{ 
			if( $strict ) 
				if( preg_match( '![^a-zA-Z0-9/+=]!', $data ) ) 
					return( false ); 
 
			return( base64_decode( $data ) ); 
		}		
 
	    /**
	     * Given a quoted-printable string, this
	     * function will decode and return it.
	     *
	     * @param  string Input body to decode
	     * @return string Decoded body
	     * @access private
	     */
	    function _quotedPrintableDecode($input)
	    {
	        // Remove soft line breaks
	        $input = preg_replace("/=\r?\n/", '', $input);
 
	        // Replace encoded characters
			$input = preg_replace('/=([a-f0-9]{2})/ie', "chr(hexdec('\\1'))", $input);
 
	        return $input;
	    }
 
	    /**
	     * Checks the input for uuencoded files and returns
	     * an array of them. Can be called statically, eg:
	     *
	     * $files =& MIMEDECODE::uudecode($some_text);
	     *
	     * It will check for the begin 666 ... end syntax
	     * however and won't just blindly decode whatever you
	     * pass it.
	     *
	     * @param  string Input body to look for attahcments in
	     * @return array  Decoded bodies, filenames and permissions
	     * @access public
	     * @author Unknown
	     */
	    function &uudecode($input)
	    {
	        // Find all uuencoded sections
	        preg_match_all("/begin ([0-7]{3}) (.+)\r?\n(.+)\r?\nend/Us", $input, $matches);
 
	        for ($j = 0; $j < count($matches[3]); $j++) {
 
	            $str      = $matches[3][$j];
	            $filename = $matches[2][$j];
	            $fileperm = $matches[1][$j];
 
	            $file = '';
	            $str = preg_split("/\r?\n/", trim($str));
	            $strlen = count($str);
 
	            for ($i = 0; $i < $strlen; $i++) {
	                $pos = 1;
	                $d = 0;
	                $len=(int)(((ord(substr($str[$i],0,1)) -32) - ' ') & 077);
 
	                while (($d + 3 <= $len) AND ($pos + 4 <= strlen($str[$i]))) {
	                    $c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20);
	                    $c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20);
	                    $c2 = (ord(substr($str[$i],$pos+2,1)) ^ 0x20);
	                    $c3 = (ord(substr($str[$i],$pos+3,1)) ^ 0x20);
	                    $file .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4));
 
	                    $file .= chr(((($c1 - ' ') & 077) << 4) | ((($c2 - ' ') & 077) >> 2));
 
	                    $file .= chr(((($c2 - ' ') & 077) << 6) |  (($c3 - ' ') & 077));
 
	                    $pos += 4;
	                    $d += 3;
	                }
 
	                if (($d + 2 <= $len) && ($pos + 3 <= strlen($str[$i]))) {
	                    $c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20);
	                    $c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20);
	                    $c2 = (ord(substr($str[$i],$pos+2,1)) ^ 0x20);
	                    $file .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4));
 
	                    $file .= chr(((($c1 - ' ') & 077) << 4) | ((($c2 - ' ') & 077) >> 2));
 
	                    $pos += 3;
	                    $d += 2;
	                }
 
	                if (($d + 1 <= $len) && ($pos + 2 <= strlen($str[$i]))) {
	                    $c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20);
	                    $c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20);
	                    $file .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4));
 
	                }
	            }
	            $files[] = array('filename' => $filename, 'fileperm' => $fileperm, 'filedata' => $file);
	        }
 
	        return $files;
	    }
 
	    /**
	     * getSendArray() returns the arguments required for Mail::send()
	     * used to build the arguments for a mail::send() call 
	     *
	     * Usage:
	     * $mailtext = Full email (for example generated by a template)
	     * $decoder = new MIMEDECODE($mailtext);
	     * $parts =  $decoder->getSendArray();
	     * if (!PEAR::isError($parts) {
	     *     list($recipents,$headers,$body) = $parts;
	     *     $mail = Mail::factory('smtp');
	     *     $mail->send($recipents,$headers,$body);
	     * } else {
	     *     echo $parts->message;
	     * }
	     * @return mixed   array of recipeint, headers,body or Pear_Error
	     * @access public
	     * @author Alan Knowles <alan@akbkhome.com>
	     */
	    function getSendArray()
	    {
	        // prevent warning if this is not set
	        $this->_decode_headers = FALSE;
	        $headerlist =$this->_parseHeaders($this->_header);
	        $to = "";
	        if (!$headerlist) {
	            return $this->raiseError("Message did not contain headers");
	        }
	        foreach($headerlist as $item) {
	            $header[$item['name']] = $item['value'];
	            switch (strtolower($item['name'])) {
	                case "to":
	                case "cc":
	                case "bcc":
	                    $to = ",".$item['value'];
	                default:
	                   break;
	            }
	        }
	        if ($to == "") {
	            return $this->raiseError("Message did not contain any recipents");
	        }
	        $to = substr($to,1);
	        return array($to,$header,$this->_body);
	    } 
 
	    /**
	     * Returns a xml copy of the output of
	     * MIMEDECODE::decode. Pass the output in as the
	     * argument. This function can be called statically. Eg:
	     *
	     * $output = $obj->decode();
	     * $xml    = MIMEDECODE::getXML($output);
	     *
	     * The DTD used for this should have been in the package. Or
	     * alternatively you can get it from cvs, or here:
	     * http://www.phpguru.org/xmail/xmail.dtd.
	     *
	     * @param  object Input to convert to xml. This should be the
	     *                output of the MIMEDECODE::decode function
	     * @return string XML version of input
	     * @access public
	     */
	    function getXML($input)
	    {
	        $crlf    =  "\r\n";
	        $output  = '<?xml version=\'1.0\'?>' . $crlf .
	                   '<!DOCTYPE email SYSTEM "http://www.phpguru.org/xmail/xmail.dtd">' . $crlf .
	                   '<email>' . $crlf .
	                   MIMEDECODE::_getXML($input) .
	                   '</email>';
 
	        return $output;
	    }
 
	    /**
	     * Function that does the actual conversion to xml. Does a single
	     * mimepart at a time.
	     *
	     * @param  object  Input to convert to xml. This is a mimepart object.
	     *                 It may or may not contain subparts.
	     * @param  integer Number of tabs to indent
	     * @return string  XML version of input
	     * @access private
	     */
	    function _getXML($input, $indent = 1)
	    {
	        $htab    =  "\t";
	        $crlf    =  "\r\n";
	        $output  =  '';
	        $headers = @(array)$input->headers;
 
	        foreach ($headers as $hdr_name => $hdr_value) {
 
	            // Multiple headers with this name
	            if (is_array($headers[$hdr_name])) {
	                for ($i = 0; $i < count($hdr_value); $i++) {
	                    $output .= MIMEDECODE::_getXML_helper($hdr_name, $hdr_value[$i], $indent);
	                }
 
	            // Only one header of this sort
	            } else {
	                $output .= MIMEDECODE::_getXML_helper($hdr_name, $hdr_value, $indent);
	            }
	        }
 
	        if (!empty($input->parts)) {
	            for ($i = 0; $i < count($input->parts); $i++) {
	                $output .= $crlf . str_repeat($htab, $indent) . '<mimepart>' . $crlf .
	                           MIMEDECODE::_getXML($input->parts[$i], $indent+1) .
	                           str_repeat($htab, $indent) . '</mimepart>' . $crlf;
	            }
	        } elseif (isset($input->body)) {
	            $output .= $crlf . str_repeat($htab, $indent) . '<body><![CDATA[' .
	                       $input->body . ']]></body>' . $crlf;
	        }
 
	        return $output;
	    }
 
	    /**
	     * Helper function to _getXML(). Returns xml of a header.
	     *
	     * @param  string  Name of header
	     * @param  string  Value of header
	     * @param  integer Number of tabs to indent
	     * @return string  XML version of input
	     * @access private
	     */
	    function _getXML_helper($hdr_name, $hdr_value, $indent)
	    {
	        $htab   = "\t";
	        $crlf   = "\r\n";
	        $return = '';
 
	        $new_hdr_value = ($hdr_name != 'received') ? MIMEDECODE::_parseHeaderValue($hdr_value) : array('value' => $hdr_value);
	        $new_hdr_name  = str_replace(' ', '-', ucwords(str_replace('-', ' ', $hdr_name)));
 
	        // Sort out any parameters
	        if (!empty($new_hdr_value['other'])) {
	            foreach ($new_hdr_value['other'] as $paramname => $paramvalue) {
	                $params[] = str_repeat($htab, $indent) . $htab . '<parameter>' . $crlf .
	                            str_repeat($htab, $indent) . $htab . $htab . '<paramname>' . htmlspecialchars($paramname) . '</paramname>' . $crlf .
	                            str_repeat($htab, $indent) . $htab . $htab . '<paramvalue>' . htmlspecialchars($paramvalue) . '</paramvalue>' . $crlf .
	                            str_repeat($htab, $indent) . $htab . '</parameter>' . $crlf;
	            }
 
	            $params = implode('', $params);
	        } else {
	            $params = '';
	        }
 
	        $return = str_repeat($htab, $indent) . '<header>' . $crlf .
	                  str_repeat($htab, $indent) . $htab . '<headername>' . htmlspecialchars($new_hdr_name) . '</headername>' . $crlf .
	                  str_repeat($htab, $indent) . $htab . '<headervalue>' . htmlspecialchars($new_hdr_value['value']) . '</headervalue>' . $crlf .
	                  $params .
	                  str_repeat($htab, $indent) . '</header>' . $crlf;
 
	        return $return;
	    }
 
		/*this function is used to get the parsed message  or you shoud say fineal message
		/////arguments [in]$object = object returned by get_message function defined above
		/////arguments [in]$msg = a pointer to messgae
		///// this function returns message string
		*/
		function get_parsed_message()
		{
			$msg = "";
			// kevin edit (moved to mimedecode function 
			//$this->_mailObjectDecoded = $this->decode();
 
			$msg.="<b>To : </b>".$this->_mailObjectDecoded->headers["to"]."<br>";
			$msg.="<b>From : </b>".$this->_mailObjectDecoded->headers["from"]."<br>";
			$msg.="<b>Subject : </b>".$this->_mailObjectDecoded->headers["subject"]."<br>";
			$msg.="<b>Date : </b>".$this->_mailObjectDecoded->headers["date"]."<br><br>";
			$main_content_type=trim($this->_mailObjectDecoded->ctype_primary)."/".trim($this->_mailObjectDecoded->ctype_secondary);
			//trim(strtok($object->headers['content-type'],";"));
			$msg.=$this->walk(&$this->_mailObjectDecoded,"",$main_content_type);
			return $msg;
		}
 
		function walk($object,$msg="",$main_content_type="")
		{			
			//echo "===============\r\nWalkcount: ".$this->walkcount++."\r\n";			
 
			if(!isset($object->parts))
			{
				//$ctype=trim(strtok($object->headers['content-type'],";"));
				$ctype=trim($object->ctype_primary)."/".trim($object->ctype_secondary);
 
				switch($ctype)
				{
					case "text/html":
						$msg.=$object->body;
						break;
					case "text/plain":
						$enc=$object->headers['content-transfer-encoding'];
						if($enc!="quoted-printable")
							$msg.=nl2br($object->body);
						break;
					case "image/jpeg":
					case "image/gif":
 
						// todo: fix the appending of .gif?
						$name=isset($object->headers['name'])? trim($object->headers['name']) : "NoName_.gif";		
 
						$cid=trim($object->headers['content-id']);		
						$cid=str_replace("<","",$cid);
						$cid=str_replace(">","",$cid);
						if(empty($name))
							 trim(strtok($object->headers['content-type'],"="));
						//$name=trim(strtok("=\""));
						$temp="pop3_temp/";
						@mkdir($temp,0777);
						$tmpfile=$temp.$name;
						//$tmpfile=realpath($tmpfile);
						//echo "\r\ntmpfile:$tmpfile\r\n";
						$fp=fopen($tmpfile,"w");
						fwrite($fp,$object->body);
						fclose($fp);
						if($main_content_type=="multipart/mixed")
						{
							$msg.="<hr>";
							$msg.="<a href='$tmpfile' target='_blank'>$name</a>";
							$msg.="<hr>";
							$msg.="<img src='$tmpfile'>";			
						}
						$msg=str_replace("cid:$cid",$tmpfile,$msg);
						//@unlink($tmpfile);
						break;
					default:
						$name=trim($object->headers['name']);		
						if(empty($name))
							 trim(strtok($object->headers['content-type'],"="));
						$name=trim(strtok("=\""));
						$temp="pop3_temp/";
						@mkdir($temp,777);
						$tmpfile=$temp.$name;
						//$tmpfile=realpath($tmpfile);
						$fp=fopen($tmpfile,"w");
						fwrite($fp,$object->body);
						fclose($fp);
						$msg.="<hr>";
						$msg.="<a href='$tmpfile' target='_blank'>$name</a>";
						break;
				}
			}
			else
			{
				foreach($object->parts as $obj)
					$this->walk($obj,&$msg,$main_content_type);
			}
			return $msg;
		}
 
 
	#########################################################################
	# BEGIN KEVIN'S FUNCTIONS
	########################################################################			
 
		function get_header($name)
		{
			$name = strtolower($name);
			$str = (isset($this->_mailObjectDecoded->headers[$name]))? $this->_mailObjectDecoded->headers[$name] : "";
			return $str;
		}
 
		function getFromEmail()
		{			
			$string = (isset($this->_mailObjectDecoded->headers["from"]))? $this->_mailObjectDecoded->headers["from"] : "";			
			$out = "";
			foreach(preg_split('/\s/', $string) as $token) 
			{
				$email = filter_var(filter_var($token, FILTER_SANITIZE_EMAIL), FILTER_VALIDATE_EMAIL);
				if ($email !== false) 
				{
					$out .= $email;
				}
			}
			return $out;			
		}	
 
		function getBody()
		{
			$body = "";
			$arr = $this->getObjects($this->_mailObjectDecoded, array(), "ctype_primary", "text");
			//return print_r($arr, true);
 
			foreach($arr as $obj)
			{
				$body = $obj->body;
			}
			return $body;
		}
 
		function getImageObjects()
		{
			//// SAMPLE OBJECT STRUCTURE...
			/*  
			Email 3...
			[0] => stdClass Object
					(
						[headers] => Array
							(
								[content-type] => image/jpeg; Name=JJ_Grey_and_MOFRO!!.jpg
								[content-id] => <JJ_Grey_and_MOFRO!!.jpg>
								[content-location] => JJ_Grey_and_MOFRO!!.jpg
								[content-transfer-encoding] => BASE64
								[content-disposition] => attachment; filename=JJ_Grey_and_MOFRO!!.jpg
							)
 
						[ctype_primary] => image
						[ctype_secondary] => jpeg
						[ctype_parameters] => Array
							(
								[Name] => JJ_Grey_and_MOFRO!!.jpg
								[name] => JJ_Grey_and_MOFRO!!.jpg
							)
 
						[disposition] => attachment
						[d_parameters] => Array
							(
								[filename] => JJ_Grey_and_MOFRO!!.jpg
							)
 
						[body] =>
 
 
 
 
			*/		
 
			$arr = $this->getObjects($this->_mailObjectDecoded, array(), "ctype_primary", "image");
			return $arr;
		}
 
		// todo: finish...
		function getAttachmentObjects($ctype_primary)
		{
			$arr = $this->getObjects($this->_mailObjectDecoded, array(), "ctype_primary", $ctype_primary);
			return $arr;
		}
 
		function saveImageToDisk($object,$name)
		{	
			$msg = "Error Saving Image '$name' To Disk";
			//$ctype=trim(strtok($object->headers['content-type'],";"));
			$ctype = strtolower(trim($object->ctype_primary)."/".trim($object->ctype_secondary));
			//echo "<br>ctype: $ctype";
 
			switch($ctype)
			{
				case ("image/png" || "image/jpeg" || "image/gif"):
					$temp="pop3_temp/";
					@mkdir($temp,0777);
					$tmpfile = $temp.$name;
					//$tmpfile=realpath($tmpfile);
					//echo "\r\ntmpfile:$tmpfile\r\n";
					$fp=fopen($tmpfile,"w");					
					fwrite($fp,$object->body);										
					fclose($fp);
					$msg = "<a href='$tmpfile' target='_blank'><img style='width:150px;' src='$tmpfile'></a>";						
					break;
				default:
					// todo: handle other types of attachments
					$temp="pop3_temp/";
					@mkdir($temp,777);
					$tmpfile=$temp.$name;
					//$tmpfile=realpath($tmpfile);
					$fp=fopen($tmpfile,"w");
					fwrite($fp,$object->body);
					fclose($fp);
					$msg = "<a href='$tmpfile' target='_blank'>$name</a>";
					break;
			}
			return $msg;
		}
 
		function getImageName($o)
		{
			if (isset($o->ctype_parameters["name"]))
				return trim($o->ctype_parameters["name"]);
			if (isset($o->d_parameters["filename"]))
				return trim($o->d_parameters["filename"]);			
 
			return "UnknownFileName";
		}
 
		function getObjects($object, $array=array(), $keyName, $valueName)
		{							
			foreach($object as $obj)
			{								
				if (isset($obj[$keyName]))
				{
					if ($obj === $valueName)
					{
						array_push($array, $object);
						//echo "<hr style='border:1px solid green;'>";																												
						//print_r($array);
						//echo "ctype_primary: '".$obj."'";
						//echo "<br>";
						//print_r($object);
					}
				}
 
				// Seek nested objects in arrays...
				if (gettype($obj) === "array")
				{
					foreach($obj as $key => $value) 
					{																
						if (gettype($value) === "object")
						{
							//echo "<hr style='border:1px solid blue;'>";	
							$array = $this->getObjects($value, $array, $keyName, $valueName);
						}
					}
				}
				else if (gettype($obj) === "object")  // Seek nested objects in object...
				{				
					$array = $this->getObjects($obj, $array, $keyName, $valueName);
				}
			}
			return $array;
		}		
 
	}
?>
Posted in Uncategorized | Leave a comment