thybag / PHP-SharePoint-Lists-API

A simple PHP API to make working with SharePoint lists easy.
MIT License
184 stars 95 forks source link

No XML document #149

Open chrisandthetopher opened 5 years ago

chrisandthetopher commented 5 years ago

I have had this script running for months, but this morning I am getting the following error:

[18-Dec-2018 12:02:50 Australia/Melbourne] PHP Fatal error: Uncaught Exception: Error (Client) looks like we got no XML document,more= in /home/jppporta/public_html/advocate/email-unsub/Thybag/SharePointAPI.php:1016 Stack trace:

0 /home/jppporta/public_html/advocate/email-unsub/Thybag/SharePointAPI.php(446): Thybag\SharePointAPI->onError(Object(SoapFault))

1 /home/jppporta/public_html/advocate/email-unsub/Thybag/Service/QueryObjectService.php(210): Thybag\SharePointAPI->read('JPP Contact Lis...', 1, Object(Thybag\Service\QueryObjectService), NULL, NULL, NULL)

2 /home/jppporta/public_html/advocate/email-unsub/sharepoint_unsub.php(26): Thybag\Service\QueryObjectService->get()

3 {main}

thrown in /home/jppporta/public_html/advocate/email-unsub/Thybag/SharePointAPI.php on line 1016

Any ideas?

djansen1987 commented 5 years ago

HI found a solution to the issue? Got similar error:

Fatal error: Uncaught Exception: Error (Client) looks like we got no XML document,more= in /home/xxxxxxxx/public_html/xxxxxxxx/sharepoint/src/Thybag/SharePointAPI.php:1016 Stack trace: #0 /home/xxxxxxxx/public_html/xxxxxxxx/sharepoint/src/Thybag/SharePointAPI.php(446): Thybag\SharePointAPI->onError(Object(SoapFault)) #1 /home/xxxxxxxx/public_html/xxxxxxxx/sharepoint/index.php(22): Thybag\SharePointAPI->read('Change Manageme...') #2 {main} thrown in /home/xxxxxxxx/public_html/xxxxxxxx/sharepoint/src/Thybag/SharePointAPI.php on line 1016

chrisandthetopher commented 5 years ago

No solution yet.

djansen1987 commented 5 years ago

Hi Chris,

Thanks for you response, hope the creators of thybag know how to fix it.

thybag commented 5 years ago

Hi both,

Do you have any example code that can replicate the bug at all? (Also be good to know what SP version your running against / what auth method your using).

The Error (Client) looks like we got no XML document message is coming direct from the SP API, so am guessing its not like something that being posted at it. It may be an API change in a newer version (I don't have access to a SP instance to test with these days, so unsure if they have introduced any breaking changes)

May also be worth checking its nothing to do with trailing white space / the BOM in the php file itself ( https://stackoverflow.com/questions/4313952/soap-looks-like-we-got-no-xml-document )

chrisandthetopher commented 5 years ago

Hi,

Mine is just a form that accepts an email address and edits a field in Sharepoint online...this is the relevant part of the page:


if(!empty($_POST['usremail'])) {
$sp =  new Thybag\SharePointAPI('username', 'password', 'https://BUSINESSNAME.sharepoint.com/_vti_bin/Lists.asmx?WSDL', 'SPONLINE'); 
$data = $sp->query('Contact List')->where('Email','=',$usremail)->limit(1)->sort('Title','FirstName','Email','DESC')->get();` 
foreach($data as $key => $value)        
{        
if(!empty($value['id'])){
$spid = $value['id'];
}
if(!empty($value['no_x0020_newsletter'])){
$spnl = $value['no_x0020_newsletter'];
}
}
if(isset($spid)) {
$sp2 =  new Thybag\SharePointAPI('username', 'password', 'https://BUSINESSNAME.sharepoint.com/_vti_bin/Lists.asmx?wsdl', 'SPONLINE'); 
$data2 = $sp2->updateMultiple('Contact List', array(
array('ID'=>$spid,'No_x0020_Newsletter'=>$true)
));
echo 'Thanks, You have been unsubscribed.';
} else {
echo 'Email address not found.';
}
} else {
echo 'Must enter a value!';
}

This was working for months, then one day just stopped...I use a similar piece of code in another part of the site and this has also stopped working without any changes on my end, so they may have changed the API
djansen1987 commented 5 years ago

basis of the script

require_once('SharePointAPI.php');

use Thybag\SharePointAPI; $sp = new SharePointAPI('username', 'password', 'https://BUSINESSNAME.sharepoint.com/sites/SITENAME/_vti_bin/Lists.asmx?WSDL', 'SPONLINE');

$data = $sp->read('Change Management');

as the code does not display well i added in a notepad:

sharepoint draft.txt

thybag commented 5 years ago

Ah, i think that may well be a headers sent to early issue. (basically any whitespace or content before the php)

Basically having any code before the <?php (like the css), will cause the server to start sending data to the client, meaning its no longer able to update the headers (sent before this data) which will break things like SOAP potentially.

Would suggest moving the SharePoint api php right to the top of the file and having all other markup after its done requesting whatever data you need.

djansen1987 commented 5 years ago

Hi Thybag,

Thanks for your response. Striped down the script to only have below. But got the same error (with debug on):

`<?php // ini_set('display_errors', 1); // ini_set('display_startup_errors', 1); // error_reporting(E_ALL);

require_once('SharePointAPI.php');

use Thybag\SharePointAPI; $sp = new SharePointAPI('username@domain.ext', 'SecurePassword', 'https://company.sharepoint.com/sites/teamsite/_vti_bin/Lists.asmx?WSDL', 'SPONLINE');

$data = $sp->read('List Name'); ?>`

chrisandthetopher commented 5 years ago

Hi,

I also tried with no luck...I stripped everything except the sharepoint code out, but got the same error:

<?php include "Thybag/SharePointAPI.php"; include "Thybag/Auth/SharePointOnlineAuth.php"; include "Thybag/Auth/SoapClientAuth.php"; include "Thybag/Auth/StreamWrapperHttpAuth.php"; include "Thybag/Service/ListService.php"; include "Thybag/Service/QueryObjectService.php"; $sp = new Thybag\SharePointAPI('USERNAME', 'PASSWORD', 'https://businessname.sharepoint.com/_vti_bin/Lists.asmx?wsdl', 'SPONLINE'); $data = $sp->read('Contact List', 10); ?>

djansen1987 commented 5 years ago

Today it started working again suddenly without changing anything to the code. Any clue how this is possible ?

chrisandthetopher commented 5 years ago

Weird...mine is still not working

djansen1987 commented 5 years ago

mine stopped working an hour later.

CakeBit commented 5 years ago

Quick fix. Try replacing

if($loop[0] == 'Set-Cookie') {

with

if(strtolower($loop[0]) == 'set-cookie') {

on line 136 in SharePointOnlineAuth.php.

Sharepoint Online (Office365) is no longer returning Set-Cookie capitalized in the response headers. This causes extractAuthCookies in SharePointOnlineAuth.php to return no cookies as it looks for an exact string match of 'Set-Cookie'. This then prevents future requests from Authenticating (I was seeing 403 FORBIDDEN returned, which the XML parser was complaining about). The fix is not requiring the case to be an exact match when searching for cookies in the header string.

If someone wants to make a pull request or include a cookie parser, feel free to improve on this.

thybag commented 5 years ago

Hi @CakeBit - have applied your fix directly to develop 👍

(I no longer have access to any SharePoint instances to test stuff myself, so am generally avoiding making many changes. That said, your fix sounded sensible & entirely safe. Cheers for the suggestion.)

https://github.com/thybag/PHP-SharePoint-Lists-API/commit/36d443641cbbf85c6458280a0eb9a96ebb473609

CakeBit commented 5 years ago

@thybag Thanks so much!

In your commit Set-Cookie should also be lowercased ('set-cookie') so that PHP can match against it. As it stands currently it will not find any cookies because it's searching a header converted to lowercase against a string with capitalization. 👀

Maybe in the future a Cookie Parser could be implemented (here's one such example on StackOverflow).

thybag commented 5 years ago

🤦‍♂️ Fixed.

chrisandthetopher commented 5 years ago

That seems to have fixed my issue...thank you very much.