How can I subtract 3 days from a date? - php

I have a sync script that syncs domain expiration dates with next due date for billing. Right now the script works great if you want the expiration date to equal the next due date.
But I need the next due date to be three days before the expiration, so I need the code to subtract 3 days from the $expirydate in the following code snippet (Full script code is below):
if ($SyncNextDueDate) {
update_query ( "tbldomains", array ("nextduedate" => $expirydate ), array ("domain" => $domainname ) );
}
Full code:
<?php
require dirname ( __FILE__ ) . '/../../../dbconnect.php';
require ROOTDIR . '/includes/functions.php';
require ROOTDIR . '/includes/registrarfunctions.php';
$cronreport = 'Internet.bs Domain Sync Report<br>
---------------------------------------------------<br>
';
/**
* gets expiration date from domain list command
* #param string $data - command TEXT response
* #return array - associative array having as key the domain name and as value the expiration date
*/
function parseResult($data) {
$result = array ();
$data=strtolower($data);
$arr = explode ( "\n", $data );
$totalDomains = 0;
$assocArr = array ();
foreach ( $arr as $str ) {
list ( $varName, $value ) = explode ( "=", $str );
$varName = trim ( $varName );
$value = trim ( $value );
if ($varName == "domaincount") {
$totalDomains = intval ( $value );
}
$assocArr [$varName] = $value;
}
if ($assocArr ["status"] != "success") {
return false;
}
for($i = 0; $i < $totalDomains; $i ++) {
list ( $y, $m, $d ) = explode ( "/", $assocArr ["domain_" . $i . "_expiration"] );
$status = strtolower ( $assocArr ["domain_" . $i . "_status"] );
if(!is_numeric($y) || !is_numeric($m) || !is_numeric($d)){
$ddat = array ("expiry" => null, "status" => $status );
} else {
$ddat = array ("expiry" => mktime ( 0, 0, 0, $m, $d, $y ), "status" => $status );
}
$result [strtolower ( $assocArr ["domain_" . $i . "_name"] )] = $ddat;
if (isset ( $assocArr ["domain_" . $i . "_punycode"] )) {
$result [strtolower ( $assocArr ["domain_" . $i . "_punycode"] )] = $ddat;
}
}
return $result;
}
$params = getregistrarconfigoptions ( 'internetbs' );
$postfields = array ();
$postfields ['ApiKey'] = $params ['Username'];
$postfields ['Password'] = $params ['Password'];
$postfields ['ResponseFormat'] = 'TEXT';
$postfields ['CompactList'] = 'no';
$testMode = trim(strtolower($params ['TestMode']))==="on";
$SyncNextDueDate = trim(strtolower($params ["SyncNextDueDate"]))==="on";
if ($testMode) {
$url = 'https://testapi.internet.bs/domain/list';
} else {
$url = 'https://api.internet.bs/domain/list';
}
$ch = curl_init ();
curl_setopt ( $ch, CURLOPT_URL, $url );
curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, FALSE );
curl_setopt ( $ch, CURLOPT_SSL_VERIFYHOST, 0 );
curl_setopt ( $ch, CURLOPT_HEADER, 0 );
curl_setopt ( $ch, CURLOPT_USERAGENT, "WHMCS Internet.bs Corp. Expiry Sync Robot" );
curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt ( $ch, CURLOPT_POST, 1 );
curl_setopt ( $ch, CURLOPT_POSTFIELDS, $postfields );
$data = curl_exec ( $ch );
$curl_err = false;
if (curl_error ( $ch )) {
$curl_err = 'CURL Error: ' . curl_errno ( $ch ) . ' - ' . curl_error ( $ch );
exit ( 'CURL Error: ' . curl_errno ( $ch ) . ' - ' . curl_error ( $ch ) );
}
curl_close ( $ch );
if ($curl_err) {
$cronreport .= "Error connecting to API: $curl_err";
} else {
$result = parseResult ( $data );
if (! $result) {
$cronreport .= "Error connecting to API:<br>" . nl2br ( $data ) . "<br>";
} else {
$queryresult = select_query ( "tbldomains", "domain", "registrar='internetbs' AND (status='Pending Transfer' OR status='Active')" );
while ( $data = mysql_fetch_array ( $queryresult ) ) {
$domainname = trim ( strtolower ( $data ['domain'] ) );
if (isset ( $result [$domainname] )) {
if(!is_null($result [$domainname] ["expiry"])){
$expirydate = date ( "Y-m-d", $result [$domainname] ["expiry"] );
} else {
$expirydate = false;
}
$status = $result [$domainname] ["status"];
if ($status == 'ok') {
update_query ( "tbldomains", array ("status" => "Active" ), array ("domain" => $domainname ) );
}
if ($expirydate) {
update_query ( "tbldomains", array ("expirydate" => $expirydate ), array ("domain" => $domainname ) );
if ($SyncNextDueDate) {
update_query ( "tbldomains", array ("nextduedate" => $expirydate ), array ("domain" => $domainname ) );
}
$cronreport .= '' . 'Updated ' . $domainname . ' expiry to ' . frommysqldate ( $expirydate ) . '<br>';
}
} else {
$cronreport .= '' . 'ERROR: ' . $domainname . ' - Domain does not appear in the account at Internet.bs.<br>';
}
}
}
}
logactivity ( 'Internet.bs Domain Sync Run' );
sendadminnotification ( 'system', 'WHMCS Internet.bs Domain Syncronisation Report', $cronreport );
?>

