Display thumbnailPhoto from Active Directory in PHP
This seems to be a JPEG-File, so you should be able to send that data together with the appropriate mime-type to the browser. It should be possible to output that image with something like:
<img src="data:image/jpeg;base64,<?php echo base64_encode($imageString); ?>"/>
But it might also be possible to save files of any image format into that thumbnailPhoto
attribute. Therefore, I would put the content into a temporary file that will then be served directly from the server. You will need to pass the file through finfo
to get the correct mime-type.
So you might do something like this:
$tempFile = tempnam(sys_get_temp_dir(), 'image');
file_put_contents($tempFile, $imageString);
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = explode(';', $finfo->file($tempFile));
echo '<img src="data:' . $mime[0] . ';base64,' . base64_encode($imageString) . '"/>';
PHP - get LDAP thumbnailphoto attribute to display in HTML
I got it working with FILEINFO as described in the link above after testing some more. Thank you.
Pull AD Photo using PHP
Try to run this code example:
<?php
// -------------- CHANGE VARIABLES TO SUIT YOUR ENVIRONMENT --------------
//LDAP server address
$server = "ldap://192.168.1.55";
//domain user to connect to LDAP
$user = "user.name@mydomain.local";
//user password
$psw = "password";
//FQDN path where search will be performed. OU - organizational unit / DC - domain component
$dn = "OU=Accounts,OU=My Company,DC=mydomain,DC=com";
//Search query. CN - common name (CN=* will return all objects)
$search = "CN=*";
// ------------------------------------------------------------------------
echo "<h2>php LDAP query test</h2>";
// connecting to LDAP server
$ds = ldap_connect($server);
$r = ldap_bind($ds, $user , $psw);
// performing search
$sr = ldap_search($ds, $dn, $search);
$data = ldap_get_entries($ds, $sr);
echo "Found " . $data["count"] . " entries";
for ($i = 0; $i < $data["count"]; $i++) {
echo "<h4><strong>Common Name: </strong>" . $data[$i]["cn"][0] . "</h4><br />";
echo "<strong>Distinguished Name: </strong>" . $data[$i]["dn"] . "<br />";
// Check if user photo exists
if (isset($data[$i]["thumbnailphoto"]) && isset($data[$i]["thumbnailphoto"][0])) {
echo "<strong>Photo in Base64: </strong>" . base64_encode($data[$i]["thumbnailphoto"][0]) . "<br />";
}
else {
echo "<strong>Photo not set</strong><br />";
}
// Checking if discription exists
if (isset($data[$i]["description"][0])) {
echo "<strong>Desription: </strong>" . $data[$i]["description"][0] . "<br />";
}
else {
echo "<strong>Description not set</strong><br />";
}
// Checking if email exists
if (isset($data[$i]["mail"][0])){
echo "<strong>Email: </strong>" . $data[$i]["mail"][0] . "<br /><hr />";
}
else {
echo "<strong>Email not set</strong><br /><hr />";
}
}
// close connection
ldap_close($ds);
?>
The problem should be that you check if $data[$i]["thumbnailphoto"][0]
is set while you should check the $data[$i]["thumbnailphoto"]
first.
Then you can read this question Display thumbnailPhoto from Active Directory in PHP and continue coding to display the image.
How to update photo in Active Directory using PHP ldap_modify
Are you sure you want the photo
attribute? By default Outlook, etc. looks at the thumbnailPhoto
attribute, which is just a byte array of the file (not base64 encoded). Something like this:
$changes['thumbnailPhoto'] = $data;
Displaying Windows Active Directory thumbnailPhoto in asp:net Search App
I see why it's taking so long. DirectorySearcher
and DirectoryEntry
can be a little sneaky with how many times it reaches out to AD. You have a lot more network requests going on there than you need.
In your code, you're going out to AD once for the search. Then for each result, you're using GetDirectoryEntry()
. Then DirectoryEntry
is going out to AD again the first time you use Properties
. Worse still, as soon as you use Properties
, it downloads every single attribute that has a value, even though you're only actually using 4 of them. That's a whole lot of useless network traffic.
You can avoid this by using Properties
collection in the search results, which already has all the attributes (by default it gets every attribute that has a value).
But you can do even better: If you set the PropertiesToLoad
property of DirectorySearcher
then it will only return the values you want to use. This way, you have one network request for everything you want, and only what you want.
protected void SearchAD(object sender, EventArgs e)
{
string Name = TextBoxSearchFirstName.Text;
Name = Name.Replace("*", "") + "*";
var dsSearcher = new DirectorySearcher {
Filter = "(&(objectClass=user) (sn=" + Name + "))"
};
dsSearcher.PropertiesToLoad.Add("sn");
dsSearcher.PropertiesToLoad.Add("givenName");
dsSearcher.PropertiesToLoad.Add("samAccountName");
dsSearcher.PropertiesToLoad.Add("thumbnailPhoto");
using (var results = dsSearcher.FindAll()) {
var t = new DataTable("ActiveDir");
t.Columns.Add(new DataColumn("SecondName", typeof(string)));
t.Columns.Add(new DataColumn("FirstName", typeof(string)));
t.Columns.Add(new DataColumn("UserID", typeof(string)));
t.Columns.Add(new DataColumn("data", typeof(byte[])));
foreach (SearchResult searchResult in results) {
var myRow = t.NewRow();
myRow[0] = searchResult.Properties.Contains("sn") ? searchResult.Properties["sn"][0] : null;
myRow[1] = searchResult.Properties.Contains("givenName") ? searchResult.Properties["givenName"][0] : null;
myRow[2] = searchResult.Properties.Contains("samAccountName") ? searchResult.Properties["samAccountName"][0] : null;
myRow[3] = searchResult.Properties.Contains("thumbnailPhoto") ? searchResult.Properties["thumbnailPhoto"][0] : null;
t.Rows.Add(myRow);
}
}
GridView1.DataSource = t;
GridView1.DataBind();
}
A few notes:
The calls to Contains
are needed because if the attribute is empty, then it doesn't exist in the Properties
collection at all.
The search results returns everything as an array, regardless of whether it is or not in AD. Thus, the [0]
is needed for every attribute.
You'll notice I put a using
statement around the search results. This is needed to prevent memory leaks, according to the documentation of FindAll()
.
Related Topics
How to Setup a Cron Job in Magento Module
Remotely Connecting to a MySQL Database
Recursive Function to Get All the Child Categories
Create Table with PHP and Populate from MySQL
Detecting Whether a User Is Behind a Proxy
What Security Problems Could Come from Exposing PHPinfo() to End Users
Replace Deprecated Preg_Replace /E with Preg_Replace_Callback
How to Take an Array, Divide It by Two and Create Two Lists
Laravel 5.3 Withcount() Nested Relation
Php: Get List of All Filenames Contained Within My Images Directory
Move All Files in a Folder to Another
Removing Black Borders 4:3 on Youtube Thumbnails
Url Encode Equivalent in Ruby on Rails