PHP Classes
Icontem

File: File_Format_Iaf.php


  Search   All class groups All class groups   Latest entries Latest entries   Top 10 charts Top 10 charts   Newsletter Newsletter   Blog Blog   Forums Forums   Help FAQ Help FAQ  
  Login   Register  
Recommend this page to a friend! ReTweet ReTweet Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of ruslan kononov  >  IAF decoder coder  >  File_Format_Iaf.php  
File: File_Format_Iaf.php
Role: Class source
Content type: text/plain
Description: Main class
Class: IAF decoder coder
Parse and generate Outlook IAF configuration files
 

Contents

Class file image Download
<?php

/*
	
	This class is php port of Perl package : Win32-Outlook-IAF
	http://search.cpan.org/dist/Win32-Outlook-IAF

	All regards to Przemek Czerkas
	
	author: Kononov Ruslan, 2008
	ver: 1.0.2
	
*/

class File_Format_Iaf
{
	private $HEADER = "\x66\x4D\x41\x49\x00\x00\x05\x00\x01\x00\x00\x00";
	private $PASSWORD_SEED = "\x75\x18\x15\x14";
	private $PASSWORD_HEADER ="\x01\x01";
	private $MAX_FIELD_LENGTH = 4096;

	// @todo разобраться с кодировками
	// public $_encoding_server;
	// public $_encoding_iaf;
	/*
		// iaf file encoding
		vista (rus) - utf-16le
		xp (rus) - cp1251
	*/

	private $_fieldFormatCheck = array(
		'bool_re' => '/^[01]$/', // boolean
		'num_re' => '/^\d+$/',	// numeric
		'regkey_re' => '/^[0-9a-z\{\}\-\-\.]+$/i', // registry key
		'iaf_ct_re' => '/^[0123]$/', // ConnectionType
		'iaf_am_re' => '/^[0123]$/', // AuthMethod enums
		'iaf_pf_re' => '/^[012]$/' // NNTP PostingFormat
	);

	// current loaded file
	private $_file;
	