$date = new DateTime($expirydate);
$date->sub(new DateInterval('P3D');
$expirydate = $date->format('Y-m-d');
or as a one-liner:
$expirydate = (new DateTime($expirydate))->sub(new DateInterval('P3D'))->format('Y-m-d');
Here's a slightly different method:
$date = new DateTime($expirydate);
$date->modify('-3 days');
$expirydate = $date->format('Y-m-d');

Related

curl_multi_exec is taking forever to give response

my project requires hitting a url against each username stored in an array using curl multi execute.The size of username array is almost 45k and till now i have created another array of 45k urls i want to hit,then to effectively send the requests i have broken that url array into chunks of size 200 each.Then i have passed each chunked array to multi_curl_execute to get the response,but the issue is it takes too much time to receive responses of all 45k requests.I have printed the response array and it was continuously increasing as expected but to print all the responses its taking too much time.Kindly help me as i have to achieve my target by tomorrow.I shall be Much obliged below given is my code
$array1=[1,2,3,4,5,6.....45000];
now creating url with each username as query string
foreach($array1 as $arr)
{
$url[]='abc.com?u='.$arr;
}
//creating chunks
$chunk[]=array_chunk($url,200,true);
//now sending each chunk
for($i=0;$i<sizeof($chunk);$i++)
{
foreach($chunk[$i] as $c_arr)
{
array_push($res,multiRequest($c_arr));
}
}
//my multi_curl function
function multiRequest($data,$options = array())
{
$curly = array();
$result = array();
$mh = curl_multi_init();
$ua = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.A.B.C Safari/525.13';
foreach ($data as $id => $d)
{
$curly[$id]= curl_init();
curl_setopt($curly[$id], CURLOPT_URL,$d);
curl_setopt($curly[$id], CURLOPT_RETURNTRANSFER,true);
curl_setopt($curly[$id], CURLOPT_USERAGENT, $ua);
curl_setopt($curly[$id], CURLOPT_AUTOREFERER, true);
curl_setopt($curly[$id], CURLOPT_FOLLOWLOCATION, true);
curl_setopt($curly[$id], CURLOPT_MAXREDIRS, 20);
curl_setopt($curly[$id], CURLOPT_HTTPGET, true);
curl_setopt($curly[$id], CURLOPT_HEADER,0);
curl_setopt($curly[$id], CURLOPT_RETURNTRANSFER,1);
curl_multi_add_handle($mh, $curly[$id]);
}
$running = null;
do {
curl_multi_exec($mh, $running);
} while($running > 0);
foreach($curly as $id => $c)
{
$result[$id] = curl_multi_getcontent($c);
curl_multi_remove_handle($mh, $c);
}
curl_multi_close($mh);
return $result;
}
Kindly tell me what should i do as it took almost 25-30 minutes to deliver the response of all 45000 requests.And right now i am running this script on my local machine whereas later on it will be scheduled as a cron job on live server
have you tried multiprocessing instead of curl_multi? maybe that's faster? wouldn't be the first time.
try
<?php
$code = <<<'CODE'
<?php
$ch=curl_init();
curl_setopt_array($ch,array(
CURLOPT_URL=>'abc.com?u='.urlencode($argv[1]),
CURLOPT_ENCODING=>"",
CURLOPT_USERAGENT=>'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.A.B.C Safari/525.13',
CURLOPT_AUTOREFERER=>true,
CURLOPT_FOLLOWLOCATION=>true,
CURLOPT_MAXREDIRS=>20
));
curl_exec($ch);
curl_close($ch);
CODE;
$jobFileh = tmpfile ();
$jobFile = stream_get_meta_data ( $jobFileh ) ['uri'];
file_put_contents ( $jobFile, $code );
$jobs = array ();
for($i = 1; $i <= 45000; ++ $i) {
$jobs [] = '/usr/bin/php ' . escapeshellarg ( $jobFile ) . ' ' . escapeshellarg ( ( string ) $i );
}
$starttime = microtime ( true );
$ret = hhb_exec_multi1 ( $jobs, 200 );
$seconds_used = microtime ( true ) - $starttime;
var_dump ( $ret, $seconds_used );
die ();
class hhb_exec_multi1_ret {
public $cmd;
public $ret;
public $stdout;
public $stderr;
function __construct(array $attributes) {
foreach ( $attributes as $name => $val ) {
$this->$name = $val;
}
}
}
/**
*
* #param string[] $cmds
* #param int $max_concurrent
* #throws InvalidArgumentException
* #return hhb_exec_multi1_ret[]
*/
function hhb_exec_multi1(array $cmds, int $max_concurrent = 10, $finished_callback = NULL): array {
// TODO: more error checking, if proc_create fail, out of ram, tmpfile() fail, etc
{
// input validation
if ($max_concurrent < 1) {
throw new InvalidArgumentException ( '$max_concurrent must be above 0... and less or equal to' . PHP_INT_MAX );
}
foreach ( $cmds as $tmp ) {
if (! is_string ( $tmp )) {
throw new InvalidArgumentException ( '$cmds must be an array of strings!' );
}
}
}
$ret = array ();
$running = array ();
foreach ( $cmds as $key => $cmd ) {
$current = array (
'cmd' => $cmd,
'ret' => - 1,
'stdout' => tmpfile (),
'stderr' => tmpfile (),
'key' => $key
);
$pipes = [ ];
$descriptorspec = array (
0 => array (
"pipe",
"rb"
),
1 => array (
"file",
stream_get_meta_data ( $current ['stdout'] ) ['uri'],
"wb"
),
2 => array (
"file",
stream_get_meta_data ( $current ['stderr'] ) ['uri'],
"wb"
) // stderr is a file to write to
);
while ( count ( $running ) >= $max_concurrent ) {
// echo ".";
usleep ( 100 * 1000 );
foreach ( $running as $runningkey => $check ) {
$stat = proc_get_status ( $check ['proc'] );
if ($stat ['running']) {
continue;
}
proc_close ( $check ['proc'] );
$check ['ret'] = $stat ['exitcode'];
$stdout = file_get_contents ( stream_get_meta_data ( $check ['stdout'] ) ['uri'] );
fclose ( $check ['stdout'] );
$check ['stdout'] = $stdout;
$stderr = file_get_contents ( stream_get_meta_data ( $check ['stderr'] ) ['uri'] );
fclose ( $check ['stderr'] );
$check ['stderr'] = $stderr;
$checkkey = $check ['key'];
unset ( $check ['key'] );
unset ( $check ['proc'] );
$tmp = ($ret [$checkkey] = new hhb_exec_multi1_ret ( $check ));
unset ( $running [$runningkey] );
if (! empty ( $finished_callback )) {
$finished_callback ( $tmp );
}
}
}
$current ['proc'] = proc_open ( $cmd, $descriptorspec, $pipes );
fclose ( $pipes [0] ); // do it like this because we don't want the children to inherit our stdin, which is the default behaviour if [0] is not defined.
$running [] = $current;
}
while ( count ( $running ) > 0 ) {
// echo ",";
usleep ( 100 * 1000 );
foreach ( $running as $runningkey => $check ) {
$stat = proc_get_status ( $check ['proc'] );
if ($stat ['running']) {
continue;
}
proc_close ( $check ['proc'] );
$check ['ret'] = $stat ['exitcode'];
$stdout = file_get_contents ( stream_get_meta_data ( $check ['stdout'] ) ['uri'] );
fclose ( $check ['stdout'] );
$check ['stdout'] = $stdout;
$stderr = file_get_contents ( stream_get_meta_data ( $check ['stderr'] ) ['uri'] );
fclose ( $check ['stderr'] );
$check ['stderr'] = $stderr;
$checkkey = $check ['key'];
unset ( $check ['key'] );
unset ( $check ['proc'] );
$tmp = ($ret [$checkkey] = new hhb_exec_multi1_ret ( $check ));
unset ( $running [$runningkey] );
if (! empty ( $finished_callback )) {
$finished_callback ( $tmp );
}
}
}
return $ret;
}
when i ran this code on my laptop to a local nginx server, it executed in 6 minutes and 39 seconds (399 seconds) with the loop set to 45000.
edit: wups, forgot to write the code to the job file (file_put_contents), fixed.

How to reduce the time CURL takes to send some data?

I'm using CURL to send some data to an api , About 300 times using a for loop , It takes some time because the CURL is started and closed each time , I want to reduce the time it takes to loop , But keeps the same functionality.
Here is the code :
//$users = 300.
for ($i=0; $i < count($users); $i++){
// some irrelevant code.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://website.com");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"src": "'.$numbers_from[$i]['number_from'].'","dst": "'.$users[$i]['international_format'].'", "text": "'.$message.'"}');
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"Content-Type: application/json",
'Authorization: Basic '. base64_encode("XXXXX:YYYYYY")
));
$message = curl_exec($ch);
curl_close($ch);
// some more code.
}
first some simple optimizations, stop counting $users on each iteration, function calls (eg, count()) are relatively expensive, a variable lookup is much faster. second, use pre-increment instead of post-increment on that $i increment, it's faster & use less cpu (in many compiled languages, the compilers auto-optmize this, but PHP doesn't), but better yet, use ForEach instead of for. it would also be faster to re-use the same curl session over and over instead of creating/deleting it every time. there is an async curl_multi interface, but it's slow and terribly cpu-hungry (no idea why, but it's been like that for years, something weird with PHP's implementation of it), i'd use multiple processes using curl_exec over curl_multi.. try
$code = <<<'CODE'
<?php
// some irrelevant code.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://website.com");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"src": "'.$argv[1].'","dst": "'.$argv[2].'", "text": "'.$argv[3].'"}');
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"Content-Type: application/json",
'Authorization: Basic '. base64_encode("XXXXX:YYYYYY")
));
$message = curl_exec($ch);
curl_close($ch);
echo $message;
// some more code.
CODE;
$jobFileh = tmpfile ();
$jobFile = stream_get_meta_data ( $jobFileh ) ['uri'];
file_put_contents($jobFile,$code);
// $users = 300.
$jobs = array ();
for($i = 0, $count = count ( $users ); $i < $count; ++ $i) {
$jobs [] = '/usr/bin/php ' . escapeshellarg ( $jobFile ) . ' ' . escapeshellarg ( $numbers_from [$i] ['number_from'] ) . ' ' . escapeshellarg ( $users [$i] ['international_format'] ) . ' ' . escapeshellarg ( $message );
}
$ret = hhb_exec_multi1 ( $jobs, 100 );
var_dump ( $ret );
die ();
class hhb_exec_multi1_ret {
public $cmd;
public $ret;
public $stdout;
public $stderr;
function __construct(array $attributes) {
foreach ( $attributes as $name => $val ) {
$this->$name = $val;
}
}
}
/**
*
* #param string[] $cmds
* #param int $max_concurrent
* #throws InvalidArgumentException
* #return hhb_exec_multi1_ret[]
*/
function hhb_exec_multi1(array $cmds, int $max_concurrent = 10, $finished_callback = NULL): array {
// TODO: more error checking, if proc_create fail, out of ram, tmpfile() fail, etc
{
// input validation
if ($max_concurrent < 1) {
throw new InvalidArgumentException ( '$max_concurrent must be above 0... and less or equal to' . PHP_INT_MAX );
}
foreach ( $cmds as $tmp ) {
if (! is_string ( $tmp )) {
throw new InvalidArgumentException ( '$cmds must be an array of strings!' );
}
}
}
$ret = array ();
$running = array ();
foreach ( $cmds as $key => $cmd ) {
$current = array (
'cmd' => $cmd,
'ret' => - 1,
'stdout' => tmpfile (),
'stderr' => tmpfile (),
'key' => $key
);
$pipes = [ ];
$descriptorspec = array (
0 => array (
"pipe",
"rb"
),
1 => array (
"file",
stream_get_meta_data ( $current ['stdout'] ) ['uri'],
"wb"
),
2 => array (
"file",
stream_get_meta_data ( $current ['stderr'] ) ['uri'],
"wb"
) // stderr is a file to write to
);
while ( count ( $running ) >= $max_concurrent ) {
// echo ".";
usleep ( 100 * 1000 );
foreach ( $running as $runningkey => $check ) {
$stat = proc_get_status ( $check ['proc'] );
if ($stat ['running']) {
continue;
}
proc_close ( $check ['proc'] );
$check ['ret'] = $stat ['exitcode'];
$stdout = file_get_contents ( stream_get_meta_data ( $check ['stdout'] ) ['uri'] );
fclose ( $check ['stdout'] );
$check ['stdout'] = $stdout;
$stderr = file_get_contents ( stream_get_meta_data ( $check ['stderr'] ) ['uri'] );
fclose ( $check ['stderr'] );
$check ['stderr'] = $stderr;
$checkkey = $check ['key'];
unset ( $check ['key'] );
unset ( $check ['proc'] );
$tmp = ($ret [$checkkey] = new hhb_exec_multi1_ret ( $check ));
unset ( $running [$runningkey] );
if (! empty ( $finished_callback )) {
$finished_callback ( $tmp );
}
}
}
$current ['proc'] = proc_open ( $cmd, $descriptorspec, $pipes );
fclose ( $pipes [0] ); // do it like this because we don't want the children to inherit our stdin, which is the default behaviour if [0] is not defined.
$running [] = $current;
}
while ( count ( $running ) > 0 ) {
// echo ",";
usleep ( 100 * 1000 );
foreach ( $running as $runningkey => $check ) {
$stat = proc_get_status ( $check ['proc'] );
if ($stat ['running']) {
continue;
}
proc_close ( $check ['proc'] );
$check ['ret'] = $stat ['exitcode'];
$stdout = file_get_contents ( stream_get_meta_data ( $check ['stdout'] ) ['uri'] );
fclose ( $check ['stdout'] );
$check ['stdout'] = $stdout;
$stderr = file_get_contents ( stream_get_meta_data ( $check ['stderr'] ) ['uri'] );
fclose ( $check ['stderr'] );
$check ['stderr'] = $stderr;
$checkkey = $check ['key'];
unset ( $check ['key'] );
unset ( $check ['proc'] );
$tmp = ($ret [$checkkey] = new hhb_exec_multi1_ret ( $check ));
unset ( $running [$runningkey] );
if (! empty ( $finished_callback )) {
$finished_callback ( $tmp );
}
}
}
return $ret;
}
now it should do 100 requests simultaneously (configurable with the 2nd parameter to the hhb_exec_multi1 call), which would probably be muuuch faster.

PHP Login using CURL not working

I want to login website bukalapak.com, but I have problem I just got blank page after execute this php, here my code :
var_dump(login_bukalapak());
function login_bukalapak(){
$data_login = array(
'user_session[username]' => 'myusername',
'user_session[password]' => 'mypassword'
);
$url = "https://www.bukalapak.com/user_sessions";
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
$cookie = 'cookies.txt';
$timeout = 30;
curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout );
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie);
curl_setopt ($ch, CURLOPT_POST, 1);
curl_setopt ($ch, CURLOPT_POSTFIELDS,$data_login);
$result = curl_exec($ch);
/*$url = "https://www.bukalapak.com/products/new?from=dropdown";
curl_setopt ($ch, CURLOPT_POST, 0);
curl_setopt($ch, CURLOPT_URL, $url);
$result = curl_exec($ch);*/
curl_close($ch);
return $result;
}
I confuse I just have return blank, how the correct answer to make it run well and return successfully login ?
Thanks.
you're doing many things wrong here.
1: their login system use application/x-www-form-urlencoded encoding for the login POST request body, but your code try to login using multipart/form-data encoding.
2: their login system requires you to have a pre-existing cookie session before logging in, but your code does not obtain a cookie session prior to sending the login request.
3: they use a CSRF token scheme to protect their login, where you need to fetch the csrf token from the page, and add it to your login post fields before sending the login request, called authenticity_token (it's in their html as <input type="hidden" name="authenticity_token" value="<TOKEN>" />), your code makes no attempt to fetch and extract this token prior to logging in.
4: there is a bunch of login parameters you're missing, namely utf8, user_session[remember_me], comeback, button, and as i said previously, authenticity_token - not all of these parameters may be required, or perhaps all of them are, but at least some of them (authenticity_token) is 100% sure to be required, just add them all, unless you wanna waste time figuring out which parameters are required and which is not, it's probably not worth the effort.
5: your code lacks error checking, curl_setopt returns bool(false) if there was a problem setting your settings, and curl_exec returns bool(false) if there was a problem during the transfer
with that in mind, here is a sample implementation in hhb_curl that i think would work with a real username/password:
<?php
require_once ('hhb_.inc.php');
$hc = login_bukalapak ( "foo#bar.com", "password" );
var_dump ( $hc->exec ( 'https://www.bukalapak.com/' )->getStdOut () );
function login_bukalapak(string $username, string $password): \hhb_curl {
$hc = new hhb_curl ( '', true );
$html = $hc->exec ( 'https://www.bukalapak.com/' )->getStdOut ();
$domd = #DOMDocument::loadHTML ( $html );
$data_login = getDOMDocumentFormInputs ( $domd, true, false ) ['new_user_session'];
// var_dump ( $data_login ) & die ();
assert ( isset ( $data_login ['user_session[username]'], $data_login ['user_session[password]'] ), 'username/password field not found in login form!' );
$data_login ['user_session[username]'] = $username;
$data_login ['user_session[password]'] = $password;
$url = "https://www.bukalapak.com/user_sessions";
$html = $hc->setopt_array ( array (
CURLOPT_URL => 'https://www.bukalapak.com/user_sessions',
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => http_build_query ( $data_login )
) )->exec ()->getStdOut ();
//var_dump ( $html );
$domd = #DOMDocument::loadHTML ( $html );
$xp = new DOMXPath ( $domd );
$loginErrorEles = $xp->query ( '//*[contains(#class,"__error") and not(contains(#class,"hidden"))]' );
$loginErrors = '';
foreach ( $loginErrorEles as $loginError ) {
if (empty ( $loginError->textContent )) {
continue;
}
$loginErrors .= trim ( $loginError->textContent );
}
if (! empty ( $loginErrors )) {
throw new RuntimeException ( 'failed to log in: '.$loginErrors);
}
// assuming logged in successfully
// note that its highly unreliable, they sometimes say "wrong username/password", and someitmes not, seemingly randomly.
return $hc;
}
function getDOMDocumentFormInputs(\DOMDocument $domd, bool $getOnlyFirstMatches = false, bool $getElements = true): array {
// :DOMNodeList?
if (! $getOnlyFirstMatches && ! $getElements) {
throw new \InvalidArgumentException ( '!$getElements is currently only implemented for $getOnlyFirstMatches (cus im lazy and nobody has written the code yet)' );
}
$forms = $domd->getElementsByTagName ( 'form' );
$parsedForms = array ();
$isDescendantOf = function (\DOMNode $decendant, \DOMNode $ele): bool {
$parent = $decendant;
while ( NULL !== ($parent = $parent->parentNode) ) {
if ($parent === $ele) {
return true;
}
}
return false;
};
// i can't use array_merge on DOMNodeLists :(
$merged = function () use (&$domd): array {
$ret = array ();
foreach ( $domd->getElementsByTagName ( "input" ) as $input ) {
$ret [] = $input;
}
foreach ( $domd->getElementsByTagName ( "textarea" ) as $textarea ) {
$ret [] = $textarea;
}
foreach ( $domd->getElementsByTagName ( "button" ) as $button ) {
$ret [] = $button;
}
return $ret;
};
$merged = $merged ();
foreach ( $forms as $form ) {
$inputs = function () use (&$domd, &$form, &$isDescendantOf, &$merged): array {
$ret = array ();
foreach ( $merged as $input ) {
// hhb_var_dump ( $input->getAttribute ( "name" ), $input->getAttribute ( "id" ) );
if ($input->hasAttribute ( "disabled" )) {
// ignore disabled elements?
continue;
}
$name = $input->getAttribute ( "name" );
if ($name === '') {
// echo "inputs with no name are ignored when submitted by mainstream browsers (presumably because of specs)... follow suite?", PHP_EOL;
continue;
}
if (! $isDescendantOf ( $input, $form ) && $form->getAttribute ( "id" ) !== '' && $input->getAttribute ( "form" ) !== $form->getAttribute ( "id" )) {
// echo "this input does not belong to this form.", PHP_EOL;
continue;
}
if (! array_key_exists ( $name, $ret )) {
$ret [$name] = array (
$input
);
} else {
$ret [$name] [] = $input;
}
}
return $ret;
};
$inputs = $inputs (); // sorry about that, Eclipse gets unstable on IIFE syntax.
$hasName = true;
$name = $form->getAttribute ( "id" );
if ($name === '') {
$name = $form->getAttribute ( "name" );
if ($name === '') {
$hasName = false;
}
}
if (! $hasName) {
$parsedForms [] = array (
$inputs
);
} else {
if (! array_key_exists ( $name, $parsedForms )) {
$parsedForms [$name] = array (
$inputs
);
} else {
$parsedForms [$name] [] = $tmp;
}
}
}
unset ( $form, $tmp, $hasName, $name, $i, $input );
if ($getOnlyFirstMatches) {
foreach ( $parsedForms as $key => $val ) {
$parsedForms [$key] = $val [0];
}
unset ( $key, $val );
foreach ( $parsedForms as $key1 => $val1 ) {
foreach ( $val1 as $key2 => $val2 ) {
$parsedForms [$key1] [$key2] = $val2 [0];
}
}
}
if ($getElements) {
return $parsedForms;
}
$ret = array ();
foreach ( $parsedForms as $formName => $arr ) {
$ret [$formName] = array ();
foreach ( $arr as $ele ) {
$ret [$formName] [$ele->getAttribute ( "name" )] = $ele->getAttribute ( "value" );
}
}
return $ret;
}

Php Curl send File AND array data

I want to send complex Post data with Curl.
The data i try to send:
Array
(
[test] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
[file] => CURLFile Object
(
[name] => H:\wwwroot\curl/upload.txt
[mime] =>
[postname] =>
)
)
I need to use the variables in the post-side as $_POST["test"] and $_FILES["file"]
But i can not realize that. For the (sometimes multidimensional) array-data i need http_build_query but that breaks the file. If i don`t use http_build_query my array gives an "array to string conversion" error.
How can i get this to work?
Code:
Index.php
$curl = curl_init();
$postValues = Array("test" => Array(1,2,3));
$postValues["file"] = new CurlFile(dirname(__FILE__). "/upload.txt");
curl_setopt($curl, CURLOPT_URL, "localhost/curl/post.php");
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $postValues);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
$curlResult = curl_exec($curl);
$curlStatus = curl_getinfo($curl);
echo $curlResult;
post.php
print_r($_REQUEST);
print_r($_FILES);
After very long research to manage the same problem, I think that a simpler solution could be:
$postValues = Array("test[0]" => 1, "test[1]" => 2, "test[2]" => 3);
this is the right way to emulate what happen on browsers
<input type="hidden" name="test[0]" value="1">
<input type="hidden" name="test[1]" value="2">
...
The result is:
Array
(
[test] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
)
Array
(
[file] => Array
(
[name] => upload.txt
[type] => application/octet-stream
[tmp_name] => /tmp/phprRGsPU
[error] => 0
[size] => 30
)
)
After long research and testing i`ve got the (not very nice but working) solution:
function createHttpHeader($postValues, $overrideKey = null) {
global $delimiter;
// invalid characters for "name" and "filename"
$disallow = array("\0", "\"", "\r", "\n");
$data = Array();
if (!is_array($postValues)) {
$postValues = Array($postValues);
}
foreach($postValues as $key => $value) {
$useKey = $overrideKey === null ? $key : $overrideKey. "[$key]";
$useKey = str_replace($disallow, "_", $useKey);
if (is_array($value)) {
$data = array_merge($data, addPostData($value, $useKey));
} else {
$data[] = "--". $delimiter. "\r\n";
$data[] = "Content-Disposition: form-data; name=\"". $useKey. "\"";
if (is_a($value, "\CurlFile")) {
$data[] = "; filename=\"". basename($value->name). "\"\r\n";
$data[] = "Content-Type: application/octet-stream\r\n\r\n";
$data[] = file_get_contents($value->name). "\r\n";
} else {
$data[] = "\r\n\r\n". $value. "\r\n";
}
}
}
return $data;
}
Test with:
$postValues = Array(
"blaat" => 1,
"test" => Array(1,2,3),
"grid" => Array(0 => array(1,2), 1 => array(4,5)),
"gridComplex" => Array("rows" => array(1,2), "columns" => array(0 => array(1,2,3,4), 1 => array(4,5,4,5)))
);
$postValues["file[0]"] = new CurlFile($file, "text/plain");
$postValues["file[1]"] = new CurlFile($file, "text/plain");
// print_r(new CurlFile($file));exit;
$delimiter = "-------------" . uniqid();
$data = createHttpHeader($postValues);
$data[] = "--" . $delimiter . "--\r\n";
$data = implode("", $data);
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "localhost/curl/post.php");
curl_setopt($curl, CURLOPT_HTTPHEADER , array('Content-Type: multipart/form-data; boundary=' . $delimiter, 'Content-Length: ' . strlen($data)));
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
$curlResult = curl_exec($curl);
echo $curlResult;
Edit: addition the addPostData function:
function addPostData($postValues, $delimiter, $overrideKey = null) {
// invalid characters for "name" and "filename"
$disallow = array("\0", "\"", "\r", "\n");
$data = Array();
if (!is_array($postValues)) {
$postValues = Array($postValues);
}
foreach($postValues as $key => $value) {
$useKey = $overrideKey === null ? $key : $overrideKey. "[$key]";
$useKey = str_replace($disallow, "_", $useKey);
if (is_array($value)) {
$data = array_merge($data, $this->addPostData($value, $delimiter, $useKey));
} else {
$data[] = "--". $delimiter. "\r\n";
$data[] = "Content-Disposition: form-data; name=\"". $useKey. "\"";
if (is_a($value, "\CurlFile")) {
$data[] = "; filename=\"". basename($value->postname). "\"\r\n";
$data[] = "Content-Type: ". $value->mime. "\r\n\r\n";
$data[] = file_get_contents($value->name). "\r\n";
} else {
$data[] = "\r\n\r\n". $value. "\r\n";
}
}
}
return $data;
}

How to echo a specific value in an array?

i am having a problem with a function that i have got online from somewhere, the issue is the function is supposed to return a specific value in an array but whenever i echo the function, it gives me a big array in the print_r style! here is the code:-
function USPSParcelRate() {
$userName = 'XXXXXXXXXXX';
$orig_zip = '10459';
//Shipping Request
$dest_zip = getshipinfo('zip_code');
foreach($_SESSION as $name=> $value){
if($value>0){
if(substr($name, 0, 5)=='cart_'){
if(substr($name, 0, 5)=='cart_'){
$id=substr($name, 5, (strlen($name)-5));
$query = mysql_query("SELECT `category`,`subcategory` FROM `items` WHERE `id`='".mysql_real_escape_string((int)$id)."' ");
while($query_row = mysql_fetch_assoc($query)){
$category = $query_row['category'];
$subcategory = $query_row['subcategory'];
}
$sql = mysql_query("SELECT `pounds`,`ounces` FROM `categories` WHERE `category`='".$category."' AND `subcategory`='".$subcategory."' ");
while($sql_row = mysql_fetch_assoc($sql)){
$pounds = $sql_row['pounds'];
$ounces = $sql_row['ounces'];
}
}
}
}
}
$url = "http://production.shippingapis.com/shippingapi.dll";
$ch = curl_init();
// set the target url
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
// parameters to post
curl_setopt($ch, CURLOPT_POST, 1);
$data = "API=RateV4&XML=http://production.shippingapis.com/shippingapi.dll=<RateV4Request USERID='151ALHAD4911' >
<Revision/>
<Package ID='1ST'>
<Service>PRIORITY</Service>
<ZipOrigination>$orig_zip</ZipOrigination>
<ZipDestination>$dest_zip</ZipDestination>
<Pounds>$pounds</Pounds>
<Ounces>$ounces</Ounces>
<Container>NONRECTANGULAR</Container>
<Size>LARGE</Size>
<Width>12</Width>
<Length>15.5</Length>
<Height>6</Height>
<Girth>31</Girth>
</Package>
</RateV4Request>";
// send the POST values to USPS
curl_setopt($ch, CURLOPT_POSTFIELDS,$data);
$result=curl_exec ($ch);
$data = strstr($result, '<?');
// echo '<!-- '. $data. ' -->'; // Uncomment to show XML in comments
$xml_parser = xml_parser_create();
xml_parse_into_struct($xml_parser, $data, $vals, $index);
xml_parser_free($xml_parser);
$params = array();
$level = array();
foreach ($vals as $xml_elem) {
if ($xml_elem['type'] == 'open') {
if (array_key_exists('attributes',$xml_elem)) {
list($level[$xml_elem['level']],$extra) = array_values($xml_elem['attributes']);
} else {
$level[$xml_elem['level']] = $xml_elem['tag'];
}
}
if ($xml_elem['type'] == 'complete') {
$start_level = 1;
$php_stmt = '$params';
while($start_level < $xml_elem['level']) {
$php_stmt .= '[$level['.$start_level.']]';
$start_level++;
}
$php_stmt .= '[$xml_elem[\'tag\']] = $xml_elem[\'value\'];';
eval($php_stmt);
}
}
curl_close($ch);
//echo '<pre>'; print_r($params); echo'</pre>'; // Uncomment to see xml tags
return $params['RateV4Response']['1ST']['1']['RATE'];
}
echo USPSParcelRate();
this code doesn't give me any results unless i uncomment the print_r lines and it shows it like this:-
Array
(
[RATEV4RESPONSE] => Array
(
[1ST] => Array
(
[ZIPORIGINATION] => XXXXX
[ZIPDESTINATION] => XXXXX
[POUNDS] => 3
[OUNCES] => 5
[CONTAINER] => NONRECTANGULAR
[SIZE] => LARGE
[WIDTH] => 12
[LENGTH] => 16
[HEIGHT] => 6
[GIRTH] => 31
[ZONE] => 5
[1] => Array
(
[MAILSERVICE] => Priority Mail 3-Day<sup>™</sup>
[RATE] => 14.05
)
)
)
)
how can i echo the value of this line only :-
[RATE] => 14.05
Array keys are case sensitive, so...
return $params['RATEV4RESPONSE']['1ST'][1]['RATE'];
Should do it

Categories