our
$VERSION
=
'4.19.0'
;
our
@AS
=
qw(endpoint apikey username password)
;
__PACKAGE__->cgBuildAccessorsScalar(\
@AS
);
__PACKAGE__->cgBuildIndices;
use
JSON::XS
qw(encode_json decode_json)
;
sub
_ua (
$self
) {
my
$ua
= Mojo::UserAgent->new(
connect_timeout
=> 5,
max_response_size
=> 0,
inactivity_timeout
=> 0,
);
$ua
->transactor->name(
'Onyphe::Api-v'
.
$VERSION
);
$ua
->proxy->detect;
return
$ua
;
}
sub
_headers (
$self
,
$apikey
,
$ct
=
undef
) {
my
$headers
= {
'Authorization'
=>
'Bearer '
.
$apikey
,
'X-Api-Key'
=>
$apikey
,
'Content-Type'
=>
'application/json'
,
'Accept'
=>
'*/*'
,
};
if
(
defined
(
$ct
)) {
$headers
->{
'Content-Type'
} =
$ct
;
}
my
$global
=
$self
->config->{
''
};
my
$username
=
$global
->{api_unrated_email} ||
$self
->username;
if
(
$global
->{api_unrated_endpoint} &&
$username
) {
print
STDERR
"VERBOSE: Using Unrated API endpoint: "
.
$global
->{api_unrated_endpoint}.
", with username: $username\n"
if
$self
->verbose;
if
(!
defined
(
$username
) || !
defined
(
$apikey
)) {
print
STDERR
"ERROR: need api_unrated_email & api_key settings\n"
unless
$self
->silent;
return
;
}
$username
=~ s{\@}{_};
my
$auth
= b64_encode(
$username
.
':'
.
$apikey
,
''
);
$headers
->{Authorization} =
'Basic '
.
$auth
;
}
return
$headers
;
}
sub
get_total (
$self
,
$json
) {
my
$total
=
$json
->{total};
return
defined
(
$total
) &&
$total
?
$total
: 0;
}
sub
get_maxpage (
$self
,
$json
) {
my
$maxpage
=
$json
->{max_page};
return
defined
(
$maxpage
) &&
$maxpage
?
$maxpage
: 0;
}
sub
get_results (
$self
,
$json
) {
my
$results
=
$json
->{results};
return
defined
(
$results
) &&
@$results
?
$results
: [];
}
sub
encode (
$self
,
$result
) {
return
''
unless
$result
;
my
$encode
;
eval
{
$encode
= encode_json(
$result
);
};
if
($@) {
chomp
($@);
print
STDERR
"ERROR: encode failed: $@\n"
unless
$self
->silent;
return
''
;
}
return
$encode
;
}
sub
_cb_request (
$self
,
$results
=
undef
,
$cb_args
=
undef
) {
return
sub
(
$results
,
$cb_args
) {
$results
=
ref
(
$results
) eq
'ARRAY'
?
$results
: [
$results
];
for
(
@$results
) {
next
if
defined
(
$_
->{
'@category'
}) &&
$_
->{
'@category'
} eq
'none'
;
print
$self
->encode(
$_
).
"\n"
;
}
};
}
sub
_params (
$self
,
$params
) {
my
$first
= 1;
my
$args
=
''
;
for
my
$p
(
@$params
) {
my
$op
=
'?'
;
$op
=
'&'
unless
$first
;
$args
.=
$op
.
$p
->{k}.
'='
.
$p
->{v};
$first
= 0;
}
return
$args
;
}
sub
request (
$self
,
$api
,
$input
=
undef
,
$page
=
undef
,
$maxpage
=
undef
,
$params
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
my
$global
=
$self
->config->{
''
};
my
$endpoint
=
$global
->{api_unrated_endpoint} ||
$global
->{api_endpoint}
||
$self
->endpoint;
my
$apikey
=
$global
->{api_key} ||
$self
->apikey;
die
(
"FATAL: api_key not configured in ~/.onyphe.ini\n"
)
unless
defined
(
$apikey
);
die
(
"FATAL: api_endpoint not configured in ~/.onyphe.ini\n"
)
unless
defined
(
$endpoint
);
$cb
||=
$self
->_cb_request;
$page
||= 1;
$maxpage
||=
$global
->{api_maxpage} || 1;
my
$ua
=
$self
->_ua();
my
$headers
=
$self
->_headers(
$apikey
);
$api
=~ s{^/*}{/}g;
my
$this_max_page
;
while
(1) {
my
$path
=
$endpoint
.
$api
;
$path
.=
'/'
.url_escape(
$input
)
if
defined
$input
;
my
$p
= [];
push
@$p
, {
k
=>
'k'
,
v
=>
$apikey
};
push
@$p
, {
k
=>
'page'
,
v
=>
$page
}
if
defined
$page
;
push
@$p
, {
k
=>
'trackquery'
,
v
=>
'true'
}
if
$global
->{api_trackquery};
push
@$p
, {
k
=>
'calculated'
,
v
=>
'true'
}
if
$global
->{api_calculated};
push
@$p
, {
k
=>
'keepalive'
,
v
=>
'true'
}
if
$global
->{api_keepalive};
if
(
defined
(
$params
) &&
ref
(
$params
) eq
'HASH'
&&
keys
%$params
) {
for
my
$this
(
qw(size trackquery calculated keepalive)
) {
next
unless
defined
(
$params
->{
$this
}) ||
defined
(
$params
->{
'api_'
.
$this
});
push
@$p
, {
k
=>
$this
,
v
=>
$params
->{
$this
} ||
$global
->{
'api_'
.
$this
} };
}
}
my
$args
=
$self
->_params(
$p
);
$path
.=
$args
if
$args
;
my
$url
= Mojo::URL->new(
$path
);
print
STDERR
"VERBOSE: Calling API: $path\n"
if
$self
->verbose;
RETRY:
my
$res
;
eval
{
$res
=
$ua
->get(
$url
=>
$headers
)->result;
};
if
($@) {
chomp
($@);
print
STDERR
"WARNING: Request API call failed: [$@], retrying...\n"
unless
$self
->silent;
goto
RETRY;
}
unless
(
$res
->is_success) {
my
$code
=
$res
->code;
unless
(
defined
(
$res
->json)) {
my
$text
=
$res
->message;
print
STDERR
"ERROR: Request API call failed: $code, $text\n"
;
return
;
}
my
$json
=
$res
->json;
if
(
$code
== 429) {
print
STDERR
"WARNING: Too fast, sleeping before retry...\n"
unless
$self
->silent;
sleep
1;
goto
RETRY;
}
print
STDERR
"ERROR: Request API call failed: $code, "
.encode_json(
$json
).
"\n"
unless
$self
->silent;
return
;
}
my
$json
=
$res
->json;
if
(
defined
(
$params
) &&
$params
->{count}) {
my
$total
=
$self
->get_total(
$json
);
$cb
->([{
"total"
=>
$total
} ],
$cb_args
);
return
1;
}
$this_max_page
=
$self
->get_maxpage(
$json
)
unless
defined
$this_max_page
;
if
(
defined
(
$input
) && !
$this_max_page
) {
print
STDERR
"ERROR: Request API call failed, no max_page found\n"
unless
$self
->silent;
print
STDERR
"VERBOSE: "
.Data::Dumper::Dumper(
$json
).
"\n"
if
$self
->verbose;
return
;
}
my
$results
=
$self
->get_results(
$json
);
if
(
defined
(
$input
) && !
@$results
) {
print
STDERR
"ERROR: Request API call failed, no results found\n"
unless
$self
->silent;
print
STDERR
"VERBOSE: "
.Data::Dumper::Dumper(
$json
).
"\n"
if
$self
->verbose;
return
;
}
$cb
->(
$results
,
$cb_args
);
last
unless
(
defined
(
$page
) &&
defined
(
$maxpage
));
last
if
(
$page
==
$maxpage
||
$page
>=
$this_max_page
);
$page
++;
}
return
1;
}
sub
post_request (
$self
,
$api
,
$input
=
undef
,
$page
=
undef
,
$maxpage
=
undef
,
$params
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
my
$global
=
$self
->config->{
''
};
my
$endpoint
=
$global
->{api_unrated_endpoint} ||
$global
->{api_endpoint}
||
$self
->endpoint;
my
$apikey
=
$global
->{api_key} ||
$self
->apikey;
die
(
"FATAL: api_key not configured in ~/.onyphe.ini\n"
)
unless
defined
(
$apikey
);
die
(
"FATAL: api_endpoint not configured in ~/.onyphe.ini\n"
)
unless
defined
(
$endpoint
);
$cb
||=
$self
->_cb_request;
$page
||= 1;
$maxpage
||=
$global
->{api_maxpage} || 1;
my
$ua
=
$self
->_ua();
my
$headers
=
$self
->_headers(
$apikey
,
'application/x-www-form-urlencoded'
);
$api
=~ s{^/*}{/}g;
my
$this_max_page
;
while
(1) {
my
$path
=
$endpoint
.
$api
;
my
$p
= [];
push
@$p
, {
k
=>
'k'
,
v
=>
$apikey
};
push
@$p
, {
k
=>
'page'
,
v
=>
$page
}
if
defined
$page
;
push
@$p
, {
k
=>
'trackquery'
,
v
=>
'true'
}
if
$global
->{api_trackquery};
push
@$p
, {
k
=>
'calculated'
,
v
=>
'true'
}
if
$global
->{api_calculated};
push
@$p
, {
k
=>
'keepalive'
,
v
=>
'true'
}
if
$global
->{api_keepalive};
if
(
defined
(
$params
) &&
ref
(
$params
) eq
'HASH'
&&
keys
%$params
) {
for
my
$this
(
qw(size trackquery calculated keepalive)
) {
next
unless
defined
(
$params
->{
$this
}) ||
defined
(
$params
->{
'api_'
.
$this
});
push
@$p
, {
k
=>
$this
,
v
=>
$params
->{
$this
} ||
$global
->{
'api_'
.
$this
} };
}
}
my
$args
=
$self
->_params(
$p
);
$path
.=
$args
if
$args
;
my
$url
= Mojo::URL->new(
$path
);
print
STDERR
"VERBOSE: Calling API: $path\n"
if
$self
->verbose;
RETRY:
my
$res
;
eval
{
$res
=
$ua
->post(
$url
=>
$headers
=>
form
=> {
query
=>
$input
})->result;
};
if
($@) {
chomp
($@);
print
STDERR
"WARNING: Request API call failed: [$@], retrying...\n"
unless
$self
->silent;
goto
RETRY;
}
unless
(
$res
->is_success) {
my
$code
=
$res
->code;
unless
(
defined
(
$res
->json)) {
my
$text
=
$res
->message;
print
STDERR
"ERROR: Request API call failed: $code, $text\n"
;
return
;
}
my
$json
=
$res
->json;
if
(
$code
== 429) {
print
STDERR
"WARNING: Too fast, sleeping before retry...\n"
unless
$self
->silent;
sleep
1;
goto
RETRY;
}
print
STDERR
"ERROR: Request API call failed: $code, "
.encode_json(
$json
).
"\n"
unless
$self
->silent;
return
;
}
my
$json
=
$res
->json;
$this_max_page
=
$self
->get_maxpage(
$json
)
unless
defined
$this_max_page
;
if
(
defined
(
$input
) && !
$this_max_page
) {
print
STDERR
"ERROR: Request API call failed, no max_page found\n"
unless
$self
->silent;
print
STDERR
"VERBOSE: "
.Data::Dumper::Dumper(
$json
).
"\n"
if
$self
->verbose;
return
;
}
my
$results
=
$self
->get_results(
$json
);
if
(
defined
(
$input
) && !
@$results
) {
print
STDERR
"ERROR: Request API call failed, no results found\n"
unless
$self
->silent;
print
STDERR
"VERBOSE: "
.Data::Dumper::Dumper(
$json
).
"\n"
if
$self
->verbose;
return
;
}
$cb
->(
$results
,
$cb_args
);
last
unless
(
defined
(
$page
) &&
defined
(
$maxpage
));
last
if
(
$page
==
$maxpage
||
$page
>=
$this_max_page
);
$page
++;
}
return
1;
}
sub
user (
$self
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
$self
->request(
'/user'
,
undef
,
undef
,
undef
,
undef
,
$cb
,
$cb_args
);
}
sub
summary (
$self
,
$api
,
$oql
,
$params
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
$self
->request(
'/summary/'
.
$api
,
$oql
,
undef
,
undef
,
$params
,
$cb
,
$cb_args
);
}
sub
simple (
$self
,
$api
,
$oql
,
$params
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
$self
->request(
'/simple/'
.
$api
,
$oql
,
undef
,
undef
,
$params
,
$cb
,
$cb_args
);
}
sub
simple_best (
$self
,
$api
,
$oql
,
$params
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
$self
->request(
'/simple/'
.
$api
.
'/best'
,
$oql
,
undef
,
undef
,
$params
,
$cb
,
$cb_args
);
}
sub
search (
$self
,
$oql
,
$page
= 1,
$maxpage
= 1,
$params
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
$self
->request(
'/search'
,
$oql
,
$page
,
$maxpage
,
$params
,
$cb
,
$cb_args
);
}
sub
post_search (
$self
,
$oql
,
$page
= 1,
$maxpage
= 1,
$params
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
$self
->post_request(
'/search'
,
$oql
,
$page
,
$maxpage
,
$params
,
$cb
,
$cb_args
);
}
sub
_cb_stream (
$self
,
$results
=
undef
,
$cb_args
=
undef
) {
return
sub
(
$results
,
$cb_args
) {
$results
=
ref
(
$results
) eq
'ARRAY'
?
$results
: [
$results
];
for
(
@$results
) {
next
if
m{.\
@category
.\s*:\s*.none.};
print
"$_\n"
;
}
};
}
sub
_on_read (
$self
,
$cb
=
undef
,
$cb_args
=
undef
,
$buf
= \
''
) {
return
sub
{
my
(
$content
,
$bytes
) =
@_
;
$bytes
=
$$buf
.
$bytes
;
my
(
$this
,
$tail
) =
$bytes
=~ m/^(.*\n)(.*)$/s;
if
(
defined
(
$bytes
) &&
$bytes
=~ m{
"status"
:
"nok"
}) {
return
$cb
->(
$bytes
,
$cb_args
);
}
if
(!
defined
(
$this
)) {
$buf
= \
$bytes
;
}
else
{
$buf
=
defined
(
$tail
) ? \
$tail
: \
''
;
my
$results
= [
split
(/\n/,
$this
) ];
return
$cb
->(
$results
,
$cb_args
);
}
};
}
sub
stream (
$self
,
$method
,
$api
,
$input
,
$params
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
my
$global
=
$self
->config->{
''
};
my
$endpoint
=
$global
->{api_unrated_endpoint} ||
$global
->{api_endpoint}
||
$self
->endpoint;
my
$apikey
=
$global
->{api_key} ||
$self
->apikey;
die
(
"FATAL: api_key not configured in ~/.onyphe.ini\n"
)
unless
defined
(
$apikey
);
die
(
"FATAL: api_endpoint not configured in ~/.onyphe.ini\n"
)
unless
defined
(
$endpoint
);
$cb
||=
$self
->_cb_stream;
my
$ua
=
$self
->_ua();
my
$headers
=
$self
->_headers(
$apikey
);
if
(
$method
eq
'POST'
) {
$headers
=
$self
->_headers(
$apikey
,
'application/x-www-form-urlencoded'
);
}
my
$path
=
$endpoint
.
$api
;
unless
(-f
$input
) {
if
(
$method
eq
'GET'
) {
$path
.=
'/'
.url_escape(
$input
);
}
}
my
$p
= [];
push
@$p
, {
k
=>
'k'
,
v
=>
$apikey
};
push
@$p
, {
k
=>
'trackquery'
,
v
=>
'true'
}
if
$global
->{api_trackquery};
push
@$p
, {
k
=>
'calculated'
,
v
=>
'true'
}
if
$global
->{api_calculated};
push
@$p
, {
k
=>
'keepalive'
,
v
=>
'true'
}
if
$global
->{api_keepalive};
if
(
defined
(
$params
) &&
ref
(
$params
) eq
'HASH'
&&
keys
%$params
) {
for
my
$this
(
qw(size trackquery calculated keepalive)
) {
next
unless
defined
(
$params
->{
$this
}) ||
defined
(
$params
->{
'api_'
.
$this
});
push
@$p
, {
k
=>
$this
,
v
=>
$params
->{
$this
} ||
$global
->{
'api_'
.
$this
} };
}
}
my
$args
=
$self
->_params(
$p
);
$path
.=
$args
if
$args
;
print
STDERR
"VERBOSE: Calling API: $path\n"
if
$self
->verbose;
my
$url
= Mojo::URL->new(
$path
);
my
$buf
=
''
;
my
$tx
;
if
(
$method
eq
'GET'
) {
$tx
=
$ua
->build_tx(
$method
=>
$url
=>
$headers
);
}
elsif
(
$method
eq
'POST'
) {
$tx
=
$ua
->build_tx(
$method
=>
$url
=>
$headers
=>
form
=> {
query
=>
$input
});
}
$tx
->res->content->unsubscribe(
'read'
)->on(
read
=>
$self
->_on_read(
$cb
,
$cb_args
, \
$buf
));
if
(-f
$input
) {
print
STDERR
"VERBOSE: Reading file: $input\n"
if
$self
->verbose;
$tx
->req->content->asset(Mojo::Asset::File->new(
path
=>
$input
));
}
return
$ua
->start(
$tx
);
}
sub
post_stream (
$self
,
$method
,
$api
,
$input
,
$params
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
my
$global
=
$self
->config->{
''
};
my
$endpoint
=
$global
->{api_unrated_endpoint} ||
$global
->{api_endpoint}
||
$self
->endpoint;
my
$apikey
=
$global
->{api_key} ||
$self
->apikey;
die
(
"FATAL: api_key not configured in ~/.onyphe.ini\n"
)
unless
defined
(
$apikey
);
die
(
"FATAL: api_endpoint not configured in ~/.onyphe.ini\n"
)
unless
defined
(
$endpoint
);
$cb
||=
$self
->_cb_stream;
my
$ua
=
$self
->_ua();
my
$headers
=
$self
->_headers(
$apikey
,
'application/x-www-form-urlencoded'
);
my
$path
=
$endpoint
.
$api
;
my
$p
= [];
push
@$p
, {
k
=>
'k'
,
v
=>
$apikey
};
push
@$p
, {
k
=>
'trackquery'
,
v
=>
'true'
}
if
$global
->{api_trackquery};
push
@$p
, {
k
=>
'calculated'
,
v
=>
'true'
}
if
$global
->{api_calculated};
push
@$p
, {
k
=>
'keepalive'
,
v
=>
'true'
}
if
$global
->{api_keepalive};
if
(
defined
(
$params
) &&
ref
(
$params
) eq
'HASH'
&&
keys
%$params
) {
for
my
$this
(
qw(size trackquery calculated keepalive)
) {
next
unless
defined
(
$params
->{
$this
}) ||
defined
(
$params
->{
'api_'
.
$this
});
push
@$p
, {
k
=>
$this
,
v
=>
$params
->{
$this
} ||
$global
->{
'api_'
.
$this
} };
}
}
my
$args
=
$self
->_params(
$p
);
$path
.=
$args
if
$args
;
print
STDERR
"VERBOSE: Calling API: $path\n"
if
$self
->verbose;
my
$url
= Mojo::URL->new(
$path
);
my
$buf
=
''
;
my
$tx
=
$ua
->build_tx(
$method
=>
$url
=>
$headers
=>
form
=> {
query
=>
$input
});
$tx
->res->content->unsubscribe(
'read'
)->on(
read
=>
$self
->_on_read(
$cb
,
$cb_args
, \
$buf
));
if
(-f
$input
) {
print
STDERR
"VERBOSE: Reading file: $input\n"
if
$self
->verbose;
$tx
->req->content->asset(Mojo::Asset::File->new(
path
=>
$input
));
}
return
$ua
->start(
$tx
);
}
sub
_check_file (
$self
,
$file
) {
unless
(-f
$file
) {
print
STDERR
"ERROR: file not found: $file\n"
unless
$self
->silent;
return
;
}
return
$file
;
}
sub
bulk_summary (
$self
,
$api
,
$file
,
$params
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
unless
$self
->_check_file(
$file
);
$api
=~ s{^/*}{/}g;
return
$self
->stream(
'POST'
,
'/bulk/summary'
.
$api
,
$file
,
$params
,
$cb
,
$cb_args
);
}
sub
bulk_simple (
$self
,
$api
,
$file
,
$params
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
unless
$self
->_check_file(
$file
);
$api
=~ s{^/*}{/}g;
return
$self
->stream(
'POST'
,
'/bulk/simple'
.
$api
.
'/ip'
,
$file
,
$params
,
$cb
,
$cb_args
);
}
sub
bulk_simple_best (
$self
,
$api
,
$file
,
$params
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
unless
$self
->_check_file(
$file
);
$api
=~ s{^/*}{/}g;
return
$self
->stream(
'POST'
,
'/bulk/simple'
.
$api
.
'/best/ip'
,
$file
,
$params
,
$cb
,
$cb_args
);
}
sub
bulk_discovery (
$self
,
$api
,
$file
,
$oql
=
undef
,
$params
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
unless
$self
->_check_file(
$file
);
$api
=~ s{^/*}{/}g;
my
$input
=
$file
;
my
(
$fh
,
$filename
);
if
(
defined
(
$oql
)) {
my
@lines
= read_file(
$file
);
(
$fh
,
$filename
) = tempfile();
$input
=
$filename
;
for
(
@lines
) {
chomp
;
my
$line
=
"$_ $oql"
;
print
$fh
"$line\n"
;
}
close
(
$fh
);
}
$self
->stream(
'POST'
,
'/bulk/discovery'
.
$api
.
'/asset'
,
$input
,
$params
,
$cb
,
$cb_args
);
unlink
(
$filename
)
if
defined
(
$filename
) && -f
$filename
;
return
1;
}
sub
export (
$self
,
$oql
,
$params
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
$self
->stream(
'GET'
,
'/export'
,
$oql
,
$params
,
$cb
,
$cb_args
);
}
sub
post_export (
$self
,
$oql
,
$params
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
$self
->stream(
'POST'
,
'/export'
,
$oql
,
$params
,
$cb
,
$cb_args
);
}
sub
_cb_alert (
$self
,
$results
=
undef
,
$cb_args
=
undef
) {
return
sub
(
$results
,
$cb_args
) {
$results
=
ref
(
$results
) eq
'ARRAY'
?
$results
: [
$results
];
for
(
@$results
) {
print
$self
->encode(
$_
).
"\n"
;
}
};
}
sub
alert (
$self
,
$method
,
$api
,
$name
,
$oql
,
$email
,
$threshold
= 0,
$cb
=
undef
,
$cb_args
=
undef
) {
my
$global
=
$self
->config->{
''
};
my
$endpoint
=
$global
->{api_unrated_endpoint} ||
$global
->{api_endpoint}
||
$self
->endpoint;
my
$apikey
=
$global
->{api_key} ||
$self
->apikey;
die
(
"FATAL: api_key not configured in ~/.onyphe.ini\n"
)
unless
defined
(
$apikey
);
die
(
"FATAL: api_endpoint not configured in ~/.onyphe.ini\n"
)
unless
defined
(
$endpoint
);
$cb
||=
$self
->_cb_alert;
my
$ua
=
$self
->_ua();
my
$headers
=
$self
->_headers(
$apikey
);
$api
=~ s{^/*}{/}g;
my
$path
=
$endpoint
.
$api
;
$path
.=
'?k='
.
$apikey
;
print
STDERR
"VERBOSE: Calling API: $path\n"
if
$self
->verbose;
my
$url
= Mojo::URL->new(
$path
);
my
$post
;
$post
->{name} =
$name
if
defined
$name
;
$post
->{query} =
$oql
if
defined
$oql
;
$post
->{email} =
$email
if
defined
$email
;
$post
->{threshold} =
$threshold
if
defined
$threshold
;
my
@args
= (
$url
=>
$headers
);
@args
= (
$url
=>
$headers
=>
json
=>
$post
)
if
defined
$post
;
RETRY:
my
$res
;
eval
{
$res
=
$ua
->
$method
(
@args
)->result;
};
if
($@) {
chomp
($@);
print
STDERR
"WARNING: Alert API call failed: [$@], retrying...\n"
unless
$self
->silent;
goto
RETRY;
}
unless
(
$res
->is_success) {
my
$code
=
$res
->code;
unless
(
defined
(
$res
->json)) {
my
$text
=
$res
->message;
print
STDERR
"ERROR: Alert API call failed: $code, $text\n"
;
return
;
}
my
$json
=
$res
->json;
if
(
$code
== 429) {
print
STDERR
"WARNING: Too fast, sleeping before retry...\n"
unless
$self
->silent;
sleep
1;
goto
RETRY;
}
print
STDERR
"ERROR: Alert API call failed: $code, "
.encode_json(
$json
).
"\n"
unless
$self
->silent;
return
;
}
my
$json
=
$res
->json;
$cb
->(
$json
,
$cb_args
);
return
1;
}
sub
alert_list (
$self
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
$self
->alert(
'get'
,
'/alert/list'
,
undef
,
undef
,
undef
,
undef
,
$cb
,
$cb_args
);
}
sub
alert_add (
$self
,
$name
,
$oql
,
$email
,
$threshold
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
if
(
$self
->verbose) {
print
STDERR
"VERBOSE: name: [$name]\n"
;
print
STDERR
"VERBOSE: oql: [$oql]\n"
;
print
STDERR
"VERBOSE: email: [$email]\n"
;
print
STDERR
"VERBOSE: threshold: [$threshold]\n"
if
defined
$threshold
;
}
return
$self
->alert(
'post'
,
'/alert/add'
,
$name
,
$oql
,
$email
,
$threshold
,
$cb
,
$cb_args
);
}
sub
alert_del (
$self
,
$id
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
$self
->alert(
'post'
,
'/alert/del/'
.
$id
,
undef
,
undef
,
undef
,
undef
,
$cb
,
$cb_args
);
}
sub
_cb_ondemand (
$self
,
$results
=
undef
,
$cb_args
=
undef
) {
return
sub
(
$results
,
$cb_args
) {
$results
=
ref
(
$results
) eq
'ARRAY'
?
$results
: [
$results
];
for
(
@$results
) {
print
$self
->encode(
$_
).
"\n"
;
}
};
}
sub
ondemand (
$self
,
$method
,
$api
,
$param
,
$post
,
$cb
=
undef
,
$cb_args
=
undef
) {
my
$global
=
$self
->config->{
''
};
my
$endpoint
=
$global
->{api_ondemand_endpoint} ||
$self
->endpoint;
my
$apikey
=
$global
->{api_ondemand_key} ||
$self
->apikey;
die
(
"FATAL: api_ondemand_key not configured in ~/.onyphe.ini\n"
)
unless
defined
(
$apikey
);
die
(
"FATAL: api_ondemand_endpoint not configured in ~/.onyphe.ini\n"
)
unless
defined
(
$endpoint
);
$cb
||=
$self
->_cb_ondemand;
my
$ua
=
$self
->_ua();
my
$headers
=
$self
->_headers(
$apikey
);
$api
=~ s{^/*}{/}g;
my
$path
=
$endpoint
.
$api
;
$path
.=
'?k='
.
$apikey
;
if
(
defined
(
$param
)) {
$post
->{maxscantime} =
$param
->{maxscantime}
if
defined
$param
->{maxscantime};
$post
->{aslines} =
$param
->{aslines} ?
'true'
:
'false'
if
defined
$param
->{aslines};
$post
->{aslink} =
$param
->{aslink} ?
'true'
:
'false'
if
defined
$param
->{aslink};
$post
->{full} =
$param
->{full} ?
'true'
:
'false'
if
defined
$param
->{full};
$post
->{urlscan} =
$param
->{urlscan} ?
'true'
:
'false'
if
defined
$param
->{urlscan};
$post
->{vulnscan} =
$param
->{vulnscan} ?
'true'
:
'false'
if
defined
$param
->{vulnscan};
$post
->{riskscan} =
$param
->{riskscan} ?
'true'
:
'false'
if
defined
$param
->{riskscan};
$post
->{asm} =
$param
->{asm} ?
'true'
:
'false'
if
defined
$param
->{asm};
$post
->{
import
} =
$param
->{
import
} ?
'true'
:
'false'
if
defined
$param
->{
import
};
$post
->{ports} =
$param
->{ports}
if
defined
$param
->{ports};
}
print
STDERR
"VERBOSE: Calling API: $path\n"
if
$self
->verbose;
my
$url
= Mojo::URL->new(
$path
);
my
@args
= (
$url
=>
$headers
);
@args
= (
$url
=>
$headers
=>
json
=>
$post
)
if
defined
$post
;
RETRY:
my
$res
;
eval
{
$res
=
$ua
->
$method
(
@args
)->result;
};
if
($@) {
chomp
($@);
print
STDERR
"WARNING: Ondemand API call failed: [$@], retrying...\n"
unless
$self
->silent;
goto
RETRY;
}
unless
(
$res
->is_success) {
my
$code
=
$res
->code;
unless
(
defined
(
$res
->json)) {
my
$text
=
$res
->message;
print
STDERR
"ERROR: Request API call failed: $code, $text\n"
;
return
;
}
my
$json
=
$res
->json;
if
(
$code
== 429) {
print
STDERR
"WARNING: Too fast, sleeping before retry...\n"
unless
$self
->silent;
sleep
1;
goto
RETRY;
}
print
STDERR
"ERROR: Ondemand API call failed: $code, "
.encode_json(
$json
).
"\n"
unless
$self
->silent;
return
;
}
my
$data
;
if
(
defined
(
$param
) &&
$param
->{aslines}) {
my
@lines
=
split
(/\r?\n/,
$res
->body);
$data
= \
@lines
;
}
else
{
$data
=
$res
->json;
}
$cb
->(
$data
,
$cb_args
);
return
1;
}
sub
ondemand_scope_ip (
$self
,
$target
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
$self
->ondemand(
'post'
,
'/ondemand/scope/ip/single'
,
$param
, {
ip
=>
$target
},
$cb
,
$cb_args
);
}
sub
ondemand_scope_port (
$self
,
$target
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
$self
->ondemand(
'post'
,
'/ondemand/scope/port/single'
,
$param
, {
port
=>
$target
},
$cb
,
$cb_args
);
}
sub
ondemand_scope_domain (
$self
,
$target
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
$self
->ondemand(
'post'
,
'/ondemand/scope/domain/single'
,
$param
, {
domain
=>
$target
},
$cb
,
$cb_args
);
}
sub
ondemand_scope_hostname (
$self
,
$target
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
$self
->ondemand(
'post'
,
'/ondemand/scope/hostname/single'
,
$param
, {
hostname
=>
$target
},
$cb
,
$cb_args
);
}
sub
ondemand_scope_ip_bulk (
$self
,
$file
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
if
(! -f
$file
) {
print
STDERR
"ERROR: Ondemand Scope Ip Bulk needs a file as input\n"
unless
$self
->silent;
}
my
@lines
= read_file(
$file
);
for
(
@lines
) {
chomp
};
unless
(
@lines
) {
print
STDERR
"ERROR: Ondemand Scope Ip Bulk needs a file with content\n"
unless
$self
->silent;
}
my
$target
=
join
(
','
,
@lines
);
return
$self
->ondemand(
'post'
,
'/ondemand/scope/ip/bulk'
,
$param
, {
ip
=>
$target
},
$cb
,
$cb_args
);
}
sub
ondemand_scope_domain_bulk (
$self
,
$file
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
if
(! -f
$file
) {
print
STDERR
"ERROR: Ondemand Scope Domain Bulk needs a file as input\n"
unless
$self
->silent;
}
my
@lines
= read_file(
$file
);
for
(
@lines
) {
chomp
};
unless
(
@lines
) {
print
STDERR
"ERROR: Ondemand Scope Domain Bulk needs a file with content\n"
unless
$self
->silent;
}
my
$target
=
join
(
','
,
@lines
);
return
$self
->ondemand(
'post'
,
'/ondemand/scope/domain/bulk'
,
$param
, {
domain
=>
$target
},
$cb
,
$cb_args
);
}
sub
ondemand_scope_hostname_bulk (
$self
,
$file
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
if
(! -f
$file
) {
print
STDERR
"ERROR: Ondemand Scope Hostname Bulk needs a file as input\n"
unless
$self
->silent;
}
my
@lines
= read_file(
$file
);
for
(
@lines
) {
chomp
};
unless
(
@lines
) {
print
STDERR
"ERROR: Ondemand Scope Hostname Bulk needs a file with content\n"
unless
$self
->silent;
}
my
$target
=
join
(
','
,
@lines
);
return
$self
->ondemand(
'post'
,
'/ondemand/scope/hostname/bulk'
,
$param
, {
hostname
=>
$target
},
$cb
,
$cb_args
);
}
sub
ondemand_scope_result (
$self
,
$scan_id
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
$self
->ondemand(
'get'
,
'/ondemand/scope/result/'
.
$scan_id
,
$param
,
undef
,
$cb
,
$cb_args
);
}
sub
ondemand_resolver_ip (
$self
,
$target
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
$self
->ondemand(
'post'
,
'/ondemand/resolver/ip/single'
,
$param
, {
ip
=>
$target
},
$cb
,
$cb_args
);
}
sub
ondemand_resolver_domain (
$self
,
$target
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
$self
->ondemand(
'post'
,
'/ondemand/resolver/domain/single'
,
$param
, {
domain
=>
$target
},
$cb
,
$cb_args
);
}
sub
ondemand_resolver_domain_bulk (
$self
,
$file
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
if
(! -f
$file
) {
print
STDERR
"ERROR: Ondemand Resolver Domain Bulk needs a file as input\n"
unless
$self
->silent;
}
my
@lines
= read_file(
$file
);
for
(
@lines
) {
chomp
};
unless
(
@lines
) {
print
STDERR
"ERROR: Ondemand Resolver Domain Bulk needs a file with content\n"
unless
$self
->silent;
}
my
$target
=
join
(
','
,
@lines
);
return
$self
->ondemand(
'post'
,
'/ondemand/resolver/domain/bulk'
,
$param
, {
domain
=>
$target
},
$cb
,
$cb_args
);
}
sub
ondemand_resolver_hostname (
$self
,
$target
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
$self
->ondemand(
'post'
,
'/ondemand/resolver/hostname/single'
,
$param
, {
hostname
=>
$target
},
$cb
,
$cb_args
);
}
sub
ondemand_resolver_result (
$self
,
$scan_id
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
$self
->ondemand(
'get'
,
'/ondemand/resolver/result/'
.
$scan_id
,
$param
,
undef
,
$cb
,
$cb_args
);
}
sub
_cb_asd (
$self
,
$results
=
undef
,
$cb_args
=
undef
) {
return
sub
(
$results
,
$cb_args
) {
$results
=
ref
(
$results
) eq
'ARRAY'
?
$results
: [
$results
];
for
(
@$results
) {
print
$self
->encode(
$_
).
"\n"
;
}
};
}
sub
asd (
$self
,
$method
,
$api
,
$param
,
$post
,
$cb
=
undef
,
$cb_args
=
undef
) {
my
$global
=
$self
->config->{
''
};
my
$endpoint
=
$global
->{api_asd_endpoint} ||
$self
->endpoint;
my
$apikey
=
$global
->{api_asd_key} ||
$self
->apikey;
die
(
"FATAL: api_asd_key not configured in ~/.onyphe.ini\n"
)
unless
defined
(
$apikey
);
die
(
"FATAL: api_asd_endpoint not configured in ~/.onyphe.ini\n"
)
unless
defined
(
$endpoint
);
$cb
||=
$self
->_cb_asd;
my
$ua
=
$self
->_ua();
my
$headers
=
$self
->_headers(
$apikey
);
$api
=~ s{^/*}{/}g;
my
$path
=
$endpoint
.
$api
;
$path
.=
'?k='
.
$apikey
;
if
(
defined
(
$param
)) {
$post
->{domain} =
$param
->{domain}
if
defined
$param
->{domain};
$post
->{aslines} =
$param
->{aslines} ?
'true'
:
'false'
if
defined
$param
->{aslines};
$post
->{astask} =
$param
->{astask} ?
'true'
:
'false'
if
defined
$param
->{astask};
$post
->{trusted} =
$param
->{trusted} ?
'true'
:
'false'
if
defined
$param
->{trusted};
$post
->{field} =
$param
->{field}
if
defined
$param
->{field};
$post
->{query} =
$param
->{query}
if
defined
$param
->{query};
$post
->{includep} =
$self
->_load_file(
$param
->{includep})
if
defined
(
$param
->{includep});
$post
->{excludep} =
$self
->_load_file(
$param
->{excludep})
if
defined
(
$param
->{excludep});
}
print
STDERR
"VERBOSE: Calling API: $path\n"
if
$self
->verbose;
print
STDERR
"VERBOSE: Calling API with content: "
.Data::Dumper::Dumper(
$post
).
"\n"
if
$self
->verbose;
my
$url
= Mojo::URL->new(
$path
);
my
@args
= (
$url
=>
$headers
);
@args
= (
$url
=>
$headers
=>
json
=>
$post
)
if
defined
$post
;
RETRY:
my
$res
;
eval
{
$res
=
$ua
->
$method
(
@args
)->result;
};
if
($@) {
chomp
($@);
if
($@ =~ m{Premature connection
close
}i) {
return
1;
}
print
STDERR
"WARNING: ASD API call failed: [$@], retrying...\n"
unless
$self
->silent;
goto
RETRY;
}
unless
(
$res
->is_success) {
my
$code
=
$res
->code;
unless
(
defined
(
$res
->json)) {
my
$text
=
$res
->message;
print
STDERR
"ERROR: ASD API call failed: $code, $text\n"
;
return
;
}
my
$json
=
$res
->json;
if
(
$code
== 429) {
print
STDERR
"WARNING: Too fast, sleeping before retry...\n"
unless
$self
->silent;
sleep
1;
goto
RETRY;
}
print
STDERR
"ERROR: ASD API call failed: $code, "
.encode_json(
$json
).
"\n"
unless
$self
->silent;
return
;
}
my
$data
;
if
(
defined
(
$param
) &&
$param
->{aslines}) {
my
@lines
=
split
(/\r?\n/,
$res
->body);
$data
= \
@lines
;
}
else
{
$data
=
$res
->json;
}
$cb
->(
$data
,
$cb_args
);
return
1;
}
sub
_load_file (
$self
,
$arg
) {
if
(-f
$arg
) {
my
$docs
=
$self
->asd_load_input(
$arg
);
unless
(
defined
(
$docs
) &&
@$docs
) {
print
STDERR
"VERBOSE: asd_load_input: failed from bad content or empty content\n"
;
return
;
}
$arg
=
$docs
;
}
else
{
$arg
= [
split
(
','
,
$arg
) ];
}
return
$arg
;
}
sub
_arg_from_field (
$self
,
$arg
,
$field
) {
return
$arg
if
ref
(
$arg
) eq
'ARRAY'
&& !
ref
(
$arg
->[0]);
my
$values
= [];
for
(
@$arg
) {
next
unless
defined
(
$_
->{
$field
});
push
@$values
,
$_
->{
$field
};
}
return
$values
;
}
sub
asd_pivot_query (
$self
,
$arg
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
$self
->asd(
'post'
,
'/asd/pivot/query'
,
$param
, {
query
=>
$arg
},
$cb
,
$cb_args
);
}
sub
asd_domain_tld (
$self
,
$arg
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
$arg
=
$self
->_load_file(
$arg
);
$arg
=
$self
->_arg_from_field(
$arg
,
'domain'
);
return
$self
->asd(
'post'
,
'/asd/domain/tld'
,
$param
, {
domain
=>
$arg
},
$cb
,
$cb_args
);
}
sub
asd_dns_domain_ns (
$self
,
$arg
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
$arg
=
$self
->_load_file(
$arg
);
$arg
=
$self
->_arg_from_field(
$arg
,
'domain'
);
return
$self
->asd(
'post'
,
'/asd/dns/domain/ns'
,
$param
, {
domain
=>
$arg
},
$cb
,
$cb_args
);
}
sub
asd_dns_domain_mx (
$self
,
$arg
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
$arg
=
$self
->_load_file(
$arg
);
$arg
=
$self
->_arg_from_field(
$arg
,
'domain'
);
return
$self
->asd(
'post'
,
'/asd/dns/domain/mx'
,
$param
, {
domain
=>
$arg
},
$cb
,
$cb_args
);
}
sub
asd_certso_domain (
$self
,
$arg
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
$arg
=
$self
->_load_file(
$arg
);
$arg
=
$self
->_arg_from_field(
$arg
,
'domain'
);
return
$self
->asd(
'post'
,
'/asd/certso/domain'
,
$param
, {
domain
=>
$arg
},
$cb
,
$cb_args
);
}
sub
asd_certso_wildcard (
$self
,
$arg
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
$arg
=
$self
->_load_file(
$arg
);
$arg
=
$self
->_arg_from_field(
$arg
,
'subject.organization'
);
return
$self
->asd(
'post'
,
'/asd/certso/wildcard'
,
$param
, {
certso
=>
$arg
},
$cb
,
$cb_args
);
}
sub
_arg_from_inventory (
$self
,
$arg
,
$default
) {
return
{
$default
=>
$arg
}
if
ref
(
$arg
) eq
'ARRAY'
&& !
ref
(
$arg
->[0]);
my
$values
= {};
for
my
$doc
(
@$arg
) {
for
my
$field
(
keys
%$doc
) {
next
unless
defined
(
$doc
->{
$field
});
push
@{
$values
->{
$field
}},
$doc
->{
$field
};
}
}
return
$values
;
}
sub
asd_org_inventory (
$self
,
$arg
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
$arg
=
$self
->_load_file(
$arg
);
$arg
=
$self
->_arg_from_inventory(
$arg
,
'domain'
);
return
$self
->asd(
'post'
,
'/asd/org/inventory'
,
$param
, {
inventory
=>
$arg
},
$cb
,
$cb_args
);
}
sub
asd_ip_inventory (
$self
,
$arg
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
$arg
=
$self
->_load_file(
$arg
);
$arg
=
$self
->_arg_from_inventory(
$arg
,
'domain'
);
return
$self
->asd(
'post'
,
'/asd/ip/inventory'
,
$param
, {
inventory
=>
$arg
},
$cb
,
$cb_args
);
}
sub
asd_subnet_inventory (
$self
,
$arg
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
$arg
=
$self
->_load_file(
$arg
);
$arg
=
$self
->_arg_from_inventory(
$arg
,
'domain'
);
return
$self
->asd(
'post'
,
'/asd/subnet/inventory'
,
$param
, {
inventory
=>
$arg
},
$cb
,
$cb_args
);
}
sub
asd_vhost_inventory (
$self
,
$arg
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
$arg
=
$self
->_load_file(
$arg
);
$arg
=
$self
->_arg_from_inventory(
$arg
,
'domain'
);
return
$self
->asd(
'post'
,
'/asd/vhost/inventory'
,
$param
, {
inventory
=>
$arg
},
$cb
,
$cb_args
);
}
sub
asd_score_inventory (
$self
,
$arg
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
$arg
=
$self
->_load_file(
$arg
);
$arg
=
$self
->_arg_from_inventory(
$arg
,
'domain'
);
return
$self
->asd(
'post'
,
'/asd/score/inventory'
,
$param
, {
inventory
=>
$arg
},
$cb
,
$cb_args
);
}
sub
asd_dns_domain_soa (
$self
,
$arg
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
$arg
=
$self
->_load_file(
$arg
);
$arg
=
$self
->_arg_from_field(
$arg
,
'domain'
);
return
$self
->asd(
'post'
,
'/asd/dns/domain/soa'
,
$param
, {
domain
=>
$arg
},
$cb
,
$cb_args
);
}
sub
asd_domain_wildcard (
$self
,
$arg
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
$arg
=
$self
->_load_file(
$arg
);
$arg
=
$self
->_arg_from_field(
$arg
,
'domain'
);
return
$self
->asd(
'post'
,
'/asd/domain/wildcard'
,
$param
, {
domain
=>
$arg
},
$cb
,
$cb_args
);
}
sub
asd_domain_certso (
$self
,
$arg
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
$arg
=
$self
->_load_file(
$arg
);
$arg
=
$self
->_arg_from_field(
$arg
,
'subject.organization'
);
return
$self
->asd(
'post'
,
'/asd/domain/certso'
,
$param
, {
certso
=>
$arg
},
$cb
,
$cb_args
);
}
sub
asd_dns_domain_exist (
$self
,
$arg
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
$arg
=
$self
->_load_file(
$arg
);
$arg
=
$self
->_arg_from_field(
$arg
,
'domain'
);
return
$self
->asd(
'post'
,
'/asd/dns/domain/exist'
,
$param
, {
domain
=>
$arg
},
$cb
,
$cb_args
);
}
sub
asd_task_id (
$self
,
$taskid
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
$self
->asd(
'get'
,
'/asd/task/id/'
.
$taskid
,
$param
,
undef
,
$cb
,
$cb_args
);
}
sub
asd_task_poll (
$self
,
$taskid
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
$self
->asd(
'get'
,
'/asd/task/poll/'
.
$taskid
,
$param
,
undef
,
$cb
,
$cb_args
);
}
sub
asd_task_list (
$self
,
$taskid
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
$self
->asd(
'get'
,
'/asd/task/list'
,
$param
,
undef
,
$cb
,
$cb_args
);
}
sub
asd_task_kill (
$self
,
$taskid
,
$param
=
undef
,
$cb
=
undef
,
$cb_args
=
undef
) {
return
$self
->asd(
'delete'
,
'/asd/task/kill/'
.
$taskid
,
$param
,
undef
,
$cb
,
$cb_args
);
}
sub
asd_load_input (
$self
,
$input
) {
my
$docs
= [];
my
@lines
= read_file(
$input
);
for
(
@lines
) {
chomp
;
unless
(
$_
=~ m{[=:]}) {
print
STDERR
"ERROR: asd_loas_input: invalid line found[$_], skipping\n"
;
next
;
}
s{(?:^\s*|\s*)$}{}g;
my
(
$k
,
$v
) =
split
(/\s*[=:]\s*/,
$_
, 2);
next
unless
(
defined
(
$k
) &&
defined
(
$v
));
$v
=~ s{(?:^[
"']|["
']$)}{}g;
push
@$docs
, {
$k
=>
$v
};
}
print
STDERR
"VERBOSE: loaded ASD file: $input: "
.Data::Dumper::Dumper(
$docs
).
"\n"
if
$self
->verbose;
return
$docs
;
}
1;