Bugzilla – Attachment 110265 Details for
Bug 25965
Create SIP2 client daemon with HTTPS API endpoint
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for adding SIP2 over HTTPS support
0001-SIP2oHTTPS.patch (text/plain), 12.33 KB, created by
Lari Strand
on 2020-09-17 13:47:58 UTC
(
hide
)
Description:
Patch for adding SIP2 over HTTPS support
Filename:
MIME Type:
Creator:
Lari Strand
Created:
2020-09-17 13:47:58 UTC
Size:
12.33 KB
patch
obsolete
>From 2e8b3fda3b1f261dc7ce94a0951c6848b31cfc0c Mon Sep 17 00:00:00 2001 >From: lmstrand <lmstrand@gmail.com> >Date: Fri, 31 Jul 2020 10:39:39 +0300 >Subject: [PATCH] SIP2oHTTPS > >--- > Koha/REST/V1/SIPoHTTP/SIPoHTTP.pm | 297 +++++++++++++++++++++++++++++ > api/v1/swagger/definitions.json | 3 + > api/v1/swagger/definitions/sipmessage.json | 4 + > api/v1/swagger/parameters/sipmessage.json | 9 + > api/v1/swagger/paths.json | 3 + > api/v1/swagger/paths/sipmessages.json | 51 +++++ > etc/sip2ohttp-config.xml | 37 ++++ > koha-tmpl/sipschema.xsd | 29 +++ > 8 files changed, 433 insertions(+) > create mode 100644 Koha/REST/V1/SIPoHTTP/SIPoHTTP.pm > create mode 100644 api/v1/swagger/definitions/sipmessage.json > create mode 100644 api/v1/swagger/parameters/sipmessage.json > create mode 100644 api/v1/swagger/paths/sipmessages.json > create mode 100755 etc/sip2ohttp-config.xml > create mode 100644 koha-tmpl/sipschema.xsd > >diff --git a/Koha/REST/V1/SIPoHTTP/SIPoHTTP.pm b/Koha/REST/V1/SIPoHTTP/SIPoHTTP.pm >new file mode 100644 >index 0000000..d12bbf4 >--- /dev/null >+++ b/Koha/REST/V1/SIPoHTTP/SIPoHTTP.pm >@@ -0,0 +1,297 @@ >+package Koha::REST::V1::SIPoHTTP::SIPoHTTP; >+ >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it under the >+# terms of the GNU General Public License as published by the Free Software >+# Foundation; either version 3 of the License, or (at your option) any later >+# version. >+# >+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY >+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR >+# A PARTICULAR PURPOSE. See the GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License along >+# with Koha; if not, write to the Free Software Foundation, Inc., >+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >+ >+use Modern::Perl; >+ >+use Mojo::Base 'Mojolicious::Controller'; >+ >+use FindBin qw($Bin); >+use lib "$Bin"; >+use Koha::Exceptions; >+use Koha::Logger; >+use XML::LibXML; >+use IO::Socket::INET; >+use IO::Socket qw(AF_INET AF_UNIX SOCK_STREAM SHUT_WR); >+use Socket qw(:crlf); >+use Try::Tiny; >+use Mojo::Log; >+use File::Basename; >+use C4::Context; >+ >+use strict; >+use warnings qw( all ); >+ >+my $CONFPATH = dirname( $ENV{'KOHA_CONF'} ); >+my $KOHAPATH = C4::Context->config('intranetdir'); >+ >+my $log = Koha::Logger->get(); >+ >+#This gets called from REST api >+sub process { >+ >+ my $c = shift->openapi->valid_input or return; >+ >+ my $body = $c->req->body; >+ my $xmlrequest = $body; >+ >+ $log->info("Request received."); >+ >+ my $validation = validateXml( $c, $xmlrequest ); >+ >+ if ( $validation != 1 ) { >+ >+ $c->render( >+ text => "Invalid Request. XML Validation failed.", >+ status => 400 >+ ); >+ >+ return; >+ } >+ >+ #process sip here >+ my ( $login, $password ) = getLogin($xmlrequest); >+ >+ if ( !$login or !$password ) { >+ >+ $log->error("Invalid request. Missing login/pw in XML."); >+ >+ $c->render( >+ text => "Invalid request. Missing login/pw in XML.", >+ status => 400 >+ ); >+ return; >+ } >+ my $sipmes = extractSip( $xmlrequest, $c ); >+ >+ unless ($sipmes) { >+ >+ $log->error("Invalid request. Missing SIP Request in XML."); >+ >+ $c->render( >+ text => "Invalid request. Missing SIP Request in XML.", >+ status => 400 >+ ); >+ return; >+ } >+ >+ my ( $siphost, $sipport ) = extractServer( $xmlrequest, $c ); >+ >+ unless ( $siphost && $sipport ) { >+ >+ $log->error("No config found for login device. "); >+ >+ return $c->render( >+ text => "No config found for login device. ", >+ status => 400 >+ ); >+ >+ } >+ >+ my $sipresponse = >+ tradeSip( $login, $password, $siphost, $sipport, $sipmes, $c ); >+ >+ #remove carriage return from response (\r) >+ $sipresponse =~ s/\r//g; >+ >+ my $xmlresponse = buildXml($sipresponse); >+ >+ return try { >+ $c->render( status => 200, text => $xmlresponse ); >+ $log->info("XML response passed to endpoint."); >+ >+ } >+ catch { >+ Koha::Exceptions::rethrow_exception($_); >+ } >+} >+ >+sub tradeSip { >+ >+ my ( $login, $password, $host, $port, $command_message, $c ) = @_; >+ >+ my $sipsock = IO::Socket::INET->new( >+ PeerAddr => $host, >+ PeerPort => $port, >+ Proto => 'tcp' >+ ) or die $log->fatal("Can't create a socket for sipserver. Sipserver down?"); >+ >+ $sipsock->autoflush(1); >+ >+ my $loginsip = buildLogin( $login, $password ); >+ >+ my $terminator = q{}; >+ $terminator = ( $terminator eq 'CR' ) ? $CR : $CRLF; >+ >+ # Set perl to expect the same record terminator it is sending >+ $/ = $terminator; >+ >+ $log->info("Trying login: $loginsip"); >+ >+ my $respdata; >+ >+ print $sipsock $loginsip . $terminator; >+ >+ $sipsock->recv( $respdata, 1024 ); >+ $sipsock->flush; >+ >+ if ( $respdata == "941" ) { >+ >+ $log->info("Login OK. Sending: $command_message"); >+ >+ print $sipsock $command_message . $terminator; >+ >+ $sipsock->recv( $respdata, 1024 ); >+ $sipsock->flush; >+ >+ $sipsock->shutdown(SHUT_WR); >+ $sipsock->shutdown(SHUT_RDWR); # we stopped using this socket >+ $sipsock->close; >+ >+ my $respmes = $respdata; >+ $respmes =~ s/.{1}$//; >+ >+ $log->info("Received: $respmes"); >+ >+ return $respdata; >+ } >+ >+ chomp $respdata; >+ $log->error( >+"Unauthorized login for $login: $respdata. Can't process attached SIP message." >+ ); >+ >+ return $respdata; >+} >+ >+sub buildLogin { >+ >+ my ( $login, $password ) = @_; >+ >+ my $siptempl = "9300CN<SIPDEVICE>|CO<SIPDEVICEPASS>|CPSIPLOCATION|"; >+ return "9300CN" . shift . "|CO" . shift . "|CPSIP2OHTTP|"; >+} >+ >+sub buildXml { >+ >+ my $responsemessage = shift; >+ >+ my $respxml = '<?xml version="1.0" encoding="UTF-8"?> >+ >+<ns1:sip xsi:schemaLocation="https://koha-suomi.fi/sipschema.xsd" xmlns:ns1="https://koha-suomi.fi/sipschema.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> >+ >+ <response><TMPL_VAR_MESSAGE></response> >+ >+</ns1:sip>'; >+ >+ $respxml =~ s|<TMPL_VAR_MESSAGE>|$responsemessage|; >+ >+ return $respxml; >+} >+ >+sub extractSip { >+ >+ my ( $xmlmessage, $c ) = @_; >+ >+ my $parser = XML::LibXML->new(); >+ my $xmldoc = $parser->load_xml( string => $xmlmessage ); >+ my $xc = XML::LibXML::XPathContext->new( $xmldoc->documentElement() ); >+ >+ my ($node) = $xc->findnodes('//request'); >+ >+ my $sample = $node->textContent; >+ return $sample; >+ >+} >+ >+sub getLogin { >+ >+ #Retrieve the self check machine login info from XML >+ my $xmlmessage = shift; >+ >+ my ( $login, $passw ); >+ >+ my $parser = XML::LibXML->new(); >+ my $doc = $parser->load_xml( string => $xmlmessage ); >+ my $xc = XML::LibXML::XPathContext->new( $doc->documentElement() ); >+ >+ my ($node) = $xc->findnodes('//ns1:sip'); >+ >+ try { >+ $login = $node->getAttribute("login"); >+ $passw = $node->getAttribute("password"); >+ >+ return $login, $passw; >+ } >+ catch { >+ return 0; >+ } >+ >+} >+ >+sub extractServer { >+ >+ my ( $host, $port ); >+ >+ my ( $xmlmessage, $c ) = @_; >+ my ( $term, $pass ) = getLogin($xmlmessage); >+ >+ my $doc = >+ XML::LibXML->load_xml( location => $CONFPATH . '/sip2ohttp-config.xml' ); >+ my $xc = XML::LibXML::XPathContext->new( $doc->documentElement() ); >+ >+ my ($node) = $xc->findnodes( '//' . $term ); >+ >+ unless ($node) { >+ $log->error( >+ "Missing server config parameters for $term in sipdevices.xml"); >+ return 0; >+ } >+ >+ $host = $node->findvalue('./host'); >+ $port = $node->findvalue('./port'); >+ return $host, $port; >+ >+} >+ >+sub validateXml { >+ >+ #For validating the content of the XML SIP message >+ my ( $c, $xmlbody ) = @_; >+ my $parser = XML::LibXML->new(); >+ >+ # parse and validate the xml against sipschema >+ # https://koha-suomi.fi/sipschema.xsd >+ my $schema = >+ XML::LibXML::Schema->new( >+ location => $KOHAPATH . '/koha-tmpl/sipschema.xsd' ); >+ >+ try { >+ >+ my $xmldoc = $parser->load_xml( string => $xmlbody ); >+ $schema->validate($xmldoc); >+ $log->info("XML Validated OK."); >+ return 1; >+ } >+ catch { >+ $log->error("Could not validate XML - @_"); >+ return 0; >+ >+ }; >+ >+} >+ >+1; >diff --git a/api/v1/swagger/definitions.json b/api/v1/swagger/definitions.json >index 2d5b354..ba27dd7 100644 >--- a/api/v1/swagger/definitions.json >+++ b/api/v1/swagger/definitions.json >@@ -106,5 +106,8 @@ > }, > "mongolog": { > "$ref": "definitions/mongolog.json" >+ }, >+ "sipmessage": { >+ "$ref": "definitions/sipmessage.json" > } > } >diff --git a/api/v1/swagger/definitions/sipmessage.json b/api/v1/swagger/definitions/sipmessage.json >new file mode 100644 >index 0000000..6c63efb >--- /dev/null >+++ b/api/v1/swagger/definitions/sipmessage.json >@@ -0,0 +1,4 @@ >+{ >+ "type": "string", >+ "additionalProperties": true >+} >diff --git a/api/v1/swagger/parameters/sipmessage.json b/api/v1/swagger/parameters/sipmessage.json >new file mode 100644 >index 0000000..8ad1fe1 >--- /dev/null >+++ b/api/v1/swagger/parameters/sipmessage.json >@@ -0,0 +1,9 @@ >+{ >+ "sipMessage": { >+ "name": "request", >+ "in": "formData", >+ "allowReserved": true, >+ "description": "sipmessage", >+ "required": false >+ } >+} >diff --git a/api/v1/swagger/paths.json b/api/v1/swagger/paths.json >index bce6bcc..6f45c73 100644 >--- a/api/v1/swagger/paths.json >+++ b/api/v1/swagger/paths.json >@@ -217,5 +217,8 @@ > }, > "/suggestions/{suggestionid}": { > "$ref": "paths/suggestions.json#/~1suggestions~1{suggestionid}" >+ }, >+ "/sipmessages": { >+ "$ref": "paths/sipmessages.json#/~1sipmessages" > } > } >diff --git a/api/v1/swagger/paths/sipmessages.json b/api/v1/swagger/paths/sipmessages.json >new file mode 100644 >index 0000000..3e8b220 >--- /dev/null >+++ b/api/v1/swagger/paths/sipmessages.json >@@ -0,0 +1,51 @@ >+{ >+ "/sipmessages": { >+ "post": { >+ "x-mojo-to": "SIPoHTTP::SIPoHTTP#process", >+ "operationId": "SIPoHTTP", >+ "tags": [ >+ "sipmessages" >+ ], >+ "parameters": [ >+ { >+ "name": "query", >+ "in": "query", >+ "description": "sip in XML.", >+ "type": "string" >+ } >+ ], >+ "consumes": [ >+ "application/xml" >+ ], >+ "produces": [ >+ "application/xml" >+ ], >+ "responses": { >+ "200": { >+ "description": "Sip message ok", >+ "schema": { >+ "$ref": "../definitions.json#/sipmessage" >+ } >+ }, >+ "400": { >+ "description": "Missing or wrong parameters", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "500": { >+ "description": "Internal server error", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "503": { >+ "description": "Under maintenance", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ } >+ } >+ } >+ } >+} >diff --git a/etc/sip2ohttp-config.xml b/etc/sip2ohttp-config.xml >new file mode 100755 >index 0000000..0a9738c >--- /dev/null >+++ b/etc/sip2ohttp-config.xml >@@ -0,0 +1,37 @@ >+<?xml version='1.0' encoding='UTF-8' standalone="yes" ?> >+ >+<Config> >+ >+ <Sipdevices> >+ >+ <!-- Devices' login id's and their sip server hosts:ports to use --> >+ <!-- Set these for devices using sipohttp(s) --> >+ >+ <!-- Examples: (these device login id's and sip server addresses get searched by SIPoHTTP.pm >+ when the /sipmessages REST endpoint receives a POST request with the XML in the request body. >+ The device login id's must match the login id's defined in SIPconfig.xml. >+ Multiple devices can use/share the same sip server.) --> >+ >+ <!-- Uncomment and replace with your config >+ >+ <SIPDEVICENAME> >+ <host>127.0.0.1</host> >+ <port>6009</port> >+ </SIPDEVICENAME> >+ <SIPDEVICENAMEB> >+ <host>127.0.0.1</host> >+ <port>6009</port> >+ </SIPDEVICENAMEB> >+ <sipdevice2> >+ <host>127.0.0.1</host> >+ <port>6010</port> >+ </sipdevice2> >+ >+ --> >+ >+ </Sipdevices> >+ >+</Config> >+ >+ >+ >diff --git a/koha-tmpl/sipschema.xsd b/koha-tmpl/sipschema.xsd >new file mode 100644 >index 0000000..bb9bab8 >--- /dev/null >+++ b/koha-tmpl/sipschema.xsd >@@ -0,0 +1,29 @@ >+<?xml version="1.0" encoding="UTF-8"?> >+ >+<!-- sipschema.xsd $Revision: 1.0 $ support@koha-suomi.fi --> >+ >+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ns1="https://koha-suomi.fi/sipschema.xsd" targetNamespace="https://koha-suomi.fi/sipschema.xsd" elementFormDefault="unqualified" attributeFormDefault="unqualified"> >+ >+ <xs:element name="sip"> >+ >+ <xs:complexType> >+ >+ <xs:choice> >+ >+ <xs:element name="request" type="xs:string"/> >+ >+ <xs:element name="response" type="xs:string"/> >+ >+ <xs:element name="error" type="xs:string"/> >+ >+ </xs:choice> >+ >+ <xs:attribute name="login" type="xs:string"/> >+ >+ <xs:attribute name="password" type="xs:string"/> >+ >+ </xs:complexType> >+ >+ </xs:element> >+ >+</xs:schema> >\ No newline at end of file >-- >2.7.4 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 25965
: 110265 |
110267