Skip to content

Instantly share code, notes, and snippets.

@jbarber
Created April 4, 2011 17:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jbarber/902008 to your computer and use it in GitHub Desktop.
Save jbarber/902008 to your computer and use it in GitHub Desktop.
Dumping sharepoint lists from perl
#!/usr/bin/perl
# Script to retrieve a list from sharepoint, which contains
# /etc/hosts type information and dump it in hosts format
#
# It's recomended to enter the username on the command line and let it prompt
# for the password
#
# The column names for the list items are hard coded.
#
# Much shamelessly taken from "james":
# http://www.squish.net/log/2008/10/11/perl-sharepoint/
#
# As well as the use'd modules, this also requires Authen::NTLM
#
# MS documentation:
# http://msdn.microsoft.com/en-us/library/lists.lists.updatelistitems.aspx
use strict;
use warnings;
use Getopt::Long;
use URI;
use Term::ReadKey;
use LWP::Debug;
use LWP::UserAgent;
use Data::Dumper;
use SOAP::Lite on_action => sub { "$_[0]$_[1]"; };
import SOAP::Data 'name', 'value';
my ($sp_endpoint, $sp_listid, $sp_domain, $sp_username, $sp_password, $debug);
$debug = 0;
GetOptions(
"endpoint=s" => \$sp_endpoint,
"listid=s" => \$sp_listid,
"domain=s" => \$sp_domain,
"username=s" => \$sp_username,
"password=s" => \$sp_password,
"debug=s" => \$debug,
);
$sp_endpoint ||= 'http://host.your.domain.com/path/to/site/_vti_bin/lists.asmx';
$sp_domain ||= URI->new( $sp_endpoint )->host_port;
$sp_listid || die "--listid missing\n";
$|=1;
$sp_username ||= do {
print "Username (DOMAIN\\username): ";
ReadLine(0);
};
$sp_password ||= do {
print STDERR "Password: ";
ReadMode('noecho');
my $tmp = ReadLine(0);
chomp $tmp;
ReadMode('restore');
print STDERR "\n";
$tmp;
};
chomp $sp_username;
if ($debug) {
LWP::Debug::level('+');
SOAP::Lite->import(+trace => 'all');
}
my @ua_args = (keep_alive => 1);
my @credentials = ($sp_domain, "", $sp_username, $sp_password);
my $schema_ua = LWP::UserAgent->new(@ua_args);
$schema_ua->credentials(@credentials);
my $soap = SOAP::Lite->proxy($sp_endpoint, @ua_args, credentials => \@credentials);
$soap->schema->useragent($schema_ua);
$soap->uri("http://schemas.microsoft.com/sharepoint/soap/");
my $lists = $soap->GetListCollection();
die(1, $lists->faultstring()) if defined $lists->fault();
# Given a list $title and the list of lists ($lists) - return the $title list ID
sub lists_getid {
my ($title, $lists) = @_;
my @result = $lists->dataof('//GetListCollectionResult/Lists/List');
foreach my $data (@result) {
my $attr = $data->attr;
return $attr->{ID} if ($attr->{Title} eq $title);
}
return undef;
}
# Return all the items in a list
sub lists_getitems {
my $listid = shift;
my $in_listName = name('listName' => $listid);
my $in_viewName = name('viewName' => '');
my $in_rowLimit = name('rowLimit' => 99999);
my $call = $soap->GetListItems($in_listName, $in_viewName, $in_rowLimit);
die($call->faultstring()) if defined $call->fault();
return $call->dataof('//GetListItemsResult/listitems/data/row');
}
my $list_id = lists_getid($sp_listid, $lists);
my @items = lists_getitems($list_id);
# For all of the rows in the list, if the row has an IP (ows_HostIP) and a
# hostname (ows_LinkTitle) add it to our collection.
# One-to-many IP to hostnames are allowed
my $hosts = {};
foreach my $row (@items) {
my $attr = $row->attr;
next unless $attr->{ows_HostIP};
next unless defined $attr->{ows_LinkTitle};
push @{ $hosts->{ $attr->{ows_HostIP} } }, $attr->{ows_LinkTitle};
}
# Method for adding a host/IP to the list
sub add_ip {
my ($list, $hostname, $ip) = @_;
my $field_id = name('Field', 'New')->attr({ Name => 'ID'});
my $field_linktitle = name('Field', $hostname )->attr({ Name => 'Title'});
my $field_something = name('Field', $ip )->attr({ Name => 'HostIP'});
my $method = name('Method', [$field_id, $field_linktitle, $field_something])->attr({ ID => "anything", Cmd => 'New'});
my $batch = name('Batch', \$method);
my $in_listName = name('listName' => $list);
my $in_updates = name('updates' => \$batch);
my $call = $soap->UpdateListItems($in_listName, $in_updates);
die($call->faultstring()) if defined $call->fault();
}
# Method for updating a row in a list
sub alter_id {
my ($list, $itemid, $hostname, $ip) = @_;
# This is important, as it identifies what you're updating
my $field_id = name('Field', $itemid)->attr({ Name => 'ID'});
my $field_linktitle = name('Field', $hostname )->attr({ Name => 'Title'});
# The Cmd == Update bit is important
my $method = name('Method', [$field_id, $field_linktitle])->attr({ ID => "anything", Cmd => 'Update'});
my $batch = name('Batch', \$method);
my $in_listName = name('listName' => $list);
my $in_updates = name('updates' => \$batch);
my $call = $soap->UpdateListItems($in_listName, $in_updates);
die($call->faultstring()) if defined $call->fault();
}
# Actaully output the hosts records (sorted by IP)
for my $ip (map { $_->[0] } sort { $a->[1] cmp $b->[1] } map { [ $_, pack("C4", split /\./, $_) ] } keys %{ $hosts }) {
unless ( @{ $hosts->{$ip} } > 0 ) {
warn "No hosts for IP $ip\n";
}
else {
print $ip, " ", join(" ", @{ $hosts->{$ip} }), "\n";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment