Author Archive

Windows Phone 7 : L’astuce du jour

par Jean-françois JOLY le avr.25, 2011, dans Windows Mobile

Récemment, je me suis mis un peu au développement pour windows phone 7 et au fur et à mesure que je développe ma première application, je me retrouve confronté à des petites difficultés toutes bêtes (enfin surement pour les habitués du C# et de silverlight). Je me suis donc dit que au fur et à mesure de mon développement, j’allais partagé les solutions à ces petits problèmes avec les quelques personnes qui passeront par ici Sourire.

Astuce n°1 :

Problématique : J’ai une page About dans mon application et je veux mettre un lien vers une page web explicative qui sera lancée dans le navigateur. J’utilise donc naturellement un HyperlinkButton  image.
Une fois mon HyperlinkButton placé, la propriété “Content” remplie, il me semble logique de rajouter un lien au niveau de la propriété  “NavigateUri”. Je mets donc mon Url a ce niveau, je compile, je clique et … erreur Tire la langue.

Solution : Il faut remplir correctement la propriété “TargetName” avec la valeur “_blank” et là, miracle : ça marche !!!

Commentaires fermés :, , , plus...

PHP, la fonction exec() et IIS 7.5 : execution denied :-(

par Jean-françois JOLY le déc.08, 2010, dans Developpement Web

Alors aujourd’hui j’ai eu un petit problème avec IIS 7.5 (je suis un newbie) : je voulais exécuter une commande et récupérer la sortie. “Pas de problème” me suis je dis, je vais faire comme sous linux :

<?php
$masortie=array();
$meserreurs=array();
@exec($macommande,$masortie,$meserreurs);
?>

Et là c’est le drame … En effet ça ne marche pas. En fait ce qui ne marche pas ce n’est pas de lancer une commande, mais plutôt d’exécuter un programme arbitraire.
Je m’explique : imaginons que j’ai envie de lancer un programme quelconque dans une directory quelconque et de récupérer la sortie. Par exemple, imaginons que j’ai ajouté les binaires de SVN dans mon path d’environnement me permettant d’appeler une commande svn comme : svn –l 100 –-xml c:\repository\projet
Là j’aimerais beaucoup pouvoir utiliser la sortie XML pour la parser et en retirer des informations intéressantes. Malheureusement pour moi je n’ai pas trouvé comment le faire avec la commande exec() de php. J’ai bien trouvé des techniques en mettant les droits de IS_USER sur le programme cible pour IIS 6.0, sauf qu’en plus d’être complexe, ça ne fonctionne pas du tout sur IIS 7.5.
Résultats des courses j’ai trouvé une alternative beaucoup plus simple que je vous livre toute cuite et qui pourra peut être resservir à quelqu’un Tire la langue.

<?php
class Exec{
	public static function run($command){
		$WScriptShell = new COM("WScript.Shell");
		$objCmd=$WScriptShell->Exec($command);
		$Out = $objCmd->StdOut->ReadAll;
		$Err = $objCmd->StdErr->ReadAll;
		$Out=explode("\r\n",$Out);
		if(empty($Out[count($Out)-1])){
			unset($Out[sizeof($Out)-1]);
		}
		$Err=explode("\r\n",$Err);
		if(empty($Err[count($Err)-1])){
			unset($Err[sizeof($Err)-1]);
		}
		$output=array('output'=>$Out,'error'=>$Err);
		return $output;
	}
}
?>

Cette solution repose tout bêtement sur la capacité de PHP a instancier des objet COM. Nous allons donc pouvoir utiliser l’objet COM qui manipule le shell pour exécuter la commande que l’on veut et récupérer les sorties standards.

Pour l’utiliser c’est relativement simple :

<?php
$retour=Exec::run($macommande);
$masortie=$retour['output'];
$meserreurs=$retour['error'];
?>

Alors si quelqu’un a trouvé comment faire le exec « natif » sous IIS 7/7.5, je suis intéressé car malgré mes recherches sur google je n’ai pas trouvé grand chose de concluant … Donc n’hésitez pas à laisser un petit commentaire pour éclairer le newbie que je suis ^^.

1 Commentaire plus...

Accéder à Sharepoint avec PHP via SOAP en passant par l’authentification Windows (NTLM)

par Jean-françois JOLY le nov.22, 2010, dans Developpement Web

Alors voilà, j’avais un problème tout simple (enfin il semblait simple) à résoudre : accéder aux données de microsoft sharepoint en utilisant PHP.
Facile me direz vous Sourire : il suffit d’y accéder via SOAP avec un webservice et le tour est joué. C’est exactement l’approche que j’ai utilisé, sauf que voilà, à chaque fois : problème d’authentification.

Je n’ai pourtant pas grand chose d’exceptionnel : Un serveur microsoft sharepoint, relié à active directory en authentification windows classique, du php 5.3 en utilisant le client SOAP natif.
Le code devrait être relativement simple pour se connecter : (le wdsl d’un serveur sharepoint est généralement de la forme http://monserveurmoss/monsite/_vti_bin/Lists.asmx?WSDL)
Ce qui nous donnerait donc dans un monde idéal :

$client = new SoapClient("http://monserveurmoss/monsite/_vti_bin/Lists.asmx?WSDL", 
			array(	'soap_version'   => SOAP_1_2,
				'login'          => "some_name",
				'password'       => "some_password"));
$params = array(
	'listName' =>'{0CD81D15-2793-4C63-BEED-1594788A3030}',
	'viewName'=>'{75B8995C-9148-40AA-924E-991684D20015}';
$rawXMLresponse = $client->GetListItems($params)->GetListItemsResult->any;

Donc là normalement, je devrais me connecter tranquillement à ma liste et la vue associée et récupérer des données sous la forme d’un fichier XML. Sauf que pas du tout … Au lieu de ça j’ai une erreur d’authentification, accès refusé.

Après quelques tests, j’en conclus que ce qui ne marche pas c’est l’authentification windows plus connues sous son petit nom de NTLM Tire la langue. Muni de cette information capitale (NTML), je me relance dans la recherche de solutions …

Et après pas mal de recherches, j’ai fini par trouver une solution qui fonctionne : http://rabaix.net/en/articles/2008/03/13/using-soap-php-with-ntlm-authentication

Comme cette page est sous licence creative commons, je me permets d’en copier le code, car sait on jamais, si la source disparait ce serait bien dommage …

Donc, bien que celà semble surprenant, on dirait que PHP n’implémente pas de base la gestion de l’authentification Windows, se coupant donc de pas mal de webservice sous Windows…

La solution proposée est très sympa car à l’aide de quelques surcharges elle permet d’accéder aux fonctionnalités SOAP natives sans utiliser de solutions ultra compliquées :

Une classe qui permet de surcharger SOAPClient en utilisant CURL :

class NTLMSoapClient extends SoapClient {
	function __doRequest($request, $location, $action, $version) {
		$headers = array(
			'Method: POST',
			'Connection: Keep-Alive',
			'User-Agent: PHP-SOAP-CURL',
			'Content-Type: text/xml; charset=utf-8',
			'SOAPAction: &quot;'.$action.'&quot;',
		);
		$this->__last_request_headers = $headers;
		$ch = curl_init($location);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
		curl_setopt($ch, CURLOPT_POST, true );
		curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
		curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
		curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_NTLM);
		curl_setopt($ch, CURLOPT_USERPWD, MossParameter::MOSS_USER.':'.MossParameter::MOSS_PASSWORD);
		$response = curl_exec($ch);
		return $response;
	}
	function __getLastRequestHeaders() {
		return implode("\n", $this->__last_request_headers)."\n";
	}
}

 

Une autre classe qui permet de redéfinir un “stream wrapper” :

class NTLMStream {
	private $path;
	private $mode;
	private $options;
	private $opened_path;
	private $buffer;
	private $pos;
	/**
	 * Open the stream 
	 *
	 * @param unknown_type $path
	 * @param unknown_type $mode
	 * @param unknown_type $options
	 * @param unknown_type $opened_path
	 * @return unknown
	 */
	public function stream_open($path, $mode, $options, $opened_path) {
		$this->path = $path;
		$this->mode = $mode;
		$this->options = $options;
		$this->opened_path = $opened_path;
		$this->createBuffer($path);
		return true;
	}
	/**
	 * Close the stream
	 *
	 */
	public function stream_close() {
		curl_close($this->ch);
	}
	/**
	 * Read the stream
	 *
	 * @param int $count number of bytes to read
	 * @return content from pos to count
	 */
	public function stream_read($count) {
		if(strlen($this->buffer) == 0) {
			return false;
		}
		$read = substr($this->buffer,$this->pos, $count);
		$this->pos += $count;
		return $read;
	}
	/**
	 * write the stream
	 *
	 * @param int $count number of bytes to read
	 * @return content from pos to count
	 */
	public function stream_write($data) {
		if(strlen($this->buffer) == 0) {
			return false;
		}
		return true;
	}
	/**
	 *
	 * @return true if eof else false
	 */
	public function stream_eof() {
		if($this->pos > strlen($this->buffer)) {
			return true;
		}
		return false;
	}
	/**
	 * @return int the position of the current read pointer
	 */
	public function stream_tell() {
		return $this->pos;
	}
	/**
	 * Flush stream data
	 */
	public function stream_flush() {
		$this->buffer = null;
		$this->pos = null;
	}
	/**
	 * Stat the file, return only the size of the buffer
	 *
	 * @return array stat information
	 */
	public function stream_stat() {
		$this->createBuffer($this->path);
		$stat = array(
			'size' => strlen($this->buffer),
		);
		return $stat;
	}
	/**
	 * Stat the url, return only the size of the buffer
	 *
	 * @return array stat information
	 */
	public function url_stat($path, $flags) {
		$this-&gt;createBuffer($path);
		$stat = array(
			'size' => strlen($this->buffer),
		);
 
		return $stat;
	}
	/**
	 * Create the buffer by requesting the url through cURL
	 *
	 * @param unknown_type $path
	 */
	private function createBuffer($path) {
		if($this->buffer) {
			return;
		}
		$this->ch = curl_init($path);
		curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($this->ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
		curl_setopt($this->ch, CURLOPT_HTTPAUTH, CURLAUTH_NTLM);
		curl_setopt($this->ch, CURLOPT_USERPWD, MossParameter::MOSS_USER.':'.MossParameter::MOSS_PASSWORD);
		$this->buffer = curl_exec($this->ch);
		$this->pos = 0;
	}
}

Bon j’ai juste fait une petite variation par rapport à l’original en utilisant une classe de constante MossParameter, histoire de ne pas dupliquer le paramétrage user/password.

Une fois ces deux classes faites, il suffit d’accéder à sharepoint très facilement de cette manière :

stream_wrapper_unregister('http');
stream_wrapper_register('http', 'NTLMStream') or die("Failed to register protocol");
$client = new NTLMSoapClient("http://monserveurmoss/monsite/_vti_bin/Lists.asmx?WSDL", 
			array(	'soap_version'   => SOAP_1_2));
$params = array(
	'listName' =>'{0CD81D15-2793-4C63-BEED-1594788A3030}',
	'viewName'=>'{75B8995C-9148-40AA-924E-991684D20015}';
$rawXMLresponse = $client->GetListItems($params)->GetListItemsResult->any;
stream_wrapper_restore('http');

 

Et voilà le tour est joué, plus de problème d’authentification SOAP entre PHP et Windows.

Autre petite précision pour ceux qui se demandent comment obtenir les uid des list et des view de sharepoint : il y a un outil très pratique (Stramit SharePoint 2007 Caml Viewer ) que vous trouverez ici : http://www.codeplex.com/wikipage?ProjectName=SPCamlViewer

A la prochaine pour de nouvelle aventure entre php et sharepoint Sourire.

3 Commentaires plus...

A la recherche de quelque chose ?

Utiliser ce champs pour faire votre recherche :

Vous n'avez pas trouvé votre bonheur ? N'hésitez pas à contacter l'auteur de ce blog ou alors laissez un commentaire sur un post !

Les liens !

Quelques liens intéressants...

Les archives

Tout, classé par ordre chronologique ...