]> wagnertech.de Git - mfinanz.git/blob - SL/BackgroundJob/SyncWebDAV.pm
restart apache2 in postinst
[mfinanz.git] / SL / BackgroundJob / SyncWebDAV.pm
1 package SL::BackgroundJob::SyncWebDAV;
2
3 use strict;
4 use warnings;
5
6 use parent qw(SL::BackgroundJob::Base);
7
8 use SL::DB::BackgroundJobHistory;
9 use HTTP::DAV;
10 use File::Find;
11 use Cwd;
12 use Data::Dumper;
13
14 sub create_job {
15   $_[0]->create_standard_job('0 3 * * *'); # daily at 3:00 am
16 }
17
18 sub run {
19   my $self    = shift;
20   my $db_obj  = shift;
21
22   my $options     = $db_obj->data_as_hash;
23   my $DELETE_ONLY = 0 || $options->{delete};
24
25   return unless $::instance_conf->get_webdav_sync_extern;
26
27   my $ret;
28
29   my $dav     = HTTP::DAV->new();
30   my $url     = $::instance_conf->get_webdav_sync_extern_url;
31   $url        =~ s|/\z||;  # no trailing slashes
32
33   $dav->credentials(
34        -user  =>  $::instance_conf->get_webdav_sync_extern_login,
35        -pass  =>  $::instance_conf->get_webdav_sync_extern_pass,
36        -url   =>  $url,
37   );
38   my $client_id   = $options->{client_id} || $::auth->get_session_value('client_id');
39   my $cwd = getcwd();
40
41   my @fails;
42
43   eval {
44
45     my (@webdav_dir_temp, @webdav_dir, @webdav_files);
46
47     # chdir to client root
48     my $webdav = $cwd. "/webdav/$client_id/";
49     chdir($webdav) or die "couldn't change into webdav dir"; # TODO throw better error message (Permission denied, etc)
50
51     find( { wanted => sub { push @webdav_dir_temp, -d && $_}, no_chdir => 1 }, '.');
52     find( { wanted => sub { push @webdav_files, -f && $_}, no_chdir => 1    }, '.');
53
54     shift @webdav_dir_temp; # first element would be undef after substr
55     foreach (@webdav_dir_temp) {
56       next unless $_;
57       push @webdav_dir, substr($_,2);
58     }
59     @webdav_files = map { substr($_,2) } grep { $_ =~ m/.*pdf/ } @webdav_files;
60
61     $ret = $dav->open(-url => $url) or die "Can't open url $url";
62     # Make a null lock on repo for 5minutes
63     #$ret = $dav->lock(-url => $url, -timeout => "30m") or die;
64
65     foreach (@webdav_dir) {
66       last if $DELETE_ONLY;
67
68       $ret             = $dav->options(-url => $url . '/' . $_);
69       next unless $ret =~ m/MKCOL/;
70
71       unless ( $dav->mkcol($_) ) {
72         push(@fails, "Cannot make dir $_");
73       };
74     }
75
76     #$dav->unlock(-url => $url); # UNLOCK after DIR sync
77     # now we have all dirs in sync, therefore we can place files
78     foreach (@webdav_files) {
79       last if $DELETE_ONLY;
80
81       $ret         = $dav->options(-url => $url . '/' . $_);
82       # $main::lxdebug->message(0, 'verzeichnis:'. $_ . '::' . $ret . ':' . $dav->message);
83       next unless $ret =~ m/MKCOL/;  # file not there #owncloud gives DELETE even if file not there
84       #$dav->lock(-url => $url . '/' . $_); # UNLOCK after DIR sync
85
86       # $main::lxdebug->message(0, 'datei:'. $_);
87       unless ( $dav->put(-local => $_, -url => $url . '/' . $_) ) {
88         push(@fails, "Cannot put file $_");
89       };
90       #$dav->unlock(-url => $url . '/' . $_); # UNLOCK after put
91     }
92
93     # maybe we delete some stuff
94     # TODO delete stuff here
95     if ($DELETE_ONLY) {
96       foreach (qw(anfragen bestellungen einkaufslieferscheine einkaufsrechnungen angebote
97              gutschriften lieferantenbestellungen rechnungen verkaufslieferscheine)) {
98         $ret = $dav->delete($url . "/$_");
99       }
100
101       # better, but not implemented - delete only local deleted stuff
102       # idea: propfind all the above dirs and check if child (rel_uri) exists locally
103       # if not, we can safely delete remote
104       # if (my $r=$dav->propfind( -url=>"$_/", -depth=>1) ) { ...
105     }
106
107     #$dav->unlock(-url => $url);
108     chdir($cwd);
109
110     1;
111
112   } or do {
113     my $error = "dav: " . $dav->message . ", eval: " . $! . ", eval 2: " . $@;
114    # $dav->unlock(-url => $url);    # unlock, just in case
115     # chdir($cwd);
116     die("Couldn't sync with external webdav repo at $url error code/protocol return:" . $error);
117   };
118
119   if ( @fails ) {
120     die join("\n", @fails);
121   };
122
123   return 1;
124 }
125
126 1;
127
128 __END__
129
130 =encoding utf8
131
132 =head1 NAME
133
134 SL::BackgroundJob::ExternalSyncWebDAV - Background job for
135 syncing all folders and files for current client to a external
136 webdav-repository
137
138 =head1 SYNOPSIS
139
140 This background job copies all files and folders for one client
141 to a external webdav-repo.
142 A optional param C<delete> can be set to 1 to delete (clean)
143 the external repo. If set to undef or 0 a folderwise copy will be
144 executed.
145 To test with different clients a param C<client_id> will overload
146 the current client id.
147 The settings for the external repo are in client config.
148 If a lock still exists, the job returns a Internal Server Error
149 from the webdav server.
150 Only pdf files are considered valid files to copy.
151
152 The job is supposed to run once a day.
153
154 =head1 BUGS
155
156 Nothing here yet.
157
158 =head1 AUTHOR
159
160 Jan Büren E<lt>jan@kivitendo-premium.deE<gt>
161
162 =cut
163