Greetings,
I already have a working connection to the AD and can search and retrieve information from it. I've even developed a recursive method by which one can retrieve all groups for a given user. However, I'd like to avoid the recursion if possible. One way to do this is to get the tokenGroups attribute from the AD for the user, which should be a list of the SIDs for the groups that the specified user has membership, whether that membership be direct or indirect.
When I run a search for a user's AD information, though, the tokenGroups attribute isn't even in it. I tried specifically requesting that information (i.e., specifying it using the fourth parameter to ldap_search) but that didn't work, either.
Thanks,
David Kees
Solved my own problem and thought I'd put the answer here so that others might find it. The issue was using the ldap_search() function. The answer was to use the ldap_read() function instead of ldap_search(). The difference is the scope of the request. The search function uses a scope of "sub" (i.e., subtree) while the read function uses "base." The tokenGroups information can only be found when using a scope of "base" so using the correct PHP function was the key.
As I mentioned above, I was working from someone else code in perl to create my solution and the perl script used a function named "search" to do it's LDAP requests which lead me down wrong path.
Thanks to those who took a peek at the question!
--
As per the requests in the comments, here's the basics of the solution in code. I'm extracting from an object that I use so this might not be 100% but it'll be close. Also, variables not declared in this snipped (e.g. $server, $user, $password) are for you to figure out; I won't know your AD credentials anyway!
$ldap = ldap_connect($server);
ldap_bind($ldap, $user, $password);
$tokengroups = ldap_read($ldap, $dn, "CN=*", array("tokengroups")));
$tokengroups = ldap_get_entries($ldap, $tokengroups);
At this point, $tokengroups is our results as an array. it should have count index as well as some other information. To extract the actual groups, you'll need to do something like this:
$groups = array();
if($tokengroups["count"] > 0) {
$groups = $tokengroups[0]["tokengroups"];
unset($groups["count"]);
// if you want the SID's for your groups, you can stop here.
// if you want to decode the SID's then you can do something like this.
// the sid_decode() here: http://www.php.net/manual/en/function.unpack.php#72591
foreach($groups as $i => &$sid) {
$sid = sid_decode($sid);
$sid_dn = ldap_read($ldap, "<SID=$sid>", "CN=*", array("dn"));
if($sid_dn !== false) {
$group = ldap_get_entries($ldap, $sid_dn);
$group = $group["count"] == 1 ? $group[0]["dn"] : NULL;
$groups[$i] = $group;
}
}
}
That's the basics. There's one caveat: you'll probably need to work with the individual or individuals who manage AD accounts at your organization. The first time I tried to get this running (a few years ago, so my memory is somewhat fuzzy) the account that I was given did not have the appropriate authorization to access the token groups information. I'm sure there are other ways to do this, but because I was porting someone else's code for this specific solution, this was how I did it.
Related
Hi have implement pagination in google app engine
with this code
https://github.com/GoogleCloudPlatform/php-docs-samples/blob/master/datastore/api/src/functions/concepts.php
function cursor_paging(DatastoreClient $datastore, $pageSize, $pageCursor = '')
{
$query = $datastore->query()
->kind('Task')
->limit($pageSize)
->start($pageCursor);
$result = $datastore->runQuery($query);
$nextPageCursor = '';
$entities = [];
/* #var Entity $entity */
foreach ($result as $entity) {
$nextPageCursor = $entity->cursor();
$entities[] = $entity;
}
return array(
'nextPageCursor' => $nextPageCursor,
'entities' => $entities
);
}
geting the next Cursor but did not get the previous cursor form this
Indeed, dealing with the previous cursor is something of a problem - even in other languages, it seems to be the bigger issue, when paginating data. There isn't much data or articles in the internet as well, on how to achieve that.
I will try to explain as much as I can, the possibilities, I believe, are available to you.
As per this other question from the Community here, you can create a new cursor with the information previous page, so you can use it for your pagination. This means that you would have three cursors now: $pageCursor, $nextPageCursor and $previousPageCursor. Using like this, you should be able to maintain the actual data, before setting the one for the next page.
Besides that, there is a reverse method in PHP that might help you, in case you want to count how many pages there will be on your application and put it backwards in the previous cursor. This way, you will have the inverted order, to use in your pagination as well - I still believe that giving a try in the first option, would be the best.
I have found some other useful questions from the Community, that might help you achieve your goal - that I believe are worth taking a look at it as well.
How do appengine cursors work?
App Engine datastore paging - previous page
Let me know if the information helped you!
I am trying to get a reply text message from Clickatell using their Rest API, when I call the parseReplyCallback function when their system posts to my page - it seems to be null or I am not sure how to get the variables it is returning. What I would like to do is have all of the variables returned insert into a SQL database so I can use it elsewhere.
I have tried quite a few things, using various styles of getting the variables such as $_POST, $results['text'], $results->text, and so forth each time I can't seem to get any information out of it. I can't just var_dump or anything because I can't see any backend or console so I am pretty much in the blind, hoping someone else is using this system and has it working fine.
require __DIR__.'/clickatell/src/Rest.php';
use clickatell\ClickatellException;
use clickatell\Rest;
$Rest = new Rest("j8VKw3sJTZuVfQGVC7jdhA");
// Incoming traffic callbacks (MO/Two Way callbacks)
$Rest->parseReplyCallback(function ($result) {
//mysqli_query($con,"INSERT INTO `SMSCHAT` (`text`) VALUES ('$result')");
$mesageId = mysqli_real_escape_string($con,$result['messageId']);
$text = mysqli_real_escape_string($con,$result['text']);
$replyMessageId = mysqli_real_escape_string($con,$result['replyMessageId']);
$to = mysqli_real_escape_string($con,$result['toNumber']);
$from = mysqli_real_escape_string($con,$result['fromNumber']);
$charset = mysqli_real_escape_string($con,$result['charset']);
$udh = mysqli_real_escape_string($con,$result['udh']);
$network = mysqli_real_escape_string($con,$result['network']);
$keyword = mysqli_real_escape_string($con,$result['keyword']);
$timestamp = mysqli_real_escape_string($con,$result['timestamp']);
//do mysqli_query
});
I'd like for it to break the result into individual variables (because I plan on doing other things such as an auto-reply, etc) and upload it to the SQL database scrubbed.
Either doesn't create the table entry or gives me a blank one altogether in that first test where I put the result in the text field.
From a Clickatell point of view, although we understand what you're asking - it's unfortunately outside the scope of support that we offer on our products.
If you would like more information on our REST API functionality, please feel free to find it here: https://www.clickatell.com/developers/api-documentation/rest-api-reply-callback/
If you don't succeed in setting up the callbacks, please feel free to log a support ticket here: https://www.clickatell.com/contact/contact-support/ and one of our team members will reach out and try to assist where possible.
I have small problem.
I've coded a full website in php using CodeIgniter framework. One of my modules is search module, it contains text input with keyword and three select lists with filtering criterias.
That's ok, when I'm searching something - result's listing pagination is done via URL like that:
mysite.com/$keyword/$criteria1/$criteria2/$criteria3/$offset
works like a charm.
But when I'm entering into one of my images (it's image gallery) I want to have an option to go into NEXT and PREVIOUS image from my search results - the ones which I entered this image from.
I'm solving this case now in this way - I have session table called 'search_conditions' and I'm storing values of keyword and my three criterias there, but that's quite not comfortable, because why if someone opens second window and search something else there?
Then all of his searches in another windows or tabs are getting the same criteria - because with every new search, user overwrite the session value.
My next and previous functions:
public function next($count)
{
$search = $this->session->userdata('search_conditions'); //getting session table and overwriting it
$catid = isset($search['catid'])?$search['catid']:'0';
$brandid = isset($search['brandid'])?$search['brandid']:'0';
$prodid = isset($search['prodid'])?$search['prodid']:'0';
$keyword = isset($search['keyword'])?$search['keyword']:'';
$res = $this->search_model->main_search($keyword, $catid, $brandid, $prodid, $count, 1);
}
public function previous($count)
{
$search = $this->session->userdata('search_conditions');
$catid = isset($search['catid'])?$search['catid']:'0';
$brandid = isset($search['brandid'])?$search['brandid']:'0';
$prodid = isset($search['prodid'])?$search['prodid']:'0';
$keyword = isset($search['keyword'])?$search['keyword']:'';
$res = $this->search_model->main_search($keyword, $catid, $brandid, $prodid, $count-2, 1);
}
Can you recommend me some other, more comfortable solution, because this seems not to be good...
: )
Thank you!
Add an index to the $search_conditions variable:
$search_conditions[1]['catid']
$search_conditions[1]['brandid']
...
then refer to it with a controller's or config variable. This way you can allow one session to store multiple search conditions.
But I would recommend you drop storing the search condition in session. Instead, just pass it with the URI. Session data, in the case you describe, work as an intermediary; you don't need it. Use the Pagination Class and pass the search page number, not the direction (next or previous) to the URI.
Do not worry that the URI may look ugly - it only depends on what user searches for, and it's still friendly to share. Your only concern is if the GET string does not extend the limited length.
Pull the segments from the URI in your next() and previous() functions. Use the codeigniter URL helper. That should allow you to pass the different search criterion as variables to the next page, this would also remove your need to use the session.
I am currently working on a PHP script that will be polling Active Directory to pick out modified objects (people/users), via LDAP.
I'm able to filter on uSNChanged when I have the value, like so:
$previousUsn = '1234';
$ldapCon = ldap_connect('ldap-host');
$ldapBind = ldap_bind($ldapCon, 'ldap-user', 'ldap-password');
$sr = ldap_search($ldapCon, "ou=Users,dc=foo", "uSNChanged >= $previousUsn");
According to this, I should be able to retrieve a highestCommittedUSN attribute that could be used for the initial run of the script. I've been looking around to find out how this can be done using PHP & LDAP, but to no avail.
Alternatively, feel free to suggest completely different methods of retrieving changes in AD.
ldap_read(...) seems to do the trick:
function getHighestCommittedUsn() {
ldap_bind(...);
$sr = ldap_read($ldapCon, null, "(highestcommittedusn=*)", array("highestcommittedusn"));
$rs = ldap_get_entries($ldapCon, $sr);
return $rs[0]["highestcommittedusn"][0];
}
Try setting the search base (second argument) in your ldap_search call to "". That attribute is on a pseudo object called RootDSE.
Perhaps if the biffins function hasn't been initialised correctly? Hmmm try changing the variable type of c_willygham
I'm using Wordpress and developed some site-specific plugins for it, additionally my theme is customized to fit the requirements of the plugins in the backend.
The last days I fiddled with transients in Wordpress. In some tutorials they're saying "If your're using custom queries and their results are cachable: Use a transient". Sounds good but I'm wondering when to use transients to get a real advantage.
I mean, even when using transients there have to be at least two queries in the background, haven't it? The first one for checking the validity, second one for the transient itself.
So is it really useful to use a transient i.e. for a custom WP_Query?
Thanks a lot for your help and thoughts.
Seems fairly straightforward. It's a literal class helper that allows you to store objects in a 'memcache' type fashion. You first set the transient
function do_something_here($callback_param = 'value'){
$key = 'do_something_' . $callback_param;//set the name of our transient equal to the value of the callback param being passed in the function.
$my_query = get_transient($myKey); //if we've stored this request before, then use it.
if($my_query !=== false){
//we found a previous existing version of this query. let's use it.
return $my_query;
}else{
//it doesn't exist, we need to build the transient.
//do our database querying here, global $wpdb; etc
//We are going to pretend our returned variable is 'george'
$value = george;
$length = 60*60*24; //how long do we want the transient to exist? 1 day here.
set_transient($key, $value, $length);
return $value;
}
}
Now that we have created our trigger and bound it to the name of '$key', we can access it anytime by using the exact value that key implies (which we declared earlier).
echo 'I wanted to do something, so : ' . do_something('value') . ' is what i did! ';
By utilizing this format you can hold queries in a 'cache' like world and use them to generate your responses. This is similar in a way to using 'trigger' events in MySql. Infact, this is a PORTION of a TECHNIQUE commonly referred to as long polling.