Presently, I am trying to interface with a SOAP-based camera system to tie into its action API so I can control when its lights come on programatically and so forth. However, when I use the code below, it's saying it cannot bind to the service and doesn't seem to be able to properly digest the WSDL file associated with the API, which can be found here:
http://www.axis.com/vapix/ws/action1/ActionService.wsdl
Is there something that's wrong with my code, or is this an issue with the WSDL file itself? Thank you very much in advance for the assistance! In advance, the error generating is the following, generated at the instantiation of the SoapClient object in the constructor:
SOAP-ERROR: Parsing WSDL: Couldn't bind to service
<?php
/**
* The purpose of this class is to act as a means to interface with a Vapix camera
* using SOAP requests so that events may be broadcast to it.
*/
$vapix = new Vapix("http://www.axis.com/vapix/ws/action1/ActionService.wsdl",
"<http://camera.address.edu>",
"<username>", "<password>");
if ($vapix)
{
echo "Connection to VAPIX successful!\n";
}
else
{
echo "Connection to VAPIX unsuccessful!\n";
}
/**
* The constructor takes in a WSDL address, the actual interfacing address of the
* server we are connecting to, a username, and a password, and establishes the
* SOAP client we need to interface with said address.
*
* #param $wsdl The WSDL specification for the service we are interacting with.
* #param $address The actual server address we are interfacing with.
* #param $username The username we need to access the server.
* #param $password The password we need to access the server.
*
* #return New Vapix object ready to interface with SOAP service.
*/
class Vapix
{
// the soap client variable we will be using to store our Vapix connection
private $soapClient;
public function __construct($wsdl, $address, $username, $password)
{
try
{
$soapClient = new SoapClient($wsdl, array("soap_version" => SOAP_1_2));
}
catch (SoapFault $fault)
{
echo "Error instantiating SOAP object!\n";
echo $fault->getMessage() . "\n";
}
// prepare SOAP headers
$sh_param = array(
"username" => $username,
"password" => $password
);
$headers = new SoapHeader($address, "UserCredentials", $sh_param);
// prepare SOAP client
$soapClient->__setSoapHeaders(array($headers));
}
/**
* This function is a generalized function used for calling a SOAP request to
* whatever service or server we are linked up to (in this case a VAPIX camera)
* so that other more specialized functions can derive from it. It will take in
* the name of the function, as well as a list of parameters.
*
* #param $funcName The name of the function we want to call.
* #param $parameters The parameters for the function we want to call.
*
* #return $info Returns info from the call if successful, NULL otherwise.
*/
public function callSoapFunction($funcName, $parameters)
{
try
{
$info = $soapClient->__call($funcName, array($parameters));
}
catch (SoapFault $fault)
{
print(
"alert('Sorry, blah returned the following ERROR: " . $fault->faultcode . "-" .
$fault->faultstring.". We will now take you back to our home page.');
window.location = 'main.php';"
);
return NULL;
}
if ($error == 0)
{
return $info;
}
}
}
?>
At least the provided WSDL-file has no <service>-area at the end of the wsdl-definition right after the <binding> block. But this missing <service>-block is needed as it contains concrete servicespecific informations (for instance its webservice URL/endpoint is listed there).
Related
The drupal/simple_oauth module creates an oauth2_token table. This table has a column value and I've examined the source code but I cannot work out how this value is generated.
To make this a little bit more complicated, I don't have this service running locally, and I don't have access to the remote server it is running on, I only have access to the database itself.
I am creating a Python service that is using the Drupal database (because reasons). I am able to generate all the required data except this value field.
I can copy the value field from one of the existing access tokens, and use it in a new record I create via a SQL INSERT. The JWT I create from this record's value works correctly with the protected endpoint. However, if I set an arbitrary value like a UUID, the request to the protected resource fails with the following error response:
{
"error": "permission_denied",
"error_description": "The 'debug simple_oauth tokens' permission is required.",
"status_code": 403,
"detail": "permission_denied"
}
The value is used in the jti of the JWT and I can see in src/Entities/AccessTokenEntity.php that this is set to $this->getIdentifier(); (<-- comments are mine):
public function convertToJWT() {
$private_claims = [];
\Drupal::moduleHandler()
->alter('simple_oauth_private_claims', $private_claims, $this);
if (!is_array($private_claims)) {
$message = 'An implementation of hook_simple_oauth_private_claims_alter ';
$message .= 'returns an invalid $private_claims value. $private_claims ';
$message .= 'must be an array.';
throw new \InvalidArgumentException($message);
}
$id = $this->getIdentifier(); /* <-- NOTE */
$now = new \DateTimeImmutable('#' . \Drupal::time()->getCurrentTime());
$key_path = $this->privateKey->getKeyPath();
$key = InMemory::file($key_path);
$config = Configuration::forSymmetricSigner(new Sha256(), $key);
$builder = $config->builder()
->permittedFor($this->getClient()->getIdentifier())
->identifiedBy($id) /* <-- SET THE JTI */
->withHeader('jti', $id)
->issuedAt($now)
->canOnlyBeUsedAfter($now)
->expiresAt($this->getExpiryDateTime())
->relatedTo($this->getUserIdentifier())
->withClaim('scope', $this->getScopes());
And this is where my investigation has stopped, as I cannot work out where getIdentifier() is implemented.
I cross-posted this question to Drupal Answers and #apaderno noted this wasn't a Drupal specific question, which nudged me towards the source for The source for PHP OAuth 2.0 Server.
The source of the value column is the generateUniqueIdentifier function in AbstractGrant.php:
/**
* Generate a new unique identifier.
*
* #param int $length
*
* #throws OAuthServerException
*
* #return string
*/
protected function generateUniqueIdentifier($length = 40)
{
try {
return \bin2hex(\random_bytes($length));
// #codeCoverageIgnoreStart
} catch (TypeError $e) {
throw OAuthServerException::serverError('An unexpected error has occurred', $e);
} catch (Error $e) {
throw OAuthServerException::serverError('An unexpected error has occurred', $e);
} catch (Exception $e) {
// If you get this message, the CSPRNG failed hard.
throw OAuthServerException::serverError('Could not generate a random string', $e);
}
// #codeCoverageIgnoreEnd
}
I want to interact with SOAP (as a client) and am not able to get the right syntax for input parameters. I have a WSDL URL that I have tested it with SoapUI and it returns result properly. There are two functions defined in the WSDL, but I only need one ("FirstFunction" below). Here is the script I run to get information on the available functions and types:
$client = new SoapClient("http://example.com/webservices?wsdl");
var_dump($client->__getFunctions());
var_dump($client->__getTypes());
And here is the output it generates:
array(
[0] => "FirstFunction Function1(FirstFunction $parameters)",
[1] => "SecondFunction Function2(SecondFunction $parameters)",
);
struct Amount {
anyURI Identifier;
Information charge;
string referenceCode;
}
struct Information {
string description;
decimal amount;
string code;
}
According to above result I developed my client with nusoap and php as below:
class Information
{
public $description;
public $amount;
public $code;
}
class Amount {
public $Identifier;
public $charge;
public $referenceCode;
}
$charge = new Information();
$charge->description = "ROUTE=XXX|abc=".$code;
$charge->amount = "NULL";
$charge->code = $chargecode;
$params = new Amount();
$params->Identifier =$num;
$params->charge = $charge;
$params->referenceCode = $refcode;
$header = new SoapHeader('key', $key);
$client->__setSoapHeaders($header);
try
{
$res = $client->__call('charge',array('parametrs'=>$params));
print_r($res->return);
}
catch(PDOException $e)
{
print_r($e->getMessage());
}
I get the following error as result:
Uncaught SoapFault exception: [soapenv:Server] unknown
In my opinion the best way to achieve it is to use a WSDL to php generator such as the PackageGenerator project. It abstracts the whole process so you only deal with objects without really worrying about SOAP.
I am learning how to use PDO and writing a Database class for the first time. I have read for a few hours about this subject and found some useful information here, here and here.
It seems clear that dependency injection is the right strategy, but I'm not sure on the best way to have the Database class access the configuration details for the database (host, dbname, user, pass).
In the first two examples above, this information is included inside the Database class. However, I usually keep all my global configuration variables inside an external file such as config.php.
In the last example, user 'prodigitalson' adds this comment to his getInstance() method:
// get the arguments to the constructor from configuration somewhere
Since the constructor for this Database class includes parameters for the database configuration, I assume that this information is not supposed to be stored in the Database class itself.
So what is the best strategy for accessing the database configuration (which I am currently storing in config.php along with other config variables) from the getInstance() method?
Someone asked a similar question here but none of the answers really addresses the question, imo.
As I said in the comments, you are using the singleton pattern which is not dependency injection.
Here is an example using dependency injection:
class Database
{
public function __construct($host, $user, $password) {
// ...
}
}
$db = new Database('foo', 'bar', 'baz');
Then you inject the database object in the classes where you need to use it:
$reportGenerator = new ReportGenerator($db);
Have a look at this tutorial if you are still lost.
While this is not what I would prefer, because \PDO does not lend itself to being configured after construction, it is the closest I've come to getting DI with \PDO.
<?php namespace b01\Database;
use Exception;
use b01\DatabaseException;
use PDO;
use PDOException;
/**
* This class is responsible for connecting to a Database.
* It wraps the PDO object, setting all the values needed in order to connect.
* Also displays some human readable error messages when connecting fails.
*
* #package \b01\Database
*/
class Connection
{
/**
* string
*/
const DSN_MYSQL = 'mysql:dbname=%s;host=%s;port=%s';
/**
* Initialized the PDO transport object.
*
* It was decided to pass the PDO class in as a string, as pseudo DI,
* to make the class more testable.
*
* #param string $server server.
* #param string $database Database name.
* #param string $username Database username for reading.
* #param string $password Database username password.
* #param int $port Server port number.
* #param string $pdoClass Defaults to \PDO, but is passed in this way to
* make this class more testable.
* #throws \b01\Exceptions\DatabaseException
*/
public function __construct(
$server,
$database,
$username,
$password,
$port = 3306,
$pdoClass = '\PDO'
) {
$dsn = sprintf(
self::DSN_MYSQL,
$database,
$server,
$port
);
$options = [
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
];
try {
$this->connection = new $pdoClass($dsn, $username, $password, $options);
} catch (Exception $error) {
throw new DatabaseException(
DatabaseException::CODE_CONNECT,
[$dsn . "\n\n", $error->getMessage()]
);
} catch (PDOException $error) {
throw new DatabaseException(
DatabaseException::CODE_CONNECT,
[$dsn . "\n\n", $error->getMessage()]
);
}
}
In your config.php file, set some constants for your database credentials, depending on the server you are running in:
switch($_SERVER['HTTP_HOST']){
case 'your-live-domain.com':
define('MYSQL_HOST', '<input>');
define('DB_NAME', '<input>');
define('MYSQL_USER', '<input>');
define('MYSQL_PW', '<input>');
break;
default:
// perhaps this could be your localhost db credentials
define('MYSQL_HOST', '<input>');
define('DB_NAME', '<input>');
define('MYSQL_USER', '<input>');
define('MYSQL_PW', '<input>');
}
Then, you can make calls to these constants within your database connection class(es).
Hi I am new to cassandra database. I am downloaded phpcassa from
https://github.com/mauritsl/php-cassandra.
When I tried to autoload cassandra library from application/config/autoload.php I got non existence class cassandra error.
Please help me to solve this issue.
o Place all Cassandra related files into application/library/ folder.
Remove the name space from each Cassandra class file.
"namespace Cassandra;"
Your file name and class name should match to load the library in auto load function in codeigniter.
Cassandra file class name is "Connection".
Change the class name as "Cassandra"
Your constructor expects a parameter to connect the database. You can't pass parameters while loading autoload library.
Change your constructor method name as connect
Using $this->cassandra->connect($host,$keyspace,$options) you can process the connection.
Rename the __construct into connect
/**
* Connect to Cassandra cluster.
*
* #param mixed $host
* Hostname as string or array of hostnames.
* #param string $keyspace
* #param array $options
*/
public function connect($host, $keyspace = NULL, $options = array()) {
$this->options += $options;
if (empty($host)) {
throw new InvalidArgumentException('Invalid host');
}
if (!is_array($host)) {
$host = array($host);
}
shuffle($host);
while ($host) {
$hostname = array_pop($host);
try {
$this->transport = new Transport($hostname, $this->options['connect_timeout'], $this->options['stream_timeout']);
break;
}
catch (Exception $e) {
if (empty($host)) {
// No other hosts available, rethrow exception.
throw $e;
}
}
}
This is the first time I am creating a restAPI. The API should only be able to process one request, which gives back all the data from an table. I went through this tutorial http://www.androidhive.info/2014/01/how-to-create-rest-api-for-android-app-using-php-slim-and-mysql-day-23/ for learning how to create an Rest API in PHP.
The Problem I am experiencing is that the api call returns an empty response and I have trouble figuring out where the error is. here the codes:
Index.php
<?php
/**
* Created by IntelliJ IDEA.
* User: Jakob Abfalter
* Date: 19.08.14
* Time: 14:17
*/
require_once '../include/DbHandler.php';
require '.././libs/Slim/Slim.php';
\Slim\Slim::registerAutoloader();
$app = new \Slim\Slim();
/**
* Echoing json response to client
* #param String $status_code Http response code
* #param Int $response Json response
*/
function echoRespnse($status_code, $response) {
$app = \Slim\Slim::getInstance();
// Http response code
$app->status($status_code);
// setting response content type to json
$app->contentType('application/json');
echo json_encode($response);
}
/**
* Listing all foods
* method GET
* url /foods
*/
$app->get('/foods', function() {
$response = array();
$db = new DbHandler();
// fetching all foods
$result = $db->getAllFoods();
$response["error"] = false;
$response["foods"] = array();
// looping through result and preparing tasks array
while ($food = $result->fetch_assoc()) {
$tmp = array();
$tmp["id"] = $food["id"];
$tmp["name"] = $food["name"];
$tmp["img"] = $food["img"];
$tmp["description"] = $food["description"];
array_push($response["foods"], $tmp);
}
echoRespnse(200, $response);
});
$app->run();
?>
DbHandler.php
<?php
/**
* Created by IntelliJ IDEA.
* User: Jakob Abfalter
* Date: 19.08.14
* Time: 14:28
*/
class DbHandler
{
private $conn;
function __construct()
{
require_once dirname(__FILE__) . './DbConnect.php';
// opening db connection
$db = new DbConnect();
$this->conn = $db->connect();
}
/**
* Fetching all foods from database
*/
public function getAllFoods() {
$stmt = $this->conn->prepare("SELECT * FROM foods");
$stmt->execute();
$foods = $stmt->get_result();
$stmt->close();
return $foods;
}
}
DbConnect.php:
<?php
/**
* Created by IntelliJ IDEA.
* User: Jakob Abfalter
* Date: 19.08.14
* Time: 14:27
*/
class DbConnect {
private $conn;
function __construct() {
}
/**
* Establishing database connection
* #return database connection handler
*/
function connect() {
include_once dirname(__FILE__) . './Config.php';
// Connecting to mysql database
$this->conn = new mysqli(DB_HOST, DB_USERNAME, DB_PASSWORD, DB_NAME);
// Check for database connection error
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
// returing connection resource
return $this->conn;
}
}
?>
.htaccess:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ %{ENV:BASE}index.php [QSA,L]
When I test the request in chrome advanced Rest Client it say:
I also tried already to put some echos in the function where the array is created and an echo in the Rspnse function, but both didnt show up
Oh actually I may have been wrong.
This looks like A problem if not THE problem.
Your method getAllFoods() closes the stmt handle $stmt->close();
You then pass the handle back to the calling code and attempt to process all the results using it.
You should not close the handle until you are finished processing the results from it.
I found the problem.
The line $foods = $stmt->get_result(); in the DbHandler threw an exception because the required driver mysqlidb wasn`t installed.