	// IAF fields
	private $_fieldsTable = array(
		
		// added from Vista
		'DeletedItems' => array('313721840', 'nullstr_fmt', '', ''),
		'JunkEmail' => array('313787376', 'nullstr_fmt', '', ''),
		'323552245' => array('323552245', 'nullstr_fmt', '', ''),
		
		// Win32-Outlook-IAF
		// fix
		'AccountID' => array('305988592', 'nullstr_fmt', '', ''),
	
		// original
		'AccountName' => array('305464304', 'nullstr_fmt', '', ''),
		'TemporaryAccount' => array('305595369', 'ulong_le_fmt', 'bool_re', ''),
		'ConnectionType' => array('305726441', 'ulong_le_fmt', 'iaf_ct_re', ''),
		'ConnectionName' => array('305791984', 'nullstr_fmt', '', ''),
		'ConnectionFlags' => array('305857513', 'ulong_le_fmt', 'num_re', ''),
		'BackupConnectionName' => array('306054128', 'nullstr_fmt', '', ''),
		'MakeAvailableOffline' => array('306185193', 'ulong_le_fmt', 'bool_re', ''),
		'ServerReadOnly' => array('306316277', 'ulong_le_fmt', 'bool_re', ''),
		'IMAPServer' => array('311952368', 'nullstr_fmt', '', ''),
		'IMAPUserName' => array('312017904', 'nullstr_fmt', '', ''),
		'IMAPPassword' => array('312083446', 'nullstr_fmt', '', 'iaf_password'),
		'IMAPAuthUseSPA' => array('312214517', 'ulong_le_fmt', 'bool_re', ''),
		'IMAPPort' => array('312280041', 'ulong_le_fmt', 'num_re', ''),
		'IMAPSecureConnection' => array('312345589', 'ulong_le_fmt', 'bool_re', 'iaf_bool'),
		'IMAPTimeout' => array('312411113', 'ulong_le_fmt', 'num_re', ''),
		'IMAPRootFolder' => array('312476656', 'nullstr_fmt', '', ''),
		'IMAPUseLSUB' => array('312673269', 'ulong_le_fmt', 'bool_re', 'iaf_bool'),
		'IMAPPolling' => array('312738805', 'ulong_le_fmt', 'bool_re', 'iaf_bool'),
		'IMAPFullList' => array('312804341', 'ulong_le_fmt', 'bool_re', 'iaf_bool'),
		'IMAPStoreSpecialFolders' => array('313000949', 'ulong_le_fmt', 'bool_re', 'iaf_bool'),
		'IMAPSentItemsFolder' => array('313066480', 'nullstr_fmt', '', ''),
		'IMAPDraftsFolder' => array('313197552', 'nullstr_fmt', '', ''),
		'IMAPPasswordPrompt' => array('313525237', 'ulong_le_fmt', 'bool_re', 'iaf_bool'),
		'IMAPDirty' => array('313590761', 'ulong_le_fmt', 'bool_re', 'iaf_bool'),
		'IMAPPollAllFolders' => array('313656309', 'ulong_le_fmt', 'bool_re', 'iaf_bool'),
		'HTTPServer' => array('321782768', 'nullstr_fmt', '', ''),
		'HTTPUserName' => array('321848304', 'nullstr_fmt', '', ''),
		'HTTPPassword' => array('321913846', 'nullstr_fmt', '', 'iaf_password'),
		'HTTPPasswordPrompt' => array('321979381', 'ulong_le_fmt', 'bool_re', 'iaf_bool'),
		'HTTPAuthUseSPA' => array('322044905', 'ulong_le_fmt', 'bool_re', ''),
		'HTTPFriendlyName' => array('322110448', 'nullstr_fmt', '', ''),
		'DomainIsMSN' => array('322175989', 'ulong_le_fmt', 'bool_re', 'iaf_bool'),
		'HTTPPolling' => array('322241525', 'ulong_le_fmt', 'bool_re', 'iaf_bool'),
		'AdBarURL' => array('322307056', 'nullstr_fmt', '', ''),
		'ShowAdBar' => array('322372597', 'ulong_le_fmt', 'bool_re', 'iaf_bool'),
		'MinPollingInterval' => array('322438135', 'ulong_le_fmt', 'num_re', ''),
		'GotPollingInterval' => array('322503669', 'ulong_le_fmt', 'bool_re', 'iaf_bool'),
		'LastPolledTime' => array('322569207', 'ulong_le_fmt', 'num_re', ''),
		'NNTPServer' => array('325059568', 'nullstr_fmt', '', ''),
		'NNTPUserName' => array('325125104', 'nullstr_fmt', '', ''),
		'NNTPPassword' => array('325190646', 'nullstr_fmt', '', 'iaf_password'),
		'NNTPAuthMethod' => array('325321717', 'ulong_le_fmt', 'iaf_am_re', ''),
		'NNTPPort' => array('325387241', 'ulong_le_fmt', 'num_re', ''),
		'NNTPSecureConnection' => array('325452789', 'ulong_le_fmt', 'bool_re', 'iaf_bool'),
		'NNTPTimeout' => array('325518313', 'ulong_le_fmt', 'num_re', ''),
		'NNTPDisplayName' => array('325583856', 'nullstr_fmt', '', ''),
		'NNTPOrganizationName' => array('325649392', 'nullstr_fmt', '', ''),
		'NNTPEmailAddress' => array('325714928', 'nullstr_fmt', '', ''),
		'NNTPReplyToEmailAddress' => array('325780464', 'nullstr_fmt', '', ''),
		'NNTPSplitMessages' => array('325846005', 'ulong_le_fmt', 'bool_re', 'iaf_bool'),
		'NNTPSplitMessageSize' => array('325911529', 'ulong_le_fmt', 'num_re', ''),
		'NNTPUseGroupDescriptions' => array('325977077', 'ulong_le_fmt', 'bool_re', 'iaf_bool'),
		'NNTPPolling' => array('326108149', 'ulong_le_fmt', 'bool_re', 'iaf_bool'),
		'NNTPPostingFormat' => array('326173673', 'ulong_le_fmt', 'iaf_pf_re', ''),
		'NNTPSignature' => array('326239216', 'nullstr_fmt', 'regkey_re', ''),
		'NNTPPasswordPrompt' => array('326304757', 'ulong_le_fmt', 'bool_re', 'iaf_bool'),
		'POP3Server' => array('331613168', 'nullstr_fmt', '', ''),
		'POP3UserName' => array('331678704', 'nullstr_fmt', '', ''),
		'POP3Password' => array('331744246', 'nullstr_fmt', '', 'iaf_password'),
		'POP3AuthUseSPA' => array('331875317', 'ulong_le_fmt', 'bool_re', ''),
		'POP3Port' => array('331940841', 'ulong_le_fmt', 'num_re', ''),
		'POP3SecureConnection' => array('332006389', 'ulong_le_fmt', 'bool_re', 'iaf_bool'),
		'POP3Timeout' => array('332071913', 'ulong_le_fmt', 'num_re', ''),
		'POP3LeaveMailOnServer' => array('332137461', 'ulong_le_fmt', 'bool_re', 'iaf_bool'),
		'POP3RemoveWhenDeleted' => array('332202997', 'ulong_le_fmt', 'bool_re', 'iaf_bool'),
		'POP3RemoveWhenExpired' => array('332268533', 'ulong_le_fmt', 'bool_re', 'iaf_bool'),
		'POP3ExpireDays' => array('332334057', 'ulong_le_fmt', 'num_re', ''),
		'POP3SkipAccount' => array('332399605', 'ulong_le_fmt', 'bool_re', 'iaf_bool'),
		'POP3PasswordPrompt' => array('332530677', 'ulong_le_fmt', 'bool_re', 'iaf_bool'),
		'SMTPServer' => array('338166768', 'nullstr_fmt', '', ''),
		'SMTPUserName' => array('338232304', 'nullstr_fmt', '', ''),
		'SMTPPassword' => array('338297846', 'nullstr_fmt', '', 'iaf_password'),
		'SMTPAuthMethod' => array('338428905', 'ulong_le_fmt', 'iaf_am_re', ''),
		'SMTPPort' => array('338494441', 'ulong_le_fmt', 'num_re', ''),
		'SMTPSecureConnection' => array('338559989', 'ulong_le_fmt', 'bool_re', 'iaf_bool'),
		'SMTPTimeout' => array('338625513', 'ulong_le_fmt', 'num_re', ''),
		'SMTPDisplayName' => array('338691056', 'nullstr_fmt', '', ''),
		'SMTPOrganizationName' => array('338756592', 'nullstr_fmt', '', ''),
		'SMTPEmailAddress' => array('338822128', 'nullstr_fmt', '', ''),
		'SMTPReplyToEmailAddress' => array('338887664', 'nullstr_fmt', '', ''),
		'SMTPSplitMessages' => array('338953205', 'ulong_le_fmt', 'bool_re', 'iaf_bool'),
		'SMTPSplitMessageSize' => array('339018729', 'ulong_le_fmt', 'num_re', ''),
		'SMTPSignature' => array('339149808', 'nullstr_fmt', 'regkey_re', ''),
		'SMTPPasswordPrompt' => array('339215349', 'ulong_le_fmt', 'bool_re', 'iaf_bool')
	);
	// current fields
	private $_fields;

