Next Active Directory IntegrationNext Active Directory Integration


Next Active Directory Integration

There haven´t been many changes to ADI in the past. Mainly bug fixes and necessary adjustments were done. But now, it´s time for a change!

Multisite Network Support

For a while now, people have kept asking me when ADI will be supporting Multisite Networks. I have always liked that idea and therefore this feature has been on my To-Do list for a long time. But I did want to do it right, so let´s not take half-measures.

A new Team behind Next ADI

To be able to properly implement Multisite Network Support a lot of effort is required and the existing code has aged making it poorly maintainable. Therefore I have decided, not to develop and maintain ADI on my own anymore. Together with my colleges from the NeosIT GmbH we are bringing ADI with version 2.0 to a whole new level. In the past months ADI was completely rewritten and is currently in a pre-alpha-stage.

If you would like to know more about Next ADI, feel free to read Schakkos blog post where he is talking about a few of the new features.

How will Next ADI continue?

We do not want to keep it a secret. So here is a schedule for the next few weeks:

  • 07.04.2016: Release of an ADI alpha version on Github
  • 11.04.2016: Further information on our website neos-it.de
  • 12.04.2016: Announcement in the WordPress-Forum
  • 13.05.2016: Microsite going online
  • 17.05.2016: ADI 2.0 release on WordPress.org

During this time, development will continue and we will be testing, testing and testing.In der letzten Zeit hat sich bei ADI nicht viel getan. Hauptsächlich Bugfixes und notwendige Anpassungen wurden vorgenommen. Doch jetzt geht’s ab!

Multisite Network Support

Schon seit langem werde ich immer wieder gefragt, wann ADI denn endlich WordPress Multisite Networks unterstützt. Die Idee fand ich schon immer gut und das Feature steht somit schon seit Jahren auf meiner To-Do-Liste. Aber ich wollte es dann auch gleich richtig machen, also klotzen und nicht kleckern.

Hinter Next ADI steht nun ein Team

Um eine vernünftige Multisite-Network-Unterstützung in ADI zu realisieren, ist viel Arbeit erforderlich und der bestehende Code ist auch in die Jahre gekommen und schlecht wartbar. Daher habe ich beschlossen, ADI nicht mehr alleine zu entwickeln und zu betreuen. Gemeinsam mit meinen Kollegen von der NeosIT GmbH heben wir ADI mit der Version 2.0 auf eine neue Ebene. In den vergangenen Monaten wurde ADI komplett neu geschrieben und befindet sich derzeit in einer pre-alpha-Phase.

Wenn ihr mehr über Next ADI erfahren wollt, dann lest bitte Schakkos Blogbeitrag, in dem er schon ein paar Neuerungen ausplaudert.

Wie geht es nun weiter mit Next ADI?

Wir wollen keine Geheimniskrämer sein. Daher hier unser Zeitplan für die nächsten Wochen:

  • 07.04.2016: Veröffentlichung einer alpha-Version von ADI 2.0 auf GitHub
  • 11.04.2016: Weitere Informationen auf unser Website neos-it.de
  • 12.04.2016: Ankündigung im WordPress-Forum
  • 13.05.2016: Microsite geht online
  • 17.05.2016: ADI 2.0 wird auf WordPress.org veröffentlicht

Während dieser Zeit geht die Entwicklung natürlich immer weiter voran und wir werden testen, testen und testen.

WMI mit PHP

Folgender PHP-Code ermittelt die auf einem Windows-System installierte Software. Dabei kann man auch einen Remote-Computer abfragen. Mit der Funktion getWMI() kann man aber auch alle anderen WMI-Abfragen durchführen. Das Funktioniert natürlich nur unter Windows.

<?php
function getWMI($strClass,$strHostname ='', $strUser ='', $strPassword = '') {

    $objLocator = new COM("WbemScripting.SWbemLocator");
    if($strHostname == "") {
        $objService = $objLocator->ConnectServer();
    } else{
        $objService = $objLocator->ConnectServer($strHostname, "rootcimv2", "$strHostname\$strUser", $strPassword);
    }
    
    $objWEBM = $objService->Get($strClass);
    $objProp = $objWEBM->Properties_;
    
    $arrProp = $objProp->Next($objProp->Count);

    $objWEBMCol = $objWEBM->Instances_();
    $arrWEBMCol = $objWEBMCol->Next($objWEBMCol->Count);
    foreach($arrWEBMCol as $objItem)
    {
        reset($arrProp);
        $arrInstance = array();
        foreach($arrProp as $propItem)
        {
            eval("\$value = \$objItem->" .$propItem->Name .";");
            $arrInstance[$propItem->Name] = trim($value);
        }
        $arrData[] = $arrInstance;
    }
    return $arrData;
}


echo "<pre>";

print_r(getWMI("Win32_Product", "192.168.0.56", "administrator", "password"));

echo "</pre>";
?>

AJAX ganz einfach

Dynamische Seite ganz einfach bauen, ohne dass wir einen Reload brauchen? Das geht! Schaut Euch mal das folgende an.

<html>
<head>
  <title>Dynamic Test</title>
  <script language="javascript" type="text/javascript" src="./request.js"></script>
</head>
<body>
  Auswahl:
  <form name="form_category">
    <select name="select_category">
	  <option value="date">Datum</option>
	  <option value="time">Uhrzeit</option>
	  <option value="datetime">Datum + Uhrzeit</option>
    </select>
    <input type="button" name="requestbtn" value="Anzeigen"
              onClick="httpRequest('http://admin/dynamic/request.php', 'id', document.form_category.select_category.value, 'answer')">
  </form>
  Ergebnis:
  <div id="answer" style="background-color: #D0D0D0;">
    <!--This is where we'll be displaying the products once they're loaded-->
	Bitte wählen Sie ein Zeitformat.
  </div>
</body>
</html>

Die Seite besteht nun aus einem Drop-Down Feld aus dem wir die Einträge „Datum“, „Uhrzeit“ und „Datum + Uhrzeit“ wählen können. Wenn wir nun auf den Button „Anzeigen“ klicken, wird uns im unteren Teil der Seite in einem DIV-Block entsprechend unserer Auswahl das Datum, die Uhrzeit oder halt beides angezeigt. Tooooll….. Nix neues? Doch! Denn das Ergebnis wird uns dort angezeigt, ohne dass die Seite neu geladen wird. Ok, das Beispiel mit Datum und Uhrzeit geht natürlich auch direkt mit JS, aber man damit noch ganz andere Sachen, z.B. Datenbankabfragen machen. Wie? Nun ja, in unserem Beispiel wird die Berechnung von Datum und Uhrzeit nicht in JS vorgenommen, sondern erfolgt in einem PHP-Skript, dass irgendwo auf einem Erreichbaren Rechner liegen kann.

Das entscheidende sind die Zeilen 4 und 15. In Zeile 4 binden wir das folgenden JavaScript „request.js“ ein:

// Hier wird die Antwort Ausgegeben (ID des Ausgabeelements, z.B. ein DIV-Block)
var ResponseTargetID = '';


// Funktion zum Erzeugen eines XMLHttpRequest-Objekts
function createRequestObject(){
	var request_o; 
	var browser = navigator.appName;
	 
	if (browser == "Microsoft Internet Explorer") {
		request_o = new ActiveXObject("Microsoft.XMLHTTP");
	} else {
		request_o = new XMLHttpRequest();
	}
	return request_o;
}
  
// Erzeuge XMLHttpRequest-Objekt
var http = createRequestObject();

	
/**
*  Funktion zum Abrufen der Informationen
*
* @param uri - URI der abzurufenden Seite 
* @param parameter - Abfrage Parameter, z.B. 'id'
* @param value - Wert des Parameters
* @param targetID - ID des Elements, dass die Ausgabe anzeigen soll
*/
function httpRequest(uri,parameter,value,targetID){
	
	ResponseTargetID = targetID;
	
	http.open('GET', uri + '?' + parameter + '=' + value);
	
	// Handler definieren
	http.onreadystatechange = handleResponse;

	// Daten senden. In unserem Fall nix!	
	http.send(null);
}


/**
* handleResponse()
*
* verarbeitet die Antworten des Requests
*/
function handleResponse(){
			
		
	/* Das XMLHttpRequest-Objekt hat eine Eigenschaft readyState. Diese kann
	   folgende Werte annehmen:
		0: Uninitialized
		1: Loading
		2: Loaded
		3: Interactive
		4: Finished */
	if(http.readyState == 4) { // Finished?
		if (http.status == 200) { // Status OK?
			var response = http.responseText;
			
			// Ergebnis in das Element einfügen.
			document.getElementById(ResponseTargetID).innerHTML = response;
		}
	}
}

Dies stellt uns die Möglichkeit zur Verfügung per JS Anfragen an einen Server zu stellen. Dazu wird die Funktion XMLHttpRequest() benutzt. Es wird einfach per XMLHttpRequest-Objekt.open() eine Seite abgerufen und das Ergebnis an unsere Seite zurückgeliefert. handleResponse() zeigt das Ergebnis wird dann im Response-Target an. In unserem Fall ist das der DIV-Block mit der ID „answer“.

Die Anfrage selber geschieht in Zeile 15 unserer HTML-Seite. Dort wird die JS-Funktion httpRequest aus unserem JS-Script benutzt, um eine Anfrage an einen anderen Rechner zu stellen. Das Ergebnis wird dann in DIV-Block mit der id=“answer“ angezeigt.

Schauen wir uns mal den Server-Code in request.php an:

<?php

if ($_GET['id'] == 'date') {
	echo date('Y-m-d');
}

if ($_GET['id'] == 'time') {
	echo '<b>'.date('H:i:s').'</b>';
}

if ($_GET['id'] == 'datetime') {
	echo date('Y-m-d / H:i:s');
}

?>

Das ist ja nun ganz simpel. Je nach per GET übergebener ID, wird einfach eine andere Ausgabe erzeugt.

Wie benutze ich das nun?

Was ich brauche ist eine HTML-Seite mit einem Formular. Auf der Seite binde ich per

<script language="javascript" type="text/javascript" src="./request.js">

im Header das JavaScript ein.

Wenn nun ein bestimmtes Ereignis ausgelöst wird, z.B. onClick eines Buttons, müssen wir nun nur noch das Ergebnis aus dem Netz abfragen:

<input type="button" name="requestbtn" value="Anzeigen"
          onClick="httpRequest('http://admin/dynamic/request.php', 'id', document.form_category.select_category.value, 'answer')"> 

Die Syntax von httpRequest

httpRequest(url,parameter,value,targetid)

  • url abzufragende Seite
  • parameter GET-Parameter, in unserem Beispiel ‚id‘
  • value Wert des Parameters, in unserem Beispiel also ‚date‘, ‚time‘ oder ‚datetime‘
  • targetid ID eines HTML-Elements, dass das Ergebnis anzeigen soll, im Beispiel ‚answer‘ (ein DIV-Block)
  • httpRequest fragt nun die Ausgabe der Seite url?parameter=value (z.B. http://admin/dynamic/request.php?id=date) ab und zeigt die Ausgabe der URL im DIV-Block an.

    Was kann man damit machen?

    Es gibt vielfältige Anwendungsmöglichkeiten. Zum Beispiel kann Datenbankeinträge abfragen und darstellen ohne dass ein Page-Reload notwendig ist. Ich denke da fällt jedem etwas Tolles ein. Eine andere Möglichkeit wäre eine Textvervollständigung in einem Text-Input-Feld, die durch das Ereignis keyKeyup ausgelöst wird.

Wake On LAN mit PHP

Mit der folgenden Funktion können WakeOnLAN-fähige Computer im lokalen Netzwerk gestartet werden.

<?php

   Trallala
   
/**
 * WakeUpComputer()
 *
 * Sends a MagicPaket to wake up a computer
 *
 * MagicPaket (116 bytes)
 *
 *     byte   content
 * ---------------------------
 *     1..6   MAC-Address
 *        7   0x00
 *        8   0x74
 *        9   0xFF   
 *       10   0xFF   
 *       11   0xFF   
 *       12   0xFF   
 *       13   0xFF   
 *       14   0xFF   
 *  15..110   6 x MAC-Adress
 *      111   0x40
 *      112   0x00
 *      113   0x90
 *      114   0x90
 *      115   0x40
 *      116   0x00 
 *   
 *   
 * @author Christoph Steindorff, ECW GmbH <cst@ecw.de>
 * @param string $strMacAddress, e.g. '001111d35df8'
 * @param integer $iPort, e.g. 80
 * @return boolean TRUE: packet send, FALSE: error 
 */
function WakeUpComputer($strMacAddress,$iPort=2050) {
	
	$strMAC='';
	$strMagicPaket='';
	
	
	if (strlen($strMacAddress) == 12) {
		for ($x=0; $x<6; $x++) {
			$strMAC .= chr(hexdec(substr($strMacAddress,($x*2),2)));
		}
		
		// Part 1: MAC-Address - Bytes 1..6
		$strMagicPaket =  $strMAC;
		
		// Part 2: Bytes 7..8
		$strMagicPaket .= chr(0x00);  
		$strMagicPaket .= chr(0x74);
		
		// Part 3: 6 x 0xFF - Bytes 9..14		
		for ($x=0; $x<6; $x++) {
			$strMagicPaket .= chr(0xFF);
		}
		
		// Part 4: 16 x MAC-Address - Bytes 15..110
		for ($x=0; $x<16; $x++) {
			$strMagicPaket .= $strMAC;
		}
		
		// Part 5: Bytes 111..116
		$strMagicPaket .= chr(0x40);  // 111
		$strMagicPaket .= chr(0x00);  // 112
		$strMagicPaket .= chr(0x90);  // 113
		$strMagicPaket .= chr(0x90);  // 114
		$strMagicPaket .= chr(0x40);  // 115
		$strMagicPaket .= chr(0x00);  // 116
		

		// Send Paket
		$fudp = fsockopen('udp://255.255.255.255',$iPort,$errno,$errstr);
		
		if ($fudp) {
			fwrite($fudp, $strMagicPaket);
			fclose($fudp);
		} else {
			return FALSE;
		}
	} else {
		return FALSE;
	}
	return TRUE;
}

if WakeUpComputer('001111d35df8') {
	echo 'MagicPaket gesendet.';
} else {
	echo 'MagicPaket nicht gesendet';
} 
?>

Um unter Windows die MAC-Adressen der lokalen Computer herauszufinden, kann man sie einfach von der Konsole aus anpingen und anschließend ein ‚arp -a‘ ausführen.

In folgenden Beispiel, wollen wir die MAC-Adresse vom Rechner mit der lokalen IP-Adresse 192.168.0.47 herausfinden. Zunächst pingen wir den Rechner an: ‚ping 192.168.0.47‘. Anschließend rufen wir ‚arp -a‘ auf. Nun wird uns die MAC-Adresse angezeigt, die zu der IP-Adresse gehört.

Diesen Wert, in unserem Beispiel ’00-04-75-d7-e0-92′, verwenden wir nun mit unserer Funktion WakeUpComputer(). Allerdings müssen alle Bindestriche entfernt werden. Der Aufruf wäre also: WakeUpComuter(‚000475d7e092‘);

Syntax Highlighting mit PHP

Ein kleines Beispiel zu PEAR:Text_Highlighter.

<?php
/**
* Beispiel zur Verwendung von PEAR::Text/Highlighter
*/
?>
<html>
<head>
  <STYLE type="text/css">
	.hl-main {font-family: monospace; font-size:13px;}
	
	.hl-default { color: #000000; }
	.hl-code { color: #7f7f33; }
	.hl-brackets { color: #0000FF; }
	.hl-comment { color: #008000; font-style: italic; }
	.hl-quotes { color: #00007F; }
	.hl-string { color: #008080; }
	.hl-identifier { color: #000000; }
	.hl-reserved { color: #000080; }
	.hl-inlinedoc { color: #0000FF; }
	.hl-var { color: #FF0000; }
	.hl-url { color: #0066FF; }
	.hl-special { color: #0000FF; }
	.hl-number { color: #800080; }
	.hl-inlinetags { color: #000080; font-weight: bold; }
  </style>
</head>
<body>
<?php

// PEAR-Klasse Text/Highlighter einbinden
require_once('Text/Highlighter.php');

// Objekt erzeugen
// Sprache: SQL, Zeilennummer anzeigen
$hl =& Text_Highlighter::factory('SQL',array('numbers'=>true));

// Ausgeben von des Quelltextes von query.sql
echo $hl->highlight(file_get_contents('query.sql'));

?>
</body>
</html>

Ist ja einfach. PEAR:Text/Highlighter unterstützt verschiedene Sprachen, u.a: PHP, SQL, Java, C++, XML, DTD …