#!perl -w
use strict;
$|=1;
#todo: add option to select from multiple named servers from .tracrc
package TracServer;
use strict;
use warnings;
use WebServer;
use Carp;
use POSIX;
sub new {
my ($class, $server, %properties)= @_;
my $self= bless {
server=> WebServer->new($server),
%properties,
}, $class;
$self->{server}->credentials($properties{username}, $properties{password});
$self->get("");
return $self;
}
sub formtoken {
my ($self)= @_;
return $self->{server}->getcookie($self->{server}{hostname}, $self->{server}{basepath}, 'trac_form_token');
}
# $self->post("newticket", { type=>'defect', status=>'new', summary=>'.....' });
sub post {
my ($self, $action, @params)= @_;
return $self->{server}->httppost($action, __FORM_TOKEN=>$self->formtoken(), @params);
}
sub get {
my ($self, $action, @params)= @_;
return $self->{server}->httpget($action, @params);
}
#
# in: hash with
# summary
# reporter
# description
# owner
# type
# priority
# milestone
# component
# keywords
# cc
# returns:
# ticketnr
sub newticket {
my ($self, %p)= @_;
my $rp= $self->post("newticket", field_reporter=>$ENV{USER}, field_status=>'new', submit=>"Create ticket", map { ("field_$_"=>$p{$_}) } keys %p);
if ($rp->header('Location') && $rp->header('Location')=~/ticket\/(\d+)/) {
return $1;
}
my $html= join "",$rp->content;
if ($html =~ /
(.*?)<\/div>/s) {
my $txt= $1;
$txt=~ s/<[^>]*>/ /gm;
$txt=~ s/^\s+//gm;
$txt=~ s/\s+$//gm;
print "$txt\n";
}
die "error creating ticket";
}
#
# in: tickernr, hash with updated fields
sub changeticket {
my ($self, $nr, %p)= @_;
my $comment= $p{comment};
delete $p{comment};
my $resolve= $p{action_resolve_resolve_resolution};
delete $p{action_resolve_resolve_resolution};
my $origticket= $self->readticket($nr);
return $self->post("ticket/$nr", author=>$ENV{USER}, cnum=>1, action=>($resolve?'resolve':'leave'),
$resolve?(action_resolve_resolve_resolution=>$resolve):(),
ts=>$origticket->{ts}, comment=>$comment, submit=>"Submit changes", map { ("field_$_"=>$p{$_}) } keys %p);
}
sub gettimestamp {
return POSIX::strftime("%Y-%m-%d %H:%M:%S+00:00", gmtime(time()));
}
sub readticket {
my ($self, $nr)= @_;
my $html= join "",$self->get("ticket/$nr")->content;
if ($html=~/name="ts" value="(.*?)"/) {
return { ts=>$1 };
}
}
#
# in: ticketnr, filename or filedata
sub attachfile {
}
sub getprops {
my ($self)= @_;
my $rp= $self->get("newticket");
my %props;
my $html= join "", $rp->content;
while ($html =~ m{}gs) {
my ($name, @values)= parseselect($&);
$props{$name}= \@values;
}
# extract possible fields from page
my @fields;
while ($html =~ m{name="field_(\w+)"}gs) {
push @fields, $1;
}
$props{properties}= \@fields;
return %props;
}
sub parseselect {
my ($html)=@_;
my $name;
if ($html =~ /]*>(.*)<\/option>/s) {
my $opthtml= $1;
@values= split /\s*<\/option>.*?