Accessing a sharepoint using perl and webdav - perl

a similar question was asked in question 494120, but IMHO was not really answered...
I want to upload files to a sharepoint using perl/WebDAV (from a Win32 host). To achive this, I need to authenticate with KERBEROS on the server. After googling for hours and trying different approaches, I'm not able to open a connection. Current code is this:
my $agent = HTTP::DAV::UserAgent->new(keep_alive=>1);
$agent->agent('Agent');
$agent->timeout(1000);
my $d = HTTP::DAV->new(-useragent => $agent);
$d->credentials( -user=>$user,-pass =>$pass, -url =>$url);
$d->open( -url=>$url ) or die("Couldn't open $url: " .$d->message . "\n");
When doing the $d->open(...), I always get "Couldn't open $url: Unauthorized. Negotiate". So, obviously the basic authentication doesn't work.
Could anyone point me to the right path, please? I am not fixed to using WebDAV, any other mechanism would fit me as well. Just want to get it working...
Edit 1
When using LWP along with Authen::NTLM (as suggested by Madhur) also doesn't work. It results in a 500 internal server error on IIS as well as on Apache. Since the same error occurs on two different web servers (with two different NTLM implementations) I guess that there's gotta be a problem in the Authen::NTLM module.
Looking at the implementation of Authen::NTLM it seems to me that the code is kinda reverse engineered and neither implemented based on a specification nor is it really configurable. What turns up the question why the specification wasn't used to implement the module...
Is using NTLM along with Perl such an exotic use case?
Edit 2
Based on Madhur's suggestion, I tried accessing the Sharepoint with Curl. This works. But sniffing the NTLM messages of Curl and those sent by Perl shows me, that the message format is somehow different.

Instead of using WebDAV. I would suggest you use out of the box web services.
This gives overview on how to use sharepoint web services in PERL:
http://www.squish.net/log/2008/10/11/perl-sharepoint/
http://shareperl.blogspot.com/
And this is the .NET code to upload the file using web service:
http://www.oriolardevol.com/Article/Details/3
Converting it to PERL code is left to you as its been years since I used PERL :)

Related

Consuming a rest api with Drupal

