I have implemented a object model, which should be extensible enough to implement different providers for managing IIS.

Method Description

  • Get Retrieves a value for a named property from the object.
  • GetDataPaths Retrieves the paths to all locations of a metabase property subordinate to a specified starting path.
  • GetEx Retrieves a value or values for a named single-valued or multivalued property of the object.
  • GetInfo Reloads the object with property values that exist in the metabase.
  • GetPropertyAttribObj Retrieves an object that contains the property’s attributes. This object can then be used to etrieve individual attributes of ADSI properties.
  • Put Sets the value for a named property of an object.
  • PutEx Sets the value or values for a named single-valued or multivalued property of the object.
  • SetInfo Writes the object property values to the metabase.

This was writen quite some time ago, however I will publish it as it simple works.

<?php

/**

* @package IIS

* @version $Id: IIS.php,v 0.1 2004/05/28 11:51:28 Andrew M. Johnstone Exp $

* @Copyright © 2003-2004 Andrew M. Johnstone (andrew@ajohnstone.com)

*/
class IIS { // extends COM { // extending Com dies()…

/**

* COM Object Parameters

* @var array

* @access public

*/

public $param=array(
‘Provider’ => ‘IIS’,

‘MachineName’ => null, // . or localhost or computername

‘ObjectPath’ => null
);

/**

* COM Object

* @var object

* @access public

*/

public $Com=null;
public function

__construct($command=null, $MachineName=‘localhost’, $ObjectPath=‘’) {

if (!isset($this->param[‘MachineName’])) $this->param[‘MachineName’]=$MachineName;
if (!isset(

$this->param[‘ObjectPath’])) $this->param[‘ObjectPath’]=$ObjectPath;

switch($command) {
case

‘Start’ : $this->StartServer();    break;

case ‘Continue’ : $this->ContinueServer(); break;
case

‘Pause’ : $this->PauseServer();    break;

case ‘Stop’ : $this->StopServer();     break;
}

try {

$this->Com = new Com(“{$this->param[Provider]}://{$this->param[MachineName]}{$this->param[ObjectPath]}”);

} catch (com_exception $e) {
die(

“TERMINATED:: n”. print_r($e));

} catch (Exception $e) {

die(“TERMINATED:: n”. print_r($e));
}

}

public function

__destruct() { unset($this->Com); }

public function __call($_callee) {
try {

switch(

$_callee) {

case ‘Start’ : return $this->Com->Start();

case ‘Continue’ : return $this->Com->Continue();
case

‘Pause’ : return $this->Com->Pause();

case ‘Stop’ : return $this->Com->Stop();
}

} catch (

exception $e) { var_dump($e); }

}

/**

* Display IIS Structure

* @var object
* @var int

* @access public

*/

public function DisplayTree($Obj, $Level) { //Recursive

if ( ($Obj->Class == “IIsWebServer”) Or ($Obj->Class == “IIsFtpServer”)) {
print

“{$Obj->Name} - {$Obj->ServerComment}n”;

} else {

print “{$Obj->Name}n”;

}

foreach ($Obj as $CurrentObj) $this->DisplayTree($CurrentObj, $Level+1);
}

/**

* @WakeUp & Think;)

*

*/

public function DisplayNode($MachineName=‘localhost’, $ObjectPath=null) {
$this->param[‘ObjectPath’]=$ObjectPath;

$this->param[‘MachineName’]=$MachineName;
switch(

$this->Com->Class) {

case “IIsComputer” :

return array(

‘MemoryCacheSize’=>$this->Com->MemoryCacheSize,
‘MaxBandwidth’=>$this->Com->MaxBandWidth

);

case “IIsWebVirtualDir” :

return array(

‘Path’=>$this->Com->path,
‘Defaultdocument’=>$this->Com->DefaultDoc,

‘UNCUserName’=>$this->Com->UNCUserName,
‘Directorybrowsing’=>$this->Com->EnableDirBrowsing,

‘ReadAccess’=>$this->Com->AccessRead,
‘WriteAccess’=>$this->Com->AccessWrite,

);

case “IIsFtpVirtualDir” :

return array(
‘Path’=>$this->Com->path,

‘UNCUserName’=>$this->Com->UNCUserName,
‘ReadAccess’=>$this->Com->AccessRead,

‘WriteAccess’=>$this->Com->AccessWrite,
);

case

“IIsWebService” :

return array(

‘DirectoryBrowsing’=>$this->Com->EnableDirBrowsing,
‘DefaultDocument’=>$this->Com->DefaultDoc,

‘ScriptAccess’=>$this->Com->AccessScript,
‘ExecuteAccess’=>$this->Com->AccessExecute

);

case “IIsFtpService” :

return array(

‘EnablePortAttack’=>$this->Com->EnablePortAttack,
‘LowerCaseFiles’=>$this->Com->LowerCaseFiles

);

case “IIsWebServer” :

return array(

‘1stBinding’=>$this->Com->ServerBindings(0,0),
‘State’=>$this->ServerState($this->Com->ServerState),

‘KeyType’=>$this->Com->KeyType
);

case “IIsFtpServer” :

return array(

‘State’=>$this->ServerState($this->Com->ServerState),
‘GreetingMessage’=>$this->Com->GreetingMessage,

‘ExitMessage’=>$this->Com->ExitMessage,
‘MaxClients Message’=>$this->Com->MaxClientsMessage,

‘AnonymousOnly’=>$this->Com->AnonymousOnly,
);

case (

“IIsWebService” or “IIsFTPService” or ‘IIsWebServer’ or ‘IIsFTPServer’) :

return array(

‘ServerComment’=>$this->Com->ServerComment,
‘AnonymousUserName’=>$this->Com->AnonymousUserName,

‘DefaultLogonDomain’=>$this->Com->DefaultLogonDomain,
‘MaxConnections’=>$this->Com->MaxConnections,

‘ConnectionTimeout’=>$this->Com->ConnectionTimeout,
‘ReadAccess’=>$this->Com->AccessRead,

‘WriteAccess’=>$this->Com->AccessWrite,
‘Log’=>$this->Com->DontLog,

);

}

}

/**
* Strut

* @var int

* @access public

* @return string

*/

public function ServerState($StateVal) {

switch ($StateVal) {
case

1 : return ‘Starting’;

case 2 : return ‘Started’;

case 3 : return ‘Stopping’;
case

4 : return ‘Stopped’;

case 5 : return ‘Pausing’;

case 6 : return ‘Paused’;
case

7 : return ‘Continuing’;

default: return ‘Unknown!’;

}

}

/**

* Backups Located at %systemroot%system32inetsrvMetaBack
* @var (bool)$Force (Overwrite)

*/

public function backupMetaBase($Name=null, $Version=-1, $Force=0) {
$Name=(!isset($Name))? ‘Created - Backup ‘.time () : ‘Custom Backup - ‘. $Name;

$this->param[‘ObjectPath’]=null;
$this->param[‘MachineName’]=‘localhost’;

//parent::__construct();

try {

$this->Com->Backup($Name, $Version, $Force);
} catch (

com_exception $e) {

print_r($e);

}

}

/**

* Backups Located at %systemroot%system32inetsrvMetaBack
*/

public function restoreMetaBase($Name=null, $Version=-2) {

$Flag=0;
$this->param[‘ObjectPath’]=null;

$this->param[‘MachineName’]=‘localhost’;
//parent::__construct();

try {

// NOTE:  ** All IIS services will be stopped by this method, then restarted!

$this->Com->Restore($Name, $Version, $Flag);; // NOTE: for restoration, Flag MUST be 0
} catch (com_exception $e) {

print_r($e);

}

}

}

class IISWeb extends IIS {
public function

__construct() { }

public function FindWeb($MachineName=‘localhost’, $WebName=null) {

$this->param[‘ObjectPath’]=‘’;///W3svc
$this->param[‘MachineName’]=$MachineName;

parent::__construct();

//View Scope

foreach ($this->Com as $obj) echo $obj->Name . “n”;
/**

* print $this->Com->W3svc->1;

*

* —

*

* $this->Com->IISADMIN
* $this->Com->Logging

* $this->Com->W3SVC

* $this->Com->MimeMap

* $this->Com->MSFTPSVC

* $this->Com->SmtpSvc

* $this->Com->EventManager

*/

}

public function mkWebDir() {} // @Stub

public function rmWebDir() {} // @Stub
public function chAccess() { /* OBJ->Put */ } // @Stub

}

/***************** *****************/

$IIS = new IIS();
//$IIS->Start();

//$IIS->Stop();

//$IIS->Pause();

//$IIS->Continue();

//print_r( $IIS->DisplayNode() );

$IISWeb = new IISWeb();
//$IISWeb->FindWeb();

//$IISWeb->DisplayTree(new Com("IIS://localhost"), 0);

$IIS->backupMetaBase();

?>

Firstly, PHP has very little dependencies. It does not need any files copied to the system root as many installation instructions state (with the exception of certain PHP extensions).

PHP from the command line.

Usage: PHP [options] [-f] <file>[--][args...]
PHP [options] -r <code> [--] [args...]
PHP [options[ [-B <begin_code>] -R <code>[-E <end_code>] [--] [args...]
PHP [options] -B <begin_code>] -F <file> [-E <end_code>] [--] [args...]
PHP [options] -- [args...]
-a Run interactively
-c <path>|<file> Look for PHP.ini file in this directory
-n No PHP.ini file will be used
-d foo[=bar] Define INI entry foo with value ‘bar’
-e Generate extended information for debugger/profiler
-f <file> Parse <file>.
-h This help
-i PHP information
-l Syntax check only ( lint)
-m Show compiled in modules
-r <code> Run PHP <code> without using script tags <?..?>
-B <begin_code> Run PHP <begin_code> before processing input lines
-R <code> Run PHP <code> for every input line
-F <file> Parse and execute <file> for every input line
-E <end_code> Run PHP <end_code> after processing all input lines
-H Hide any passed arguments from external tools.
-s Display colour syntax highlighted source.
-v Version number
-w Display source with stripped comments and whitespace.
-z Load Zend extension <file>.
args… Arguments passed to script. Use — args when first argument starts with – or script is read from stdin

As we can see a number of options can be passed to PHP that manipulates the way PHP acts. This will allow us to define the location of PHP.ini, if defined at all or other parameters that maybe injected. Apache is also configurable in a manner that will allow us to choose the PHP version to run upon apache‘s execution. For Example placing the following in httpd.conf will allow you to choose the version of PHP to be executed with apache.

<ifdefine PHP-5.0.0RC1>
  LoadModule PHP5_module C:\PHP\Distributions\PHP-5.0.0RC1-Win32\PHP5apache.dll
</ifdefine>

<ifdefine PHP-5.0.0RC2>
  LoadModule PHP5_module C:\PHP\Distributions\PHP-5.0.0RC2\PHP5apache.dll
</ifdefine>

<ifdefine PHP-5.0.0RC3>
  LoadModule PHP5_module C:\PHP\Distributions\PHP-5.0.0RC3-Win32\PHP5apache.dll
</ifdefine>

Using ‘ apache.exe -D PHP-5.0.0RC3-Win32‘.

Note: IfDefine is case sensative, also ensure Capital D is used in the command line as lower case has a different function (-d directory initial value for ServerRoot & -D parameter define parameter for <ifdefine>).

If any failures occur at this point, there are two common reasons, firstly in early versions of PHP, version 4 requires PHP.ini & PHP4ts.dll. As so many installation manuals like to tell you DO NOT PLACE ANY FILES IN THE SYSTEM ROOT, the best way to encapsulate installations is by placing any required file in the root path of the PHP.exe location, if using CLI copy the (PHP4ts.dll or PHP5ts.dll) & PHP.ini to that directory.

The order for PHP is to locate required files is %system%, %system32%, %systemroot%, %apacheroot%, %phproot%; in the general order of the system variable %path%. I recommend the follow directory structure when installing PHP

cvs -d :pserver:cvsread@cvs.PHP.net:/repository checkout phpweb/distributions (extract all)

C:.
---PHP
    +---Distributions
        +---PHP-3.0.17-win32
        +---PHP-4.3.2-Win32
        +---PHP-4.3.3-Win32
        +---PHP-4.3.4-Win32
        +---PHP-4.3.5-Win32
        +---PHP-4.3.6-Win32
        +---PHP-4.3.7-Win32
        +---PHP-5.0.0RC1-Win32
        +---PHP-5.0.0RC2-Win32
        +---PHP-5.0.0RC3-Win32

For each, rename ‘PHP.ini-dist’ to ‘PHP.ini’ and if applicable copy ‘PHP.ini-dist’ & ‘PHP4ts.dll/PHP5ts.dll’ to the directory ‘cli’ as well as ammending ‘PHP.ini’ temp path to your systems temp. From each %rootphp% path you can configure that installation with its own customised ‘ini’. I recommend reading PHP directives at php.net. From this you can setup VirtualHosts, such as http://PHP4/, http://php5/ etc, which will make switching between PHP 3, 4 & 5 simple :) . Note: This is for development purposes and should not be used in a production enviroment.

  • Share/Bookmark

Extending on Wez Furlongs article at zend on Com… Firstly lets clear up a little introduction to ADSI and its relevance to Com.

Active Directory Service Interfaces (ADSI) abstracts the capabilities of directory services from different network providers in a distributed computing environment, to present a single set of directory service interfaces for managing network resources. Administrators and developers can use ADSI services to enumerate and manage the resources in a directory service, no matter which network environment contains the resource.

The following figure shows how ADSI fits into an application environment. Whether the application is written in Visual Basic, C/C++, VBScript, Microsoft JScript, or as a Web application using Active Server Pages, Active Directory Service Interfaces provide a clean and easy-to-use access to the underlying directory services without having to use the native network APIs.

Thats nice, but what can ADSI do?

ADSI exposes interfaces to automate common administrative tasks, such as adding users and groups, managing printers, and setting permissions on network resources. Administrators use Windows Management Instrumentation (WMI) to manage operating systems via Windows Management Instrumentation Query Language (WQL). WMI is a component of the Windows OS that is an industry initiative to develop a standard technology for accessing management information in an enterprise environment, which uses the Common Information Model (CIM) provider that represent systems, applications, networks, devices, and other managed components. Confused?

Through the use of these providers,..

  • winmgmts://
  • cim://
  • LDAP://
  • WinNT://
  • NDS://
  • NWCOMPAT://
  • More Providers

Some simple examples… Read the rest of this entry »

Recently I have been researching into multi-lingual content, admittedly I have never properly looked into the concepts of Internationalization and Localization (i18n, l10n) before. Whilst reading the ICU documents. I have realised there is a significant lack of support for i18n & l10n in PHP applications. Despite the controversy with enterprise PHP, and the contenders commonly mentioned eZ Systems & Interakt, they still have limited support despite weak attempts at globalization (g11n).

The problem with i18n is the broad complexity of the field. Whilst PHP may well be able to handle i18n, it does not mean that the database or repertoire can? With regard to PHP in particular, I find that we make far too many assumptions; In general, this is a pitfall in many programming languages, so it is not justified pin pointing PHP developers. Whilst those particular details are applicable to i18n, we essentially need to look at a complete solution as a whole, which computer-based translation is just part of a recipe for an efficient globalized product.

I had a fundamental problem when I looked into Internationalizing data, this was simply to do with structuring globalized content. It is relatively simple handling string literals, which can be placed in a database and normalized. However, binary data and other forms of media are not ideally placed in a database. As, such structuring this data is challenging with regard to replication. Do you categorize content by country or language; as a result, I have concluded that replication is unavoidable in this instance. Although the approach that Internationalized Components for Unicode has taken with resource bundling is in hindsight the best approach. Some key points:-

  • Keep Data Separate
  • Keep Data Small
  • Find the Best Available Data

Whilst, this would be ideal it is not a feasible to implement for a variety of reasons, so the only ideal is to mediate content and aid linguists with a form of mediation via computer-based translation. Lets try and open our eyes and develop higher level applications.

About this blog

I have been a developer for roughly 10 years and have worked with an extensive range of technologies. Whilst working for relatively small companies, I have worked with all aspects of the development life cycle, which has given me a broad and in-depth experience.