I'm using the SSRS SDK For PHP which has not been updated since years surprisingly (08.04.2010) .
It works fine under PHP 5.4 (5.4.44) but not under 5.5+ (5.5.37, 5.6.28, 7.x)
The error is :
array ( )Failed to connect to Reporting Service Make sure that the url
(https://myHost:60004/ReportServer/) and credentials are
correct!
The exception is thrown in line 207 because the var $content is equals to FALSE (so can't load the content).
It's perfectly fine with PHP 5.4.44.
I can't find the "SSRS SDK For PHP" documentation regarding the PHP version supported...
I'm not using any framework such as Symfony2, CakePHP, Zend Framework,... except Bootstrap.
Does anyone know or have figured out this issue?
EDIT
As asked in a comment, here is my code :
function buildSSRSReport($companyId)
{
require_once '../tools/SSRSReport/SSRSReport.php';
try {
// Create a connection to the SSRS Server
$rs = new SSRSReport(new Credentials(SSRS_USER_ID, SSRS_PASSWORD), SSRS_REPORT_SERVER_URL);
$sqlConnection = self::getSqlConnection();
// Load the report and specify the params required for its execution
$executionInfo = $rs->LoadReport2(self::getSSRSEnvironment(), NULL);
$parameters = array();
$parameters[0] = new ParameterValue();
$parameters[0]->Name = "CompanyId";
$parameters[0]->Value = $companyId;
$rs->SetExecutionParameters2($parameters);
// Require the Report to be rendered in HTML format
$renderAsHTML = new RenderAsPDF();
// Set the links in the reports to point to the php app
//$renderAsHTML->ReplacementRoot = getPageURL();
// Set the root path on the server for any image included in the report
//$renderAsHTML->StreamRoot = './images/';
// Execute the Report
$result_html = $rs->Render2($renderAsHTML,
PageCountModeEnum::$Actual,
$Extension,
$MimeType,
$Encoding,
$Warnings,
$StreamIds);
$pdfFileName = self::getCompanyAlias($sqlConnection, $companyId) . ".pdf";
header('Content-Type: application/x-download');
header('Content-Disposition: attachment; filename="' . $pdfFileName . '"');
header('Cache-Control: private, max-age=0, must-revalidate');
header('Pragma: public');
return $result_html;
} catch (SSRSReportException $serviceException) {
echo $serviceException->GetErrorMessage();
}
}
function getSSRSEnvironment()
{
return "/DEV/CompanyESGReportingServices-DEV/Main";
}
private function getSqlConnection()
{
require_once("../inc/eth_connexion.php");
/* These 4 variables are contained within the eth_connexion.php file */
$serverName = SQL_SERVERNAME;
$userName = SQL_USERNAME;
$dbName = SQL_DATABASENAME;
$password = SQL_PASSWORD;
// SQLSRV : Connection array used when calling SQL via sqlsrv_query
$connectionInfo = array("Database"=> SQL_DATABASENAME,
"UID"=> SQL_USERNAME,
"PWD"=> SQL_PASSWORD,
"ReturnDatesAsStrings" => true);
$sqlConnection = sqlsrv_connect($serverName, $connectionInfo);
if (!$sqlConnection) {
die('Can't log to the database');
}
return $sqlConnection;
}
And here is the source code of the SSRSReport constructor (original from the SSRS SDK For PHP) :
public function SSRSReport($credentials, $url, $proxy = null)
{
$this->_BaseUrl = ($url[strlen($url) - 1] == '/')? $url : $url . '/';
$executionServiceUrl = $this->_BaseUrl . self::ExecutionService;
$managementServiceUrl = $this->_BaseUrl . self::ManagementService;
$options = $credentials->getCredentails();
$stream_conext_params = array( 'http' =>
array('header' =>
array($credentials->getBase64Auth())));
if(isset($proxy))
{
$options = array_merge($options, $proxy->getProxy());
$stream_conext_params['http']['proxy'] = 'tcp://' .
$proxy->getHost() .
':' .
$proxy->getPort();
if($proxy->getLogin() != null)
{
$stream_conext_params['http']['header'][1] = $proxy->getBase64Auth();
}
}
/**
* If the SoapClient call fails, we cannot catch exception or supress warning
* since it throws php fatal exception.
* http://bugs.php.net/bug.php?id=34657
* So try to load the wsdl by
* calling file_get_contents (with warning supressed i.e. using # symbol
* infront of the function call)
* http://stackoverflow.com/questions/272361/how-can-i-handle-the-warning-of-filegetcontents-function-in-php
*/
$context = stream_context_create($stream_conext_params);
$content = #file_get_contents($executionServiceUrl, false, $context);
if ($content === FALSE) // I'M GOING HERE WITH PHP 5.5+
{
throw new SSRSReportException("",
"Failed to connect to Reporting Service <br/> Make sure " .
"that the url ($this->_BaseUrl) and credentials are correct!");
}
$this->_soapHandle_Exe = new SoapClient ($executionServiceUrl, $options);
$this->_soapHandle_Mgt = new SoapClient ($managementServiceUrl, $options);
$this->ClearRequest();
}
The exact error message is :
https://myPublicHostProvider:60004/ReportServer/ReportExecution2005.asmx?wsdl
Authorization: Basic = array(1) {
["http"]=> array(1) { ["header"]=> array(1) { [0]=> string(57)
"Authorization: Basic =" } } }
Failed to connect to Reporting Service
Make sure that the url (https://myPublicHostProvider:60004/ReportServer/) and credentials are correct!
SSRS SDK for PHP Configuration Pointers
Make sure your Report Server instance is accessible. Test it by going to the Web Portal or the Service URL.
Provide your credentials. If you are authenticated, then the credentials that you used are valid.
After that, go to the directory \Program Files\Microsoft SQL Server\<INSTANCE_NAME>\Reporting Services\ReportServer and look for the file named rsreportserver.config
Find this snippet
<Authentication>
<AuthenticationTypes>
<RSWindowsNTLM/>
</AuthenticationTypes>
<Authentication>
Add <RSWindowsBasic/> below the <RSWindowsNTLM/> entry.
For your reference, this was the snippet I used to test my instance during configuration.
require_once( 'SSRSReport\bin\SSRSReport.php' );
define( 'UID', 'DOMAIN\Username' );
define( 'PASWD', 'Password' );
define( 'SERVICE_URL', 'http://127.0.0.1/SERVICE_URL/' );
try {
$ssrs_report = new SSRSReport( new Credentials( UID, PASWD ), SERVICE_URL );
$ssrs_report->LoadReport2( '/test', NULL );
$renderAsHTML = new RenderAsHTML();
$result_html = $ssrs_report->Render2(
$renderAsHTML,
PageCountModeEnum::$Estimate,
$Extension,
$MimeType,
$Encoding,
$Warnings,
$StreamIds
);
echo $result_html;
} catch ( SSRSReportException $serviceException ) {
echo $serviceException->GetErrorMessage();
}
It can successfully load the RDL that is located on the load path.
Thanks for your help MiSAKACHi. It pointed me on the right direction. Actually, I'm using a remote dedicated server on a hosting provider on which I don't have access. But the <RSWindowsBasic/> is there as it can load the report with PHP 5.4. Everything is fine under this version.
Thanks to you, I found the issue : I'm using HTTPS and with HTTPS it doesn't work whereas it works when I'm using HTTP !
I'm check with my hosting provider if they can do something.
EDIT - Solution
My hosting provider fixed the issue last year (forgot to post it here). During the time it wasn't fixed, I was still under PHP 5.4.
I paste their original message :
These issues that you describe is because the installed Certificate is a self signed Certificate. New Web Browsers and PHP Version don't accept these Certificates because of Security Risks.
We have changed the Certificate with a official issued Certificate
I just want to add that I was facing issue using the codeplex ssrsphp, therefore I googled and found another sdk, which works perfectly. I'm using php 7+. Here is the link and I'm available if there're any questions related to this.
Related
I try to read the dir and wanna get the last files from the current date.
When I put the url in the browser I got a result of all the files, which are in the ftp-directory.
So I have the proof, that the ftp-connectionparameter still works.
When I try to start the following function, then I get the error
RecursiveDirectoryIterator::__construct(ftp://...#example.com:4242): failed to open dir: operation failed
Here is the Exception from symfony:
/**
* #Route("/download", name="getfile")
*/
public function getFileWithFtp()
{
$host = "example.com";
$username = "username";
$userpass = "userpass";
$port = 4242;
$url = 'ftp://' . $username . ':' . $userpass . '#' . $host . ':' . $port .'/';
$datum = date('Y-m-d');
$finder = new Finder();
$iterator = $finder
->files()
->in($url)
->name('*BEHWN.TXT')
->date($datum);
$anzahl = count($iterator);
return $this->render('ftp/index.html.twig', [
'controller_name' => 'FtpController',
'url' => $url,
'anzahl' => $anzahl
]);
}
WHen i open the url with the file with file_gets_content($url."filename.txt"), then i get the content without error.
Only it seems that I dont use the Finder from Symfony not correct.
My current Symfony is 4.1.4 and I had cleared the caches and also i deleted the cache-files manually.
Thanks for every tipp
Here is the link to the symfony-finder-component:
https://symfony.com/doc/current/components/finder.html
As the Finder uses PHP iterators, you can pass any URL with a supported protocol:
Here is the part of the FTP code from the documentation:
// always add a trailing slash when looking for in the FTP root dir
$finder->in('ftp://example.com/');
// you can also look for in a FTP directory
$finder->in('ftp://example.com/pub/');
As stated in the docs, what you have in $iterator is a PHP iterator,
so you need to use iterator_count:
$anzahl = iterator_count($iterator);
This WILL not work anymore IF you are using symfony v3.4.7 and above..
There is the issue:
https://github.com/symfony/symfony/issues/27423
I did a fix but it will take a while till it gets merged i think
https://github.com/symfony/symfony/pull/28604
Summary:
"In Finder[...]was released which should remove duplicate slashes from path names.
However, this results in an error when used to find files in an FTP root dir."
"As a result, a working code before v3.4.7 result in breaking code after v3.4.7"
This is the method messing things up, including my fix
https://github.com/symfony/symfony/blob/0670c48477b3d88787b6fe0dec168c5c8ae49c66/src/Symfony/Component/Finder/Finder.php#L741
I'm using the Apache Chemistry CMIS PHP client to upload documents from a local folder to Alfresco Community Edition 5.1 via ATOM. Here's the script I'm using to do so:
require_once ('cmis_repository_wrapper.php');
require_once ('cmis_service.php');
$repo_url = "http://127.0.0.1:8080/alfresco/api/-default-/public/cmis/versions/1.1/atom";
$repo_username = "user";
$repo_password = "pass";
$client = new CMISService($repo_url, $repo_username, $repo_password);
$repo_folder = "/alfrescoFolder";
$source_folder = "localFolder/";
$source_files = array_diff(scandir("$source_folder", 1), array('..', '.'));
$myfolder = $client->getObjectByPath($repo_folder);
foreach($source_files as $file)
{
try
{
$upload = $client->createDocumentFromSource($myfolder->id, $file, "$source_folder/$file");
}
catch(Exception $e)
{
echo "Some error here.";
}
}
This script works fine and documents are uploaded without problem, provided that the document doesn't already exist in the Alfresco repository. For example, let's say I have a document in my Alfresco repository named example.txt, and so, if I try to upload a document from my local folder with the same name, I get a CMIS constraint exception. I dont't know how I can upload a new version of an existing document.
This is what I've tried so far, but it doesn't work:
$objs = $client->getChildren($myfolder->id);
foreach($source_files as $file)
{
foreach($objs->objectList as $obj)
{
if($obj->properties['cmis:name'] == $file)
{
try
{
$checkedout = $client->checkOut($obj->id);
$client->checkIn($checkedout->id);
}
catch(Exception $e)
{
echo "Some error here.";
}
}
else
{
try
{
$upload = $client->createDocumentFromSource($myfolder->id, $file, "$source_folder/$file", array('cmis:objectTypeId'=>'D:ex:document'));
}
catch(Exception $e)
{
echo "Some error here";
}
}
}
}
I get this error:
DEBUG: postEntry: myURL = http://127.0.0.1:8080/alfresco/api/-default-/public/cmis/versions/1.1/atom/checkedoutDEBUG: postEntry: entry_template = {title} {SUMMARY} {CONTENT} {PROPERTIES} DEBUG: postEntry: properties_xml = b549c715-9a9d-427c-bd4b-c6ea29d222cb;1.0 DEBUG: postEntry: hash_values = Array ( [PROPERTIES] => b549c715-9a9d-427c-bd4b-c6ea29d222cb;1.0 [SUMMARY] => {summary} ) DEBUG: postEntry: post_value = b549c715-9a9d-427c-bd4b-c6ea29d222cb;1.0
What's funny is that the document is in fact locked for editing, so I don't really know what's going on. I also don't know if checking out and then checking in a document is how I'm supposed to version a document.
TL;DR
I want to be able to specify that the document I'm uploading is a new version of an existing document. Does anyone know how I can do that?
The function coverage page on the Apache Chemistry web site lists what the CMIS PHP client can and cannot do. Check out, check in, and cancel checkout are all unsupported at the present time. I know they would welcome contributions.
The underlying CMIS specification supports it, of course, so you can either update the library to support checkout/checkin or use the raw binding.
I'm not an expert on CMIS, but I think that this forum post answers the question. See the answer from "jevon" that provides an example and a link to this page (see the "Updating a document" section)
I've recently found out about an alternative CMIS PHP library that implements versioning services, including example usage. I've used it to successfully solve the problem I posted in my question.
Edit: additional information added.
So, to get versioning working, I used the example code provided in the library. The script I used can be used to create new documents and to update and version existing documents. So, here it is:
<?php
require_once(__DIR__ . '/../vendor/autoload.php');
if (!is_file(__DIR__ . '/conf/Configuration.php')) {
die("Please add your connection credentials to the file \"" . __DIR__ . "/conf/Configuration.php\".\n");
} else {
require_once(__DIR__ . '/conf/Configuration.php');
}
$major = (boolean) isset($argv[1]) ? $argv[1] : false;
$httpInvoker = new \GuzzleHttp\Client(
array(
'defaults' => array(
'auth' => array(
CMIS_BROWSER_USER,
CMIS_BROWSER_PASSWORD
)
)
)
);
$parameters = array(
\Dkd\PhpCmis\SessionParameter::BINDING_TYPE => \Dkd\PhpCmis\Enum\BindingType::BROWSER,
\Dkd\PhpCmis\SessionParameter::BROWSER_URL => CMIS_BROWSER_URL,
\Dkd\PhpCmis\SessionParameter::BROWSER_SUCCINCT => false,
\Dkd\PhpCmis\SessionParameter::HTTP_INVOKER_OBJECT => $httpInvoker,
);
$sessionFactory = new \Dkd\PhpCmis\SessionFactory();
// If no repository id is defined use the first repository
if (CMIS_REPOSITORY_ID === null) {
$repositories = $sessionFactory->getRepositories($parameters);
$repositoryId = $repositories[0]->getId();
} else {
$repositoryId = CMIS_REPOSITORY_ID;
}
$parameters[\Dkd\PhpCmis\SessionParameter::REPOSITORY_ID] = $repositoryId;
$session = $sessionFactory->createSession($parameters);
$rootFolder = $session->getObject($session->createObjectId($session->getRootFolder()->getId()));
try {
$document = null;
$stream = \GuzzleHttp\Stream\Stream::factory(fopen($filePath, 'r'));
foreach ($rootFolder->getChildren() as $child) {
if ($child->getName() === $fileName) {
$document = $child;
break;
}
}
if (!$document) {
$properties = array(
\Dkd\PhpCmis\PropertyIds::OBJECT_TYPE_ID => 'cmis:document',
\Dkd\PhpCmis\PropertyIds::NAME => $fileName
);
$document = $session->createDocument($properties, $rootFolder, $stream);
$document = $session->getObject($document);
}
$checkedOutDocumentId = $document->getVersionSeriesCheckedOutId();
if ($checkedOutDocumentId) {
$checkedOutDocumentId = $session->createObjectId($checkedOutDocumentId);
} else {
$checkedOutDocumentId = $document->checkOut();
}
$checkedInDocumentId = $session->getObject($checkedOutDocumentId)->checkIn(
$major,
array(
\Dkd\PhpCmis\PropertyIds::DESCRIPTION => 'New description'
),
$stream,
'Comments'
);
} catch (\Dkd\PhpCmis\Exception\CmisVersioningException $e) {
echo "********* ERROR **********\n";
echo $e->getMessage() . "\n";
echo "**************************\n";
exit();
}
I have the following code from google adwords api and for some reason there is a specific section that prevents the browser from displaying output. I can't figure out why but can someone please tell me how to fix and why this line would prevent the browser from displaying output but allows the cli to display output.
<?php
// Include the initialization file
require_once 'src/Google/Api/Ads/AdWords/init.php';
require_once ADWORDS_UTIL_PATH . '/ReportUtils.php';
/**
* Runs the example.
* #param AdWordsUser $user the user to run the example with
* #param string $filePath the path of the file to download the report to
*/
function DownloadCriteriaReportExample(AdWordsUser $user, $filePath) {
// Load the service, so that the required classes are available.
$user->LoadService('ReportDefinitionService', ADWORDS_VERSION);
// Create selector.
$selector = new Selector();
$selector->fields = array('CampaignName', 'AdGroupName', 'Criteria',
'AverageCpc', 'Impressions', 'Clicks', 'Cost', 'AveragePosition', 'Ctr');
// Filter out deleted criteria.
$selector->predicates[] = new Predicate('Status', 'NOT_IN', array('DELETED'));
// Create report definition.
$reportDefinition = new ReportDefinition();
$reportDefinition->selector = $selector;
$reportDefinition->reportName = 'Criteria performance report #' . uniqid();
$reportDefinition->dateRangeType = 'LAST_30_DAYS';
$reportDefinition->reportType = 'CRITERIA_PERFORMANCE_REPORT';
$reportDefinition->downloadFormat = 'CSV';
// Exclude criteria that haven't recieved any impressions over the date range.
$reportDefinition->includeZeroImpressions = FALSE;
// Set additional options.
$options = array('version' => ADWORDS_VERSION, 'returnMoneyInMicros' => FALSE);
// Download report.
ReportUtils::DownloadReport($reportDefinition, $filePath, $user, $options);
printf("Report with name '%s' was downloaded to '%s'.\n",
$reportDefinition->reportName, $filePath);
}
This is the line that is causing the issue for some reason
// Don't run the example if the file is being included.
if (__FILE__ != realpath($_SERVER['PHP_SELF'])) {
return;
}
End of line causing issue
try {
// Get AdWordsUser from credentials in "../auth.ini"
// relative to the AdWordsUser.php file's directory.
$user = new AdWordsUser();
// Log every SOAP XML request and response.
$user->LogAll();
// Download the report to a file in the same directory as the example.
$filePath = dirname(__FILE__) . '/report.csv';
// Run the example.
DownloadCriteriaReportExample($user, $filePath);
} catch (Exception $e) {
printf("An error has occurred: %s\n", $e->getMessage());
}
I have set up an windows azure website (php), and I want to connect to the azure storage (blob) environment. I walked through the How to use the Blob service from PHP tutorial, but that only mentions the case when the website is stored localy.
I tried to set up a few cases, but i'm constantly getting a http 500 error.
<?php
require_once 'WindowsAzure/WindowsAzure.php';
use WindowsAzure\Common\ServicesBuilder;
use WindowsAzure\Common\ServiceException;
//$connectionString = "\WindowsAzure\Blob\Internal\IBlob";
// Create blob REST proxy.
$blobRestProxy = ServicesBuilder::getInstance()->createBlobService($connectionString); // the code gets stuck at this line, result is a HTTP 500 error
$content = fopen("C:\Users\Public\Pictures\Sample%20Pictures\Woestijn.jpg", "r");
$blob_name = "newBlob";
try {
//Upload blob
$blobRestProxy->createBlockBlob("default", $blob_name, $content);
}
catch(ServiceException $e){
// Handle exception based on error codes and messages.
// Error codes and messages are here:
// http://msdn.microsoft.com/en-us/library/windowsazure/dd179439.aspx
$code = $e->getCode();
$error_message = $e->getMessage();
echo $code.": ".$error_message."<br />";
}?>
Is there anyone who had a similar problem and managed to figure it out?
EDIT:
I now narrowed down the error search. I went into the ServicesBuilder.php file, and commented out line by line, until the page stopped to work. The line it went wrong at is $httpClient, as shown below:
public function createBlobService($connectionString)
{
$settings = StorageServiceSettings::createFromConnectionString(
$connectionString
);
$httpClient = $this->httpClient();
$serializer = $this->serializer();
$uri = Utilities::tryAddUrlScheme(
$settings->getBlobEndpointUri()
);
From what I'm seeing you're filling up the $connectionString variable with this value: "\WindowsAzure\Blob\Internal\IBlob" (even though it's commented - so probably you're passing it from somewhere else). If that's the case you'll need to change it.
The connection string should be a reference to your storage account containing the protocol, the name of the account and the key (you can find the name and the key in the portal):
$connectionString = "DefaultEndpointsProtocol=https;AccountName=jeroensaccount;AccountKey=fjmezfjmIOFJEZIOPAFJAZOPIFJAIMO"
I've been searching around StackOverflow (and other resources) on how to remotely upload files on Selenium WebDriver with PHP. I've read this http://saucelabs.com/blog/index.php/2012/03/selenium-tips-uploading-files-in-remote-webdriver/, and it mentions that you need to use a "setFileDetector" method somehow to change the way the WebDriver library you're using works.
This should work fine if I was using Ruby or Java. Most PHP frameworks on the other hand don't have this method.
Can anybody tell me how to do this in PHP? Specifically, I'm using the phpwebdriver library http://code.google.com/p/php-webdriver-bindings/
I was able to determine that the JsonWireProtocol to upload a file would be /session/<sessionId>/file by checking out the raw log on the SauceLabs.com blog post (https://saucelabs.com/jobs/1a408cf60af0601f49052f66fa37812c/selenium-server.log) so with that, I created this function to add-in to the php-webdriver-bindings library:
/**
* Send a file to your Remote WebDriver server
* This will return the local URL of the file you uploaded, which will then
* let you use sendKeys in file input elements
* #params String $value - a local or remote file to send
* #return String $resopnseValue - the local directory where the file resides on the remote server
*/
public function sendFile($value) {
$file = #file_get_contents($value);
if( $file === false ) {
return false;
}
$file = base64_encode($file);
$request = $this->requestURL . "/file";
$session = $this->curlInit($request);
$args = array( 'file' => $file );
$postargs = json_encode($args);
$this->preparePOST($session, $postargs);
$response = trim(curl_exec($session));
$responseValue = $this->extractValueFromJsonResponse($response);
return $responseValue;
}
Add this to the WebDriver.php file.
To use, just do something like this:
...
$file_location = $webdriver->sendFile('http://test.com/some/file.zip');
$file_input = $webdriver->findElementBy(LocatorStrategy::id, 'uploadfile');
$file_input->sendKeys(array($file_location));
I hope this will help other developers, spent like 3 hours looking for the answer to this.
Update:
I had to change this due to getting this error:
Expected there to be only 1 file. There were: 0
Hopefully putting this here would get Google results (I tried searching for the error message on Google and the only results it could find were the references to the source code on Google Code).
To solve this problem, I was able to deduce that the file you send actually needs to be zipped. So I've augmented the source code to use PHP's ZipArchive library. I will keep the old code on top for record-keeping, but please use the new code here:
public function sendFile($value, $file_extension = '')
{
$zip = new ZipArchive();
$filename_hash = sha1(time().$value);
$zip_filename = "{$filename_hash}_zip.zip";
if( $zip->open($zip_filename, ZIPARCHIVE::CREATE) === false ) {
echo 'WebDriver sendFile $zip->open failed\n';
return false;
}
$file_data = #file_get_contents($value);
if( $file_data === false ) {
throw new Exception('WebDriver sendFile file_get_contents failed');
}
$filename = "{$filename_hash}.{$file_extension}";
if( #file_put_contents($filename, $file_data) === false ) {
throw new Exception('WebDriver sendFile file_put_contents failed');
}
$zip->addFile($filename, "{$filename_hash}.{$file_extension}");
$zip->close();
$zip_file = #file_get_contents($zip_filename);
if( $zip_file === false ) {
throw new Exception('WebDriver sendFile file_get_contents for $zip_file failed');
}
$file = base64_encode($zip_file);
$request = $this->requestURL . "/file";
$session = $this->curlInit($request);
$args = array( 'file' => $file );
$postargs = json_encode($args);
$this->preparePOST($session, $postargs);
$response = trim(curl_exec($session));
return $this->extractValueFromJsonResponse($response);
}
Update: Turns out, you need to set two parameters on the $zip->addFile() method. Edited the above code to reflect the changes.