View | Details | Raw Unified | Return to bug 7613
Collapse All | Expand All

(-)a/misc/bin/connexion_import_daemon.pl (-18 / +65 lines)
Lines 87-98 use IO::Socket::INET; Link Here
87
use IO::Select;
87
use IO::Select;
88
use POSIX;
88
use POSIX;
89
use HTTP::Status qw(:constants);
89
use HTTP::Status qw(:constants);
90
use strict;
91
use warnings;
90
92
91
use LWP::UserAgent;
93
use LWP::UserAgent;
92
use XML::Simple;
94
use XML::Simple;
95
use MARC::Record;
96
use MARC::File::XML;
93
97
94
use constant CLIENT_READ_TIMEOUT     => 5;
98
use constant CLIENT_READ_TIMEOUT     => 5;
95
use constant CLIENT_READ_BUFFER_SIZE => 4 * 1024;
99
use constant CLIENT_READ_BUFFER_SIZE => 100000;
96
use constant AUTH_URI       => "/cgi-bin/koha/mainpage.pl";
100
use constant AUTH_URI       => "/cgi-bin/koha/mainpage.pl";
97
use constant IMPORT_SVC_URI => "/cgi-bin/koha/svc/import_bib";
101
use constant IMPORT_SVC_URI => "/cgi-bin/koha/svc/import_bib";
98
102
Lines 222-228 sub _ua { Link Here
222
sub read_request {
226
sub read_request {
223
    my ( $self, $io ) = @_;
227
    my ( $self, $io ) = @_;
224
228
225
    my ($in, @in, $timeout);
229
    my ($in, @in_arr, $timeout, $bad_marc);
226
    my $select = IO::Select->new($io) ;
230
    my $select = IO::Select->new($io) ;
227
    while ( "FOREVER" ) {
231
    while ( "FOREVER" ) {
228
        if ( $select->can_read(CLIENT_READ_TIMEOUT) ){
232
        if ( $select->can_read(CLIENT_READ_TIMEOUT) ){
Lines 231-252 sub read_request { Link Here
231
235
232
            # XXX ignore after NULL
236
            # XXX ignore after NULL
233
            if ( $in =~ m/^(.*)\000/so ) { # null received, EOT
237
            if ( $in =~ m/^(.*)\000/so ) { # null received, EOT
234
                push @in, $1;
238
                push @in_arr, $1;
235
                last;
239
                last;
236
            }
240
            }
237
            push @in, $in;
241
            push @in_arr, $in;
238
        }
242
        }
239
        else {
243
        else {
240
            $timeout = 1;
241
            last;
244
            last;
242
        }
245
        }
243
    }
246
    }
244
247
245
    $in = join '', @in;
248
    $in = join '', @in_arr;
246
249
250
    $in =~ m/(.)$/;
251
    my $lastchar = $1;
247
    my ($xml, $user, $password, $local_user);
252
    my ($xml, $user, $password, $local_user);
248
    my $data = $in; # copy for diagmostic purposes
253
    my $data = $in; # copy for diagmostic purposes
249
    while ( my $first = substr( $data, 0, 1 ) ) {
254
    while () {
255
        my $first = substr( $data, 0, 1 );
256
        if (!defined $first) {
257
           last;
258
        }
250
        $first eq 'U' && do {
259
        $first eq 'U' && do {
251
            ($user, $data) = _trim_identifier($data);
260
            ($user, $data) = _trim_identifier($data);
252
            next;
261
            next;
Lines 256-281 sub read_request { Link Here
256
            next;
265
            next;
257
        };
266
        };
258
        $first eq 'P' && do {
267
        $first eq 'P' && do {
259
            ($password,, $data) = _trim_identifier($data);
268
            ($password, $data) = _trim_identifier($data);
260
            next;
269
            next;
261
        };
270
        };
262
        $first eq ' ' && do {
271
        $first eq ' ' && do {
263
            $data = substr( $data, 1 ); # trim
272
            $data = substr( $data, 1 ); # trim
264
            next;
273
            next;
265
        };
274
        };
266
        $first eq '<' && do {
275
        $data =~ m/^[0-9]/ && do {
267
            $xml = $data;
276
            # What we have here might be a MARC record...
277
            my $marc_record;
278
            eval { $marc_record = MARC::Record->new_from_usmarc($data); };
279
            if ($@) {
280
                $bad_marc = 1;
281
            } 
282
            else {
283
               $xml = $marc_record->as_xml();
284
            }
268
            last;
285
            last;
269
        };
286
        };
270
271
        last; # unexpected input
287
        last; # unexpected input
272
    }
288
    }
273
289
274
    my @details;
290
    my @details;
275
    push @details, "Timeout" if $timeout;
291
    push @details, "Timeout" if $timeout;
292
    push @details, "Bad MARC" if $bad_marc;
276
    push @details, "User: $user" if $user;
293
    push @details, "User: $user" if $user;
277
    push @details, "Password: " . ( $self->{debug} ? $password : ("x" x length($password)) ) if $password;
294
    push @details, "Password: " . ( $self->{debug} ? $password : ("x" x length($password)) ) if $password;
278
    push @details, "Local user: $local_user" if $local_user;
295
    push @details, "Local user: $local_user" if $local_user;
296
    push @details, "XML: $xml" if $xml;
297
    push @details, "Remaining data: $data" if ($data && !$xml);
279
    unless ($xml) {
298
    unless ($xml) {
280
        $self->log("Invalid request", $in, @details);
299
        $self->log("Invalid request", $in, @details);
281
        return;
300
        return;
Lines 287-295 sub read_request { Link Here
287
}
306
}
288
307
289
sub _trim_identifier {
308
sub _trim_identifier {
290
    my ($a, $len) = unpack "cc", substr( $_[0], 0, 2 );
309
    #my ($a, $len) = unpack "cc", substr( $_[0], 0, 2 );
291
310
    my $len=ord(substr ($_[0], 1, 1)) - 64;
292
    return ( substr( $_[0], 2, $len ), substr( $_[0], 2 + $len ) );
311
    if ($len <0) {  #length is numeric, and thus comes from the web client, not the desktop client.
312
       $_[0] =~ m/.(\d+)/;
313
       $len = $1;
314
       return ( substr( $_[0], length($len)+1 , $len ), substr( $_[0], length($len) + 1 + $len ) );
315
    }
316
    return ( substr( $_[0], 2 , $len ), substr( $_[0], 2 + $len ) );
293
}
317
}
294
318
295
sub handle_request {
319
sub handle_request {
Lines 309-321 sub handle_request { Link Here
309
    }
333
    }
310
334
311
    my $base_url = $self->{koha};
335
    my $base_url = $self->{koha};
312
    my $resp = $ua->post( $base_url.IMPORT_SVC_URI, $self->{params}, 'Content-Type' => 'text/plain', Content => $data );
336
    my $resp = $ua->post( $base_url.IMPORT_SVC_URI,  
337
                              {'nomatch_action' => $self->{params}->{nomatch_action},
338
                               'overlay_action' => $self->{params}->{overlay_action}, 
339
                               'match'          => $self->{params}->{match},
340
                               'import_mode'    => $self->{params}->{import_mode},
341
                               'framework'      => $self->{params}->{framework},
342
                               'item_action'    => $self->{params}->{item_action},
343
                               'xml'            => $data});
344
313
    my $status = $resp->code;
345
    my $status = $resp->code;
314
    if ($status == HTTP_UNAUTHORIZED || $status == HTTP_FORBIDDEN) {
346
    if ($status == HTTP_UNAUTHORIZED || $status == HTTP_FORBIDDEN) {
315
        my $user = $self->{user};
347
        my $user = $self->{user};
316
        my $password = $self->{password};
348
        my $password = $self->{password};
317
        $resp = $ua->post( $base_url.AUTH_URI, { userid => $user, password => $password } );
349
        $resp = $ua->post( $base_url.AUTH_URI, { userid => $user, password => $password } );
318
        $resp = $ua->post( $base_url.IMPORT_SVC_URI, $self->{params}, 'Content-Type' => 'text/plain', Content => $data )
350
        $resp = $ua->post( $base_url.IMPORT_SVC_URI,
351
                              {'nomatch_action' => $self->{params}->{nomatch_action},
352
                               'overlay_action' => $self->{params}->{overlay_action}, 
353
                               'match'          => $self->{params}->{match},
354
                               'import_mode'    => $self->{params}->{import_mode},
355
                               'framework'      => $self->{params}->{framework},
356
                               'item_action'    => $self->{params}->{item_action},
357
                               'xml'            => $data})
319
          if $resp->is_success;
358
          if $resp->is_success;
320
    }
359
    }
321
    unless ($resp->is_success) {
360
    unless ($resp->is_success) {
Lines 323-333 sub handle_request { Link Here
323
        return $self->error_response("Unsuccessful request");
362
        return $self->error_response("Unsuccessful request");
324
    }
363
    }
325
364
326
    my ($koha_status, $bib, $batch_id, $error);
365
    my ($koha_status, $bib, $overlay, $batch_id, $error, $url);
327
    if ( my $r = eval { XMLin($resp->content) } ) {
366
    if ( my $r = eval { XMLin($resp->content) } ) {
328
        $koha_status = $r->{status};
367
        $koha_status = $r->{status};
329
        $batch_id    = $r->{import_batch_id};
368
        $batch_id    = $r->{import_batch_id};
330
        $error       = $r->{error};
369
        $error       = $r->{error};
370
        $bib         = $r->{biblionumber};
371
        $overlay     = $r->{match_status};
372
        $url         = $r->{url};
331
    }
373
    }
332
    else {
374
    else {
333
        $koha_status = "error";
375
        $koha_status = "error";
Lines 336-342 sub handle_request { Link Here
336
    }
378
    }
337
379
338
    if ($koha_status eq "ok") {
380
    if ($koha_status eq "ok") {
339
        return $self->response( sprintf( "Success. Import batch id: %s", $batch_id ) );
381
        my $response_string = sprintf( "Success.  Batch number %s - biblio record number %s", 
382
                                        $batch_id,$bib);
383
        $response_string .= $overlay eq 'no_match' ? ' added to Koha.' : ' overlaid by import.';
384
        $response_string .= "\n\n$url";
385
        
386
        return $self->response( $response_string );
340
    }
387
    }
341
388
342
    return $self->error_response( sprintf( "%s.  Please contact administrator.", $error ) );
389
    return $self->error_response( sprintf( "%s.  Please contact administrator.", $error ) );
(-)a/svc/import_bib (-13 / +20 lines)
Lines 41-50 unless ($status eq "ok") { Link Here
41
41
42
my $xml;
42
my $xml;
43
if ($query->request_method eq "POST") {
43
if ($query->request_method eq "POST") {
44
    $xml = $query->param('POSTDATA');
44
    $xml = $query->param('xml');
45
}
45
}
46
if ($xml) {
46
if ($xml) {
47
    my %params = map { $_ => $query->url_param($_) } $query->url_param;
47
    my %params = map { $_ => $query->param($_) } $query->param;
48
    my $result = import_bib($xml, \%params );
48
    my $result = import_bib($xml, \%params );
49
    print $query->header(-type => 'text/xml');
49
    print $query->header(-type => 'text/xml');
50
    print XMLout($result, NoAttr => 1, RootName => 'response', XMLDecl => 1);
50
    print XMLout($result, NoAttr => 1, RootName => 'response', XMLDecl => 1);
Lines 62-68 sub import_bib { Link Here
62
    my $import_mode = delete $params->{import_mode} || '';
62
    my $import_mode = delete $params->{import_mode} || '';
63
    my $framework   = delete $params->{framework}   || '';
63
    my $framework   = delete $params->{framework}   || '';
64
64
65
    if (my $matcher_code = delete $params->{matcher}) {
65
    if (my $matcher_code = delete $params->{match}) {
66
        $params->{matcher_id} = C4::Matcher::GetMatcherId($matcher_code);
66
        $params->{matcher_id} = C4::Matcher::GetMatcherId($matcher_code);
67
    }
67
    }
68
68
Lines 83-101 sub import_bib { Link Here
83
83
84
    my $import_record_id = AddBiblioToBatch($batch_id, 0, $marc_record, "utf8", int(rand(99999)));
84
    my $import_record_id = AddBiblioToBatch($batch_id, 0, $marc_record, "utf8", int(rand(99999)));
85
    my @import_items_ids = AddItemsToImportBiblio($batch_id, $import_record_id, $marc_record, 'UPDATE COUNTS');
85
    my @import_items_ids = AddItemsToImportBiblio($batch_id, $import_record_id, $marc_record, 'UPDATE COUNTS');
86
    my $marcxml = GetImportRecordMarcXML($import_record_id);
86
    
87
    unless ($marcxml) {
87
    my $matcher = C4::Matcher->new($params->{record_type} || 'biblio');
88
        $result->{'status'} = "failed";
88
    $matcher = C4::Matcher->fetch($params->{matcher_id});
89
        $result->{'error'} = "database write error";
89
    my $number_of_matches =  BatchFindBibDuplicates($batch_id, $matcher);
90
        return $result;
91
    }
92
    $marcxml =~ s/<\?xml.*?\?>//i;
93
90
94
    # XXX we are ignoring the result of this;
91
    # XXX we are ignoring the result of this;
95
    BatchCommitBibRecords($batch_id, $framework) if lc($import_mode) eq 'direct';
92
    BatchCommitBibRecords($batch_id, $framework) if lc($import_mode) eq 'direct';
96
93
94
    my $dbh = C4::Context->dbh();
95
    my $sth = $dbh->prepare("SELECT matched_biblionumber FROM import_biblios WHERE import_record_id =?");
96
    $sth->execute($import_record_id);
97
    my $biblionumber=$sth->fetchrow_arrayref->[0] || '';
98
    $sth = $dbh->prepare("SELECT overlay_status FROM import_records WHERE import_record_id =?");
99
    $sth->execute($import_record_id);
100
    my $match_status = $sth->fetchrow_arrayref->[0] || 'no_match';
101
    my $url = 'http://'. C4::Context->preference('staffClientBaseURL') .'/cgi-bin/koha/catalogue/detail.pl?biblionumber='. $biblionumber;
102
97
    $result->{'status'} = "ok";
103
    $result->{'status'} = "ok";
98
    $result->{'import_batch_id'} =  $batch_id;
104
    $result->{'import_batch_id'} = $batch_id;
99
    $result->{'marcxml'} =  $marcxml;
105
    $result->{'match_status'} = $match_status;
106
    $result->{'biblionumber'} = $biblionumber;
107
    $result->{'url'} = $url;
100
    return $result;
108
    return $result;
101
}
109
}
102
- 

Return to bug 7613