	// last error
	private $_error;
	
	public function load($file) {

		//iconv_set_encoding('internal_encoding', $this->_internal_encoding);

        $fieldsUnknown = array();
		$this->_file = $file;
        $this->_fields = array();
        $pos = 0;

		if (!is_readable($this->_file)) {
			
			$this->_error = "File '{$this->_file}' is not readable";
			return false;
		}

		$contentIAF = file_get_contents($this->_file);

		$len = strlen($contentIAF);
		$pos += strlen($this->HEADER);

		while ($pos<$len) {


			if ($pos+4 > $len) {

				$this->_error = 'Premature end of data while reading field_id';
				return false;
			}

			$field_id = current(unpack('V', substr($contentIAF, $pos, 4)));
			$pos += 4;

			if ($pos+4 > $len) {

				$this->_error = 'Premature end of data while reading field_len';
				return false;
			}

			$field_len = current(unpack('V', substr($contentIAF, $pos, 4)));
			$pos += 4;


			if (($pos+$field_len) > $len) {

				$this->_error = 'Premature end of data while reading field_len';
				return false;
			}

			if ($field_len > $this->MAX_FIELD_LENGTH) {

				$this->_error = 'Excessive field length: ' . $field_len;
				return false;
			}

			$field = substr($contentIAF, $pos, $field_len);
			$pos += $field_len;

			$key = -1;

            $field_format = null;
            $field_regex = null;
            $field_callback = null;
            
            if ($fieldParams = $this->getFieldById($field_id)) {
                
                list($field_name, , $field_format, $field_regex ,$field_callback) = $fieldParams; 
                
            } else {
                
                $fieldsUnknown[] = $field_id;
                continue;
            }


			// call callback() as 'read packed'
			if (!empty($field_callback)) $field = $this->$field_callback($field, 'read', 'packed');
			
			// apply binary format
			switch($field_format) {

				case 'ulong_le_fmt' :
					
					$field = current(unpack('V', $field));
					break;

				case 'nullstr_fmt' :

					// @todo разобраться с кодировками
					//file_put_contents("debug/{$field_name}_.txt", $field);
					//if ($this->_iaf_encoding) $field = iconv($this->_iaf_encoding, $this->_server_encoding, $field);
					$field = substr($field, 0, strrpos($field, "\0"));
					$field = current(unpack("a*", $field));

					//file_put_contents("debug/{$field_name}.txt", $field);
					
					break;

				default:
				
					$this->_error = "Unknown field format: {$field_format} for field id '{$field_id}'";
                    return false;
			}

			// call callback() as 'read unpacked'
			if (!empty($field_callback)) $field = $this->$field_callback($field, 'read', 'unpacked');
			// @todo разобраться с кодировками
			//else $field = mb_convert_encoding($field, 'windows-1251', 'UCS-4');
			
						
			if ($this->check_field($field, $field_regex)) $this->_fields[$field_name] = $field;


			$this->_fields[$field_name] = $field;
		}
        
        if (count($fieldsUnknown) > 0) {
            
            $this->_error = 'Unknown fields : ' . implode(', ', $fieldsUnknown);
            return false;
        }
        
		return true;
	}
	