I am currently maintaining a drupal 7 site. Although I already gained some experience with Drupal my knowledge is still rather low-level and doesn't go beyond installing and configuring modules.
My site is pretty much a metadata repository. People fill in forms about datasets.
My problem is probably rather basic (or maybe not - it's hard to say).
I need to implement an external file repository. The data repository provides a REST API that should allow the users to upload files to their repository using my drupal site.
After uploading a file the data repository then provides a permanent identifier that I have to save in addition to the other fields.
Now I'm looking for the best way to build a very simple UI that allows users to upload their files to the repository without leaving my drupal site (e.g. while they are in the process of filling in the fields). I also need the liberty to form the URLs needed myself as commands for the API as there are many options that need to be declared. For instance I need to provide a certain token in my URLs for the data repository to be able to identify who's uploading.
I already did some research and found modules like:
https://www.drupal.org/project/wsclient
https://www.drupal.org/project/chr
https://www.drupal.org/project/rest_client
or these topics:
http://drupal.stackexchange.com/questions/42103/how-do-i-consume-rest-as-a-client
https://www.drupal.org/node/1114312
However, I still wasn't able to find out what the best strategy is to implement that.
What I need are tips on what the best way is to do that.
Currently I don't really know what I'm looking for.
Also I do realise that the are drupal forums where I could ask a question like this, but I have far more better experiences with stackoverflow.
I'd appreciate any help.
Thanks
Sorry for answering my own question, but based on the information I got from here:
https://drupal.stackexchange.com/questions/42103/how-do-i-consume-rest-as-a-client
I was able to solve the problem.
I wrote a custom drupal module that communicates with the API.
Drupal 7 comes with its own function for https requests:
https://api.drupal.org/api/drupal/includes%21common.inc/function/drupal_http_request/7.x
However, it wasn't enough for my needs as I also neeeded to transfer data, so I ended up using the php library curl (https://curl.haxx.se/), which was built for exactly that purpose.
Basically, you install curl on your server where your drupal installation is also running on. Somewhere in your custom module, preferably in a config menu, you can check if the installation was succesful using something like this:
function _is_curl_installed() {
if (in_array ('curl', get_loaded_extensions())) {
return true;
}
else {
return false;
}
}
if (_is_curl_installed()) {
drupal_set_message(t('Curl is installed.'));
} else {
drupal_set_message(t('Curl is NOT installed.'), 'error');
}
Drupal should be able to recognise curl automatically after the installation.
And here is one example for a rest call in drupal using curl (based on this answer how to upload file using curl with php). Keep in mind that the syntax using '#' is outdated and that drupal will complain about it. In my example I used "new CURLFile".
$request = curl_init($deposit_url);
curl_setopt($request, CURLOPT_POST, true);
$cfile = new CURLFile($file_realpath,'application/octet-stream', $base_file_name);
curl_setopt(
$request,
// the content of the array depends on the API you are communicating with
CURLOPT_POSTFIELDS,
array(
'file' => $cfile,
'access_token' => $temp_token,
'verify' => false,
));
curl_setopt($request, CURLOPT_RETURNTRANSFER, true);
$output= curl_exec($request);
// output the response
// drupal_set_message(t('The curl output [1] is '.$output));
curl_close($request);
I hope this is helpful to someone.
EDIT: I released a contributed module that solves the described problem:
https://www.drupal.org/project/b2share
Yes you can implement nice REST API services using Drupal if you are using drupal 7 try to use "Services" MOdule that would be a great starting point for your project by using this module you can create your own endpoinds and you can intergrate other applications to this endpoinds.

Do away with SOAP::Lite->service() call

I have a fully functional perl script which talks to our SOAP webservice. Today it does that via the SOAP::Lite->service('.../name?WSDL') and then a call to execute() against the returned value. They're now locking down the WSDL so when I hit that I get a 403 error back.
I'm looking for pointers on how to change my script so that it no longer uses the WSDL to figure things out. I do have access to the WSDL itself to look at anything I need to know, but the perl script no longer will.
Since you have the WSDL file, you can use the local copy of it to drop right in with no other changes to your code:
my $soap = SOAP::Lite->service("file:localcopy.wsdl");
If you don't mind switching to SOAP::WSDL, it includes wsdl2perl.pl which will generate all of the perl packages for you:
wsdl2perl.pl file:localcopy.wsdl

Implement WebDAV connection in iPhone app

I've been searching around this forum and Google, but I can't find anything that helps me. I need to be able to connect to a WebDAV server, type in a username and password to get access and show the folders and files in my iPhone app. Just like the free iPhone app called WebDAV Nav.
Seems like the question is asked a lot, but no one really has an answer for it?
Does anyone know if there's a sample project out there, that could get me on the right track?
I've tried WTClient and flyingcode webdav.
Both flycode's WebDAV and WTClient are a few years old, seem incomplete and have a few errors.
When I try WTClient with a WebDAV server I get the response
This URL can be accessed only with a WebDAV compatible software program.
When I try the flycode WebDAV code, it fails to parse the server directory listing response correctly. I managed to modify the code in FMWebDAVRequest to look for slightly different XML elementNames in the response
eg "response" instead of "D:response", "href" instead of "D:href",
"resourcetype" instead of ":getcontenttype"
Then it worked, successfully retrieving the directory listing.
But should I continue to tweak this code, try something more robust or roll my own? What have others done/used?

How do I implement cookie based auth for a Perl website on shared hosting?

I'm very new to Perl, and I have absolutely no idea how to approach this. We have an old Perl application which previously used Apache auth; we'd like to replace this with a cookie based form-style authentication. I understand that this is very case-specific, and there is no one answer as such, but some general tips would be much appreciated.
Will I need to edit all .pl files in the website? Or is there a "golden hammer" solution I can use? Is there something on CPAN I can use? We're using Perl v5.8.8 if it matters, and we're using Apache 2 shared hosting. I am happy to provide additional information as is necessary.
For the authentication to be recognized/required, it will need to be checked by the .pl file that initially receives the user's request. So the answer to whether all .pl files will need to be changed depends on how your application is structured:
If the user goes to http://myserver.com/one.pl to do the first thing and http://myserver.com/two.pl to do the second thing, then, yes, you'll need to change them all because they're all receiving requests individually.
If the user goes to http://myserver.com/dispatch.pl?mode=one for the first thing and http://myserver.com/dispatch.pl?mode=two for the second thing and dispatch.pl calls either one.pl or two.pl behind the scenes based on the mode parameter, then you only need to change dispatch.pl, since it's the only one directly receiving requests from the user.
Edited to add: If you're dealing with the first model, then I'd strongly recommend setting up an external module (.pm file) with the cookie-handling code and calling that from each of your individual .pl files instead of duplicating that code all over the place. Ideally, this would let you get by with only a few lines of added code in each .pl:
use MyCookieHandlingModule qw(verify_cookie redirect_to_login);
my $q = CGI->new; # ...unless you're already using CGI in object-oriented mode
redirect_to_login unless verify_cookie($q);
You could do it at a level outside the Perl program.
Thanks for your answers guys, but I eventually decided on CGI::Session::Auth::DBI which works well on shared hosting.

How can I download Yahoo Groups?

I want to download some Yahoo Groups (files, photos, messages, memberlist) and I've found these scripts:
http://freshmeat.net/projects/grabyahoogroup/
http://sourceforge.net/project/showfiles.php?group_id=62034
I've downloaded ActivePerl and the needed modules from CPAN (nothing fancy; they're very easy to find). I've managed to install them, but when I run the script I get an error after it tells me that I've successfully logged in:
"Use of uninitialized value $cells in pattern match (m//) at yahoogroups_files.pl line 244, line 2."
I'm guessing that Yahoo changed the layout of the page or something, but I'm not able to update the script myself. I'm a newbie when it comes to Perl and understanding the way Yahoo generates the pages, I only know some basic C++. I want to mention that I'm not lazy, I'll try do fix it myself but I need your help: hints, advice, anything.
PS: I've contacted the author, but he isn't willing to update the scripts.
You would need knowledge in the following fields:
use of an html parser
http knowledge ( get/post/head )
web scraping
I suggest you focus on WWW::Mechanize since it's capable of all these things ( and more )
EDIT: another solution ( that doesn't need programming ) , is this: login with your browser on yahoo groups, store the cookie, and then run wget , passing the stored cookie as a parameter. This way you'll get the task accomplished very fast.
Find your browser's cookies.txt file on your harddrive, and then call wget like this ( if I remember the commands correctly ) :
wget --load-cookies path_to_cookie_file -r -w 60 website
The full man page can be found here
EDIT2: Another option is to use WebDriver to automate firefox. You can use this article as a guide on how to accomplish this.
By the filename I'm assuming you're using Yahoo Group archiver found here: http://sourceforge.net/projects/grabyahoogroup/
I ran the files script against the SubEthaEdit group and it works great. All of the files downloaded without incident.
Looking at the code it seems to barf while processing an html table in a while loop if $cells is empty.
Considering the code did work when I tested it it's possible there's something going on with the listing of that group's files. You'll want to try outputting $content and figure out where and why the regular expression on 243 isn't able to process that html.
EDIT: If you don't mind posting the group this is happening with I'm sure myself or someone else here can try it out and troubleshoot on their own. It's tough to pinpoint what's up when the issue can't be duplicated. Also, try the same group I did and see if it works out for you. Certainly something up with the group you're trying if that works.
Dunno if it will help you, but here's what I did to get the message-download working:
http://sourceforge.net/forum/forum.php?thread_id=3283915&forum_id=209170
(I only used message-download, I didn't look at file-download)
Was tinkering on this a while ago to backup my girlfriend's group messages and files from uni. Upon debugging on the latest scripts I've found out that there seems to be a bug on group_domain declaration (theres also a group declaration bug that i've found on yahoo2maildir.pl of the same project, see $request)
($group_domain) = $url =~ /\/\/(.*?groups.yahoo.com)\//;
in this case, i've overwritten the $request var under the function sub download_folder() with
from <br>
$request = GET "http://$group_domain/group/$group/files$sub_folder/";
<br> to <br>
$request = GET "http://**groups.yahoo.com/group/$user_group**/files$sub_folder/";
grabyahoogroup works well in the latest edition, which can be found at the svn repo:
http://grabyahoogroup.svn.sourceforge.net/viewvc/grabyahoogroup/trunk/yahoo_group/
The version at sourceforge.net/projects/grabyahoogroup/files/ HAS BUGS AND DID NOT WORK FOR ME.
I've been looking for a tool that collects messages/conversations from Yahoo Groups!. I finally found this tool that converts your Yahoo! Groups messages into MBOX format after struggling to try to make my own and searching everywhere on the internet.
Download tools
Both of the following are Google Chrome extensions.
Chrome Extension to Download Members posted by Sam Hobbs (2015).
Chrome Application To Download Messages posted by Mark Fletcher (Jan 2016).
Plain string to Base64 binary data
At some time past September 16, 2010 (at least for me), the messages retrieved are no longer plain text and instead Base 64 binary data (ASCII). Using this swiss converter tool can allow you to read the data as it is.
Sample content from the MBOX format
VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4=
Sample result after conversion
The quick brown fox jumps over the lazy dog.
for cause, as of 2019/09
https://github.com/csaftoiu/yahoo-groups-backup
.....