#!/usr/bin/env perl
use
open
":std"
,
":encoding(UTF-8)"
;
our
$VERSION
=
'v0.1.4'
;
$Getopt::Std::STANDARD_HELP_VERSION
= 1;
my
%options
= ();
my
$auth
;
my
$ua
= LWP::UserAgent->new;
sub
save_collection {
my
(
$items
) =
@_
;
my
$filename
;
foreach
my
$item
(@{
$items
}) {
if
(
$item
->{
"id"
}) {
$filename
=
$item
->{
"id"
};
$filename
=~
tr
/\//_/;
}
else
{
die
"id property undefined"
if
not
$_
->{
"id"
};
}
open
(
my
$fh
,
'>'
,
$filename
) or
die
"couldn't open"
,
$filename
;
print
$fh
encode_json(
$item
);
close
$fh
;
}
}
sub
apc2s_backup {
my
(
$url
) =
@_
;
my
$req
= HTTP::Request->new(
GET
=>
$url
);
$req
->header(
'Accept'
=>
'application/activity+json'
);
$req
->header(
'Authorization'
=>
$auth
);
my
$res
=
$ua
->request(
$req
);
if
(
$res
->is_success) {
print
"Got $url\n"
;
my
$content_type
=
$res
->header(
"Content-Type"
);
my
$content_match
= /application\/([^+]*+)?json(; .*)?/;
if
(
$content_type
=~
$content_match
) {
my
$response
= decode_json(
$res
->content);
if
(
$response
->{
"type"
} eq
"OrderedCollection"
) {
if
(not
$response
->{
"first"
}) {
die
"“first” property of OrderedCollection undefined"
;
}
print
"Fetching first property: "
,
$response
->{
"first"
},
"\n"
;
apc2s_backup(
$response
->{
"first"
});
}
elsif
(
$response
->{
"type"
} eq
"OrderedCollectionPage"
) {
if
(
$response
->{
"orderedItems"
}) {
save_collection(
$response
->{
"orderedItems"
});
print
"next: "
,
$response
->{
"next"
},
"\n"
if
$response
->{
"next"
};
print
"prev: "
,
$response
->{
"prev"
},
"\n"
if
$response
->{
"prev"
};
if
(
$response
->{
"next"
}) {
print
"Fetching next property\n"
;
apc2s_backup(
$response
->{
"next"
});
}
else
{
print
"No “next” property defined, done?\n"
;
}
}
else
{
die
"OrderedCollectionPage without “orderedItems” defined is unsupported"
;
}
}
elsif
(
$response
->{
"type"
} eq
"Person"
) {
if
(
$response
->{
"outbox"
}) {
print
"Fetching outbox property: "
,
$response
->{
"outbox"
},
"\n"
;
apc2s_backup(
$response
->{
"outbox"
});
}
else
{
die
"Person actor with no outbox"
;
}
}
else
{
die
"Unknown type: "
,
$response
->{
"type"
};
}
}
else
{
die
"Got "
,
$content_type
,
" instead of "
,
$content_match
;
}
}
else
{
die
"Got "
,
$res
->status_line,
" instead of 2xx"
;
}
}
getopts(
"u:o:"
, \
%options
);
if
(
$#ARGV
!= 0) {
print
"usage: ap-backup.pl <-u user:password|-o OAuth-Bearer-Token> <url>\n"
;
exit
1;
}
if
(
defined
$options
{u}) {
$auth
=
"Basic "
. encode_base64(
$options
{u});
}
if
(
defined
$options
{o}) {
$auth
=
"Bearer "
.
$options
{o};
}
print
"Authorization: $auth"
;
print
"Fetching: "
,
$ARGV
[0],
"\n"
;
apc2s_backup(
$ARGV
[0]);