	public function render()
	{

		$data = $this->HEADER;
		
		foreach ($this->_fields as $field_name => $field) {
			
            list($field_id, $field_format, ,$field_callback) = $this->_fieldsTable[$field_name];
            
			// call callback() as 'write unpacked'
			if (!empty($field_callback)) $field = $this->$field_callback($field, 'write', 'unpacked');
			
			// apply binary format
			switch($field_format) {

				case 'ulong_le_fmt' :
					
					$field = pack('V', $field);
					break;

				case 'nullstr_fmt' :
					
					$field = pack("a*", $field);
					// @todo разобраться с кодировками
					// if ($this->_iaf_encoding) $field = iconv($this->_server_encoding, $this->_iaf_encoding,  $field);
					$field .= "\0";
					break;

				default :
				
					echo "Unknown format: [{$field_format}]";
					continue;
			}
			
			// call callback() as 'write packed'
			if (!empty($field_callback)) $field = $this->$field_callback($field, 'write', 'packed');
			$field_len = pack('V', strlen($field));
			$field_id = pack('V', $field_id);
			
			$data .= $field_id . $field_len . $field;
		}
		
		return $data;
	}
	
	public function save($file = null) {
		
		$file = $file === null ? $this->_file : $file;
		
		if (empty($file)) {
			$this->_error = 'Output file not defined';
		 	return false;
		}
		
		$data = $this->render();
		
		if (file_put_contents($file, $data)) return true;
		
		return false;
	}
	
	public function __set($field, $value) {
		// @todo current	
		if (!array_key_exists($field, $this->_fieldsTable)) return;
		
		$regex = $this->_fieldsTable[$field][2];
		if (!$this->check_field($value, $regex)) return;

		$this->_fields[$field] = $value;

	}

	public function __get($field) {

		if (array_key_exists($field, $this->_fields)) return $this->_fields[$field]; 
		return false;
		
	}
	
	private function iaf_bool($value, $operation, $phase) {

		if (!($operation == 'get' || $operation == 'set')) return $value;
		return $value ? 1 : 0;

	}

	private function iaf_password($password, $operation, $phase) {

		if ($operation == 'text') return '********';
		if (!($operation == 'read' || $operation == 'write')) return $password;
		if (!($phase == 'packed')) return $password;

		$seed = $this->PASSWORD_SEED;
		$ret = '';
		$pos = 0;
		$len = strlen($password);

		if ($operation == 'read') {

			if ($pos+strlen($this->PASSWORD_HEADER) > $len)  throw new Exception('Premature end of data while reading password header');

			$pos += strlen($this->PASSWORD_HEADER);
			if ($pos+4 > $len) throw new Exception('Premature end of data while reading password_len');

			$password_len = current(unpack('V', substr($password, $pos, 4)));
			$pos += 4;
			if ($pos + $password_len != $len) throw new Exception('Malformed password record');

		} else {

			$ret = $this->PASSWORD_HEADER;
			$ret .= pack('V', $len);
		}

		while ($pos < $len) {

			$fill = $pos+4 > $len ? $pos+4-$len : 0;
			$seed=current(unpack('V', str_repeat("\x00", $fill) . substr($seed,$fill)));

			$d = current(unpack('V', str_repeat("\x00", $fill) . substr($password, $pos, 4-$fill)));
			$pos += 4 - $fill;

			$ret .= substr(pack('V', $d^$seed), $fill);

			$seed = pack('V', $operation == 'read' ? $d^$seed : $d);
		}

		return $ret;
	}

	private function check_field($field, $field_format_check) {

		if ($field_format_check) $regex = $this->_fieldFormatCheck[$field_format_check];
		else return true;

		if ($regex) {

			if (preg_match($regex, $field)) return true;
			else echo "invalid field value = '{$field}' fieldType = '{$field_format_check}'";
			
			return false;
		}
	}

	public function getFieldById($id)
	{
		foreach ($this->_fieldsTable as $field_name => $field) {
			
			if ($field[0] == $id) {
                
                array_unshift($field, $field_name);
                return $field;
            }
		}
		
        return false;
	}

	public function getFields()
	{
		return $this->_fields;
	}

	public function error()
	{
		return $this->_error;
	}
}

 
  Advertise on this site Advertise on this site   Site map Site map   Statistics Statistics   Site tips Site tips   Privacy policy Privacy policy   Contact Contact  

For more information send a message to :
info at phpclasses dot org.
Copyright (c) Icontem 1999-2009 PHP Classes - PHP Class Scripts
  PHP Book Reviews - Reviews of books and other products