VBscript results to PHP variable - php

I’m trying to send the results of Vb script to a PHP variable,
The code get the CN name in AD.
My Vb code is below:
Set objADSysInfo = CreateObject("ADSystemInfo")
strUser = objADSysInfo.UserName
Set objUser = GetObject("LDAP://" & strUser)
objUser.CN
How can I send the code to my PHP file as a variable once the webpage is loaded?

You can use an ADO Recordset as a wrapper
Set objADSysInfo = CreateObject("ADSystemInfo")
strUser = objADSysInfo.UserName
Set objUser = GetObject("LDAP://" & strUser)
objUser.CN
ret = send2PHP("yourpage.php?data=", strUser)
function send2PHP(phpURL, data)
on error resume next ' if your php page returns a valid recorset you can omit 'on error
set rsPHP = wscript.createobject("adodb.recordset")
'here you must serialize "data" to be a valid uri value (not done here) '
rsPHP.open phpURL & data ,,,, 256 ' this statment (and the following ones) '
if not rsPHP.eof then send2PHP = rsPHP(0) ' fails if you do not return a valid recordset '
rsPHP.close ' form php script, but at least you '
set rsPHP = nothing ' have the "data" within the php anyway '
end function

Related

Read Windows Installer (MSI file) attributes from PHP

I have a Windows MSI file, that I need to programmatically read the version number from. The only place I can see this version is within the Subject of the file details:
If I somehow can read the entire content of Subject this would be fine but is there any way to get this from PHP? The PHP is running in an IIS web server, if this helps ;-)
stat is of no help for this.
I considered doing a checksum of the file, and can do that, but I really need the real version.
For now I am unable to find a native PHP solution for this, so I have temporarily solved this by calling a Powershell script as it seems easier to do in there.
I am now having this PHP code:
$version = exec("powershell.exe -file GetMsiVersion.ps1 MyFile.msi);
With my above picture then $version will contain 1.5.9, so I will not even require to interpret the data from Subject.
The GetMsiVersion.ps1 Powershell script has this code:
function Get-Property ($Object, $PropertyName, [object[]]$ArgumentList) {
return $Object.GetType().InvokeMember($PropertyName, 'Public, Instance, GetProperty', $null, $Object, $ArgumentList)
}
function Invoke-Method ($Object, $MethodName, $ArgumentList) {
return $Object.GetType().InvokeMember($MethodName, 'Public, Instance, InvokeMethod', $null, $Object, $ArgumentList)
}
$Path = $args[0]
$msiOpenDatabaseModeReadOnly = 0
$Installer = New-Object -ComObject WindowsInstaller.Installer
$Database = Invoke-Method $Installer OpenDatabase #($Path, $msiOpenDatabaseModeReadOnly)
$View = Invoke-Method $Database OpenView #("SELECT Value FROM Property WHERE Property='ProductVersion'")
Invoke-Method $View Execute
$Record = Invoke-Method $View Fetch
if ($Record) {
Write-Output (Get-Property $Record StringData 1)
}
Invoke-Method $View Close #()
I will accept this as the best solution here-and-now but, I hope this can be archieved natively from PHP as I see this as a better and more clean solution - and by then I will accept that as the best answer (or at least unaccept my own temporary solution).
Doing an exec is a little evil ;-)
Two things first:
I have never accessed COM from PHP, but below are some VBScript samples of getting information from MSI files by using MSI API - COM automation. There are also Win32 functions.
That field you refer to is not a version field, but a text field from the MSI's "Summary Stream" - a special part of the MSI file with "meta information" of various kinds. Summary Information Stream (the full name).
Here is how you can get the REAL version of an MSI file. This is stored in the property "ProductVersion" in the MSI file. There are at least two different ways to retrieve it - by opening the MSI file as a session or just access the property table via SQL query:
Access version via Session object:
Const msiUILevelNone = 2
Dim installer : Set installer = CreateObject("WindowsInstaller.Installer")
installer.UILevel = msiUILevelNone
Set s = installer.OpenPackage("C:\MySetup.msi",1)
MsgBox CStr(s.ProductProperty("ProductVersion"))
Accessing version via SQL agains MSI database (property table):
Dim installer : Set installer = CreateObject("WindowsInstaller.Installer")
' Open MSI database in read-only mode (0)
Set db = installer.OpenDatabase("C:\MySetup.msi", 0)
Set view = db.OpenView("SELECT `Value` FROM `Property` WHERE `Property`='ProductVersion'")
view.Execute
Set record = view.Fetch
MsgBox CStr(record.StringData(1))
Then there is the issue of accessing the SummaryStream - which is what you are really asking by the looks of it - here is a simple smoke test with some hints as to what properties you can retrieve - be careful with the summary stream - corruption is possible in various ways (I don't recall the details, but it should be safe to access read-only):
Dim installer : Set installer = CreateObject("WindowsInstaller.Installer")
' Open MSI database in read-only mode (0)
Set db = installer.OpenDatabase("C:\MySetup.msi", 0)
MsgBox CStr(db.SummaryInformation.Property(3))
' 1 = "Codepage"
' 2 = "Title"
' 3 = "Subject"
' 4 = "Author"
' 5 = "Keywords"
' 6 = "Comments"
' 7 = "Template"
' 8 = "LastAuthor"
' 9 = "Revision"
' 11 = "Printed"
' 12 = "Created"
' 13 = "Saved"
' 14 = "Pages"
' 15 = "Words"
' 16 = "Characters"
' 18 = "Application"
' 19 = "Security"
Links:
Modify an MSI using MSI SQL VBScript WiRunSQL.vbs
List tables in MSI file using VBScript

How to create solr document with String type using solarium query

I' creating solr document via solarium plugin in php.
But the all document is stored text_general data type except id field. text_general is the default datatype in solr system.
My doubt is why id field is only to stored string type as default.
And If any possible to add document with string type using solarium plugin.
My code part is here,
public function updateQuery() {
$update = $this->client2->createUpdate();
// create a new document for the data
$doc1 = $update->createDocument();
// $doc1->id = 123;
$doc1->name = 'value123';
$doc1->price = 364;
// and a second one
$doc2 = $update->createDocument();
// $doc2->id = 124;
$doc2->name = 'value124';
$doc2->price = 340;
// add the documents and a commit command to the update query
$update->addDocuments(array($doc1, $doc2));
$update->addCommit();
// this executes the query and returns the result
$result = $this->client2->update($update);
echo '<b>Update query executed</b><br/>';
echo 'Query status: ' . $result->getStatus(). '<br/>';
echo 'Query time: ' . $result->getQueryTime();
}
The result document for the above code is here,
{
"responseHeader":{
"status":0,
"QTime":2,
"params":{
"q":"*:*",
"_":"1562736411330"}},
"response":{"numFound":2,"start":0,"docs":[
{
"name":["value123"],
"price":[364],
"id":"873dfec0-4f9b-4d16-9579-a4d5be8fee85",
"_version_":1638647891775979520},
{
"name":["value124"],
"price":[340],
"id":"7228e92d-5ee6-4a09-bf12-78e24bdfa52a",
"_version_":1638647892102086656}]
}}
This depends on the field type defined in the schema for your Solr installation. It does not have anything to do with how you're sending data through Solarium.
In the schemaless mode, the id field is always set as a string, since a unique field can't be tokenized (well, it can, but it'll give weird, non-obvious errors).
In your case i'd suggest defining the price field as an integer/long field (if it's integers all the way) and the name field as a string field. Be aware that string fields only generate hits on exact matches, so in your case you'd have to search for value124 with exact casing to get a hit.
You can also adjust the multiValued property of the field when you define the fields explicitly. That way you get only the string back in the JSON structure instead of an array containing the string.

Pass By Reference to COM Object in PHP

So I'm hoping someone can help and I'm sure this is probably something simple I'm missing. I'm using PHP to access a .net API for a third party software.
Based on the very minimalist documentation on the API I have a working vbsript that connects to the object, performs a login and then does a query which results in the output of the query being dumped to a message box.
Here's the vbscript sample:
'Test device status
Set xxx = CreateObject("The.API.Object.Goes.Here")
'Login
Result = Xxx.LoginToHost("xxx.xxx.xxx.xxx","8989","Administrator","")
if (Result = true) then
MsgBox("OK")
else
MsgBox("Error - " & Xxx.LastError)
WScript.Quit
end if
'Get Status
Result = Xxx.GetDeviceStatus("", out)
if (Result = true) then
MsgBox(out)
else
MsgBox("Error - " & Xxx.LastError)
end if
'Logout
Result = Xxx.Logout()
if (Result = true) then
MsgBox("Logout OK")
else
MsgBox("Error - " & Xxx.LastError)
end if
The Xxx.GetDeviceStatus has two perimeters, the first being a device target or if left blank returns all devices, the second is the string variable to dump the result in.
When the script executes, the second message box contains a list of all devices as I would expect.
In PHP I have:
$obj = new DOTNET("XxxScripting, Version=1.0.XXXX.XXXXXX, Culture=neutral, PublicKeyToken=XXXXXXXXXXXXXXXX","Here.Goes.The.Api");
$obj->LoginToHost('xxx.xxx.xxx.xxx','8989','Administrator','');
$result = $obj->GetDeviceStatus('','out');
echo $result."<br />";
echoing result gives 1 because the value of result is a boolean value and GetDeviceStatus is successful. What I can't figure out is how to get the value of 'out' which is the actual query result.
Any help would be greatly appreciated.
The second parameter of GetDeviceStatus() method call according to the VBScript should pass a variable that will be populated with the output.
However in the PHP example you are just passing the string 'out' which isn't equivalent to what is being done in the VBScript.
Instead try passing a PHP variable to the method and then echoing that variable to screen, like this;
$result = $obj->GetDeviceStatus('', $out);
if ($result)
echo $out."<br />";
After a bit of digging it appears according to the PHP Reference that you need to pass By Reference variables to COM using the VARIANT data type.
Quote from ferozzahid [at] usa [dot] com on PHP - COM Functions
"To pass a parameter by reference to a COM function, you need to pass VARIANT to it. Common data types like integers and strings will not work for it."
With this in mind maybe this will work;
$out = new VARIANT;
$result = $obj->GetDeviceStatus('', $out);
if ($result)
echo $out."<br />";

How to handle long SMS text from Nexmo API properly?

be kind, this is my first question and my english is not very good.
I have no problem to deal with standard messages from Nexmo API and I want to receive long SMS just like I do with standard ones (i.e. in one block).
Exemple of data received from Nexmo for a standard SMS:
$_GET['msisdn'] ==> "33612345678" // "from"
$_GET['to'] ==> "33687654321"
$_GET['messageId'] ==> "02000000478EBE09"
$_GET['text'] ==> "Hello world!"
$_GET['type'] ==> "unicode"
$_GET['keyword'] ==> "HELLO"
$_GET['message-timestamp'] ==> "2014-11-25 14:06:58"
Long one: (Nexmo sent it piece by piece)
$_GET['msisdn'] ==> "33612345678" // "from"
$_GET['to'] ==> "33687654321"
$_GET['messageId'] ==> "02000000478EBE09"
$_GET['text'] ==> "the first part of a too long text..."
$_GET['type'] ==> "unicode"
$_GET['keyword'] ==> "THE"
$_GET['message-timestamp'] ==> "2014-11-25 12:06:58"
$_GET['concat'] ==> "true"
$_GET['concat-ref'] ==> "108" // unique identifier for long SMS text
$_GET['concat-total'] ==> "4" // or more, or less...
$_GET['concat-part'] ==> "1" // index of the part, start at 1
See more on the Nexmo documetation: Here
So, I started from a library found on github (Nexmo-PHP-lib) and did this:
(pretty ugly but it's for test purpose)
public function inboundText( $data=null ){
if(!$data) $data = $_GET;
if(!isset($data['text'], $data['msisdn'], $data['to']))
return false;
if(isset($data['concat']) && $data['concat'])
{
session_start();
if ($data['concat-part'] > 1) // first part ?
{
if ($data['concat-total'] == $data['concat-part']) // last part ?
{
// last part ! stock the data in the text and unset now useless $_SESSION entry!
$data['text'] = $_SESSION[(string)$data['concat-ref']] . $data['text'];
unset($_SESSION[(string)$data['concat-ref']]);
}
else // not the first or the last, so concat !
{
// concat the new part in the entry named after the concat-ref
$_SESSION[(string)$data['concat-ref']] .= $data['text'];
return false;
}
}
else // first part ! so creat a $_SESSION entry for that! (named after concat-ref)
{
$_SESSION[(string)$data['concat-ref']] = $data['text'];
return false;
}
}
// Get the relevant data
$this->to = $data['to'];
$this->from = $data['msisdn'];
$this->text = $data['text'];
$this->network = (isset($data['network-code'])) ? $data['network-code'] : '';
$this->message_id = $data['messageId'];
// Flag that we have an inbound message
$this->inbound_message = true;
return true;
}
It works perfectly with local test but not when it's hosted on my heroku server, the $_SESSION array seems to be reset at each part of the sms...
So, have you any idea of how to handle it properly? (and without an ugly temporary SQL table).
How can I retreive the previous part of the message until I receive it completely?
Using a session to store the temporary sms parts would only work if there is an exchange of keys between the client and server with each HTTP request which identifies the session.
In PHP, when you create a session and store a value inside $_SESSION a file is created on the server to store this data (unless you are using a DB session handler, in which case the session data is stored in a database). This data is referenced with an identifier (e.g., PHPSESSID=66dda288eb1947843c2341b4e470fa28) which is normally provided to the client as a cookie. When the client returns at the next HTTP request, the identifier is returned to the server as a cookie value, and the server uses this to reference the same session data.
While your server may be providing the cookie to the Nexmo client when it connects to your endpoint URL, Nexmo is probably not storing the cookie and returning it with its next request. (This is an assumption on my part, but I think it is a safe one—although I can't explain why it works on your local machine but not Heroku. Anyways, it is easy to test—just check if the Nexmo client provides any $_COOKIE value during subsequent requests).
Bottom line: if the Nexmo client doesn't use cookies to save state between requests, you cannot use sessions to save temporary sms parts.
A better option, in any case (because the temporary saved message parts would persist in case of a server reboot), would be to save each temporary part to a small database table. (Don't worry, it's a beautiful temporary SQL table. ;) Here's an example using MySQL:
CREATE TABLE `response_concat_tbl` (
`concat-ref` SMALLINT NOT NULL DEFAULT '0',
`concat-total` TINYINT UNSIGNED NOT NULL DEFAULT '0',
`concat-part` TINYINT UNSIGNED NOT NULL DEFAULT '0',
`text` VARCHAR(160) NOT NULL DEFAULT '',
`added_datetime` DATETIME DEFAULT NULL,
UNIQUE KEY `concat-ref` (`concat-ref`, `concat-part`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='A place to temporarily store multipart SMS messages before they are combined and saved as a whole response.';
Here I've defined a UNIQUE KEY so we can avoid duplicate message parts with a REPLACE INTO clause (in case the Nexmo client tries to submit the same part twice). The added_datetime can be used to clean up orphaned messages in the future (in case the final part of a message is never received).
Now let's insert some sample data:
REPLACE INTO response_concat_tbl (`concat-ref`,`concat-total`,`concat-part`,text,added_datetime) VALUES ('101','4','1','This is',NOW());
REPLACE INTO response_concat_tbl (`concat-ref`,`concat-total`,`concat-part`,text,added_datetime) VALUES ('101','4','2','a multipart',NOW());
REPLACE INTO response_concat_tbl (`concat-ref`,`concat-total`,`concat-part`,text,added_datetime) VALUES ('101','4','4','for you!',NOW());
REPLACE INTO response_concat_tbl (`concat-ref`,`concat-total`,`concat-part`,text,added_datetime) VALUES ('101','4','3','sms message',NOW());
Now we can use MySQL's GROUP_CONCAT function to grab all the parts in one query.
SET SESSION group_concat_max_len = 1000000;
SELECT GROUP_CONCAT(text ORDER BY `concat-part` ASC SEPARATOR ' ') AS text
FROM response_concat_tbl
WHERE `concat-ref` = '101'
GROUP BY `concat-ref`;
We set the group_concat_max_len setting so the total string length may be longer than the default 1024 characters (although that's already lots of message). Here's the result:
+-------------------------------------------------------------+
| GROUP_CONCAT(text ORDER BY `concat-part` ASC SEPARATOR ' ') |
+-------------------------------------------------------------+
| This is a multipart sms message for you! |
+-------------------------------------------------------------+
If you're not using MySQL, you might need to do a bit more work (some duplication check and then a loop) without REPLACE INTO and GROUP_CONCAT.
Here is a full working example using this technique:
class SMS
{
static public function processMultipart($sms)
{
$db =& DB::getInstance();
if (isset($sms['concat']) && $sms['concat']) {
// This sms is part of a multipart message, save it temporarily to the db.
$sms = array_map('trim', $sms);
$db->query("
REPLACE INTO response_concat_tbl (
`concat-ref`,
`concat-total`,
`concat-part`,
`text`,
`added_datetime`
) VALUES (
'" . $db->escapeString($sms['concat-ref']) . "',
'" . $db->escapeString($sms['concat-total']) . "',
'" . $db->escapeString($sms['concat-part']) . "',
'" . $db->escapeString($sms['text']) . "',
NOW()
)
");
if ($sms['concat-total'] > $sms['concat-part']) {
// Not all the parts have been received; return false to signal the fact we don't have a complete message yet.
return false;
}
// Otherwise, it means the last part has just been received. Concatonate all the parts and return it.
// Increase the max length returned by MySQL's GROUP_CONCAT function.
$db->query("SET SESSION group_concat_max_len = 32000");
// Group the sms responses by concat-ref and return them as a concatonated string.
$qid = $db->query("
SELECT GROUP_CONCAT(text ORDER BY `concat-part` ASC SEPARATOR ' ')
FROM response_concat_tbl
WHERE `concat-ref` = '" . $db->escapeString($sms['concat-ref']) . "'
GROUP BY `concat-ref`
");
list($sms['text']) = $db->fetch_row($qid);
// Delete the temporary records.
$db->query("
DELETE FROM response_concat_tbl
WHERE `concat-ref` = '" . $db->escapeString($sms['concat-ref']) . "'
");
}
// If this is not a multipart message, the original sms data is returned. If it is a multipart message, we're returning the fully-concatonated message.
return $sms;
}
}
And here's how to use this function:
// False is returned here if we need to wait for additional parts to arrive. Otherwise, $sms is populated with the final, usable data.
if (false === $sms = SMS::processMultipart($_GET)) {
header($_SERVER['SERVER_PROTOCOL'] . ' 200 OK', true, 200);
die('Waiting for additional message parts');
}
// Do something with $sms['text'], e.g.,
SMSResponse::save($sms['text']);

POSTing binary data over http with Python -> PHP

I'm want to post a binary data string from a Python script to a webserver where a PHP script should pick it up and store it. I receive the whatever I echo in my POST part of the php script on the Python side so I assume, the actual POST works. However, I'm posting 23 Bytes and strlen($_POST['data']) stays 0.
My PHP script to pickj up the data looks like this:
if (isset($_REQUEST["f"]) && $_REQUEST["f"]=="post_status") {
$fname = "status/".time().".bin";
if (file_exists($fname)) {
$fname = $fname."_".rand();
if (file_exists($fname)) {
$fname = $fname."_".rand();
}
}
echo strlen($_POST['data'])." SUCCESS!";
}
and the Python POST script looks like this:
data = statusstr
host = HOST
func = "post_status"
url = "http://{0}{1}?f={2}".format(host,URI,func)
print url
r = urllib2.Request(url, data,{'Content-Type': 'application/octet-stream'})
r.get_method = lambda: 'PUT'
response = urllib2.urlopen(r)
print "RESPONSE " + response.read()
Why does my data not seem to get through, I'm wondering?
Thank you,
PHP will only populate posted values into the $_POST/REQUEST arrays for data that is sent as one of the form data content types. In your case, you need to read in the binary data directly from standard in like this:
$postdata = file_get_contents("php://input");

Categories