webmoney 0.0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,8 @@
1
+ // stdafx.cpp : source file that includes just the standard includes
2
+ // wmsigner.pch will be the pre-compiled header
3
+ // stdafx.obj will contain the pre-compiled type information
4
+
5
+ #include "stdafx.h"
6
+
7
+ // TODO: reference any additional headers you need in STDAFX.H
8
+ // and not in this file
@@ -0,0 +1,33 @@
1
+ // stdafx.h : include file for standard system include files,
2
+ // or project specific include files that are used frequently, but
3
+ // are changed infrequently
4
+ //
5
+
6
+ // REMOVE COMMENT FOR DEBUG MODE
7
+ //#ifndef _DEBUG
8
+ //#define _DEBUG
9
+ //#endif
10
+
11
+
12
+ #include <stdio.h>
13
+ #include <stdlib.h>
14
+ #include <string.h>
15
+ #include <sys/types.h>
16
+ #include <errno.h>
17
+ #ifdef _WIN32
18
+ #pragma once
19
+ #include <iostream>
20
+ #include <tchar.h>
21
+ #include <windows.h>
22
+ #include <io.h>
23
+ #include <memory.h>
24
+ #pragma warning(disable : 4996)
25
+ #endif
26
+ // TODO: reference additional headers your program requires here
27
+ #ifndef TRUE
28
+ #define TRUE 1
29
+ #endif
30
+ #ifndef FALSE
31
+ #define FALSE 0
32
+ #endif
33
+
@@ -0,0 +1,119 @@
1
+ // Include the Ruby headers and goodies
2
+ #include <stdlib.h>
3
+ #include <ctype.h>
4
+ #include "ruby.h"
5
+ #include "signer.h"
6
+ #include "base64.h"
7
+ #include "cmdbase.h"
8
+
9
+ #define ASCII_SIZE 512
10
+ #define BUF_64_SIZE 220
11
+
12
+ // Defining a space for information and references about the module to be stored internally
13
+ VALUE cSigner;
14
+
15
+ typedef VALUE (ruby_method)(...);
16
+
17
+ // Prototype for the initialization method - Ruby calls this, not you
18
+ //extern "C" void Init_Wmutils();
19
+
20
+ // Prototype for our method 'test1' - methods are prefixed by 'method_' here
21
+ // typedef VALUE method_test1(VALUE self);
22
+ // typedef VALUE initialize(VALUE self, const char *szWMID, const char *szPwd, const char *szKeyData);
23
+
24
+ //Signer *pSign;
25
+
26
+ void signer_free(Signer *p)
27
+ {
28
+ if (p)
29
+ delete p;
30
+ }
31
+
32
+ bool IsWmid(const char* sz)
33
+ {
34
+ int len = strlen(sz);
35
+ if (len != 12) return false;
36
+ for(int i = 0; i < len; i++)
37
+ {
38
+ if (!isdigit(sz[i]))
39
+ return false;
40
+ }
41
+ return true;
42
+ }
43
+
44
+ extern "C" VALUE signer_new(VALUE self, VALUE szWMID, VALUE szPwd, VALUE szKeyData64)
45
+ {
46
+ Signer *pSign;
47
+
48
+ if(NIL_P(szWMID)) rb_raise(rb_eArgError, "nil wmid");
49
+
50
+ // check WMID
51
+ if (! IsWmid(RSTRING(szWMID)->ptr)) rb_raise(rb_eArgError, "Incorrect WMID");
52
+
53
+ if(NIL_P(szPwd)) rb_raise(rb_eArgError, "nil password");
54
+
55
+ if(NIL_P(szKeyData64)) rb_raise(rb_eArgError, "nil key");
56
+
57
+ // check base64 data
58
+ if ( RSTRING(szKeyData64)->len != 220 ) rb_raise(rb_eArgError, "Illegal size for base64 keydata");
59
+
60
+ char KeyBuffer[ASCII_SIZE];
61
+ int bytes = code64( ENCODE, KeyBuffer, ASCII_SIZE, RSTRING(szKeyData64)->ptr, BUF_64_SIZE );
62
+
63
+ // check encoded key
64
+ if ( bytes != 164) rb_raise(rb_eArgError, "Illegal size for keydata");
65
+
66
+ pSign = new Signer(RSTRING(szWMID)->ptr, RSTRING(szPwd)->ptr, "");
67
+ VALUE tdata = Data_Wrap_Struct(self, 0, signer_free, pSign);
68
+
69
+ pSign->isIgnoreKeyFile = TRUE;
70
+ pSign->Key64Flag = TRUE;
71
+
72
+ if (pSign) pSign->SetKeyFromCL( TRUE, KeyBuffer );
73
+
74
+ return tdata;
75
+ }
76
+
77
+ extern "C" VALUE signer_init(VALUE self)
78
+ {
79
+ return self;
80
+ }
81
+
82
+ extern "C" VALUE signer_sign(VALUE self, VALUE szIn)
83
+ {
84
+ VALUE ret;
85
+ ret = rb_str_new2("");
86
+
87
+ Signer *pSign;
88
+
89
+ Data_Get_Struct(self, Signer, pSign);
90
+
91
+ if(NIL_P(szIn)) rb_raise(rb_eArgError, "nil for sign");
92
+
93
+ if (pSign)
94
+ {
95
+ szptr szSign;
96
+ if (pSign->Sign(RSTRING(szIn)->ptr, szSign))
97
+ {
98
+ ret = rb_str_new2((char *)(const char *)szSign);
99
+ }
100
+ }
101
+
102
+ int err_no = pSign->ErrorCode();
103
+ if (err_no){
104
+ char err[20];
105
+ sprintf(err, "Signer error: %d", err_no);
106
+ rb_raise(rb_eStandardError, err);
107
+ }
108
+
109
+ return ret;
110
+ }
111
+
112
+ // The initialization method for this module
113
+ extern "C" void Init_wmsigner()
114
+ {
115
+ cSigner = rb_define_class("Signer", rb_cObject);
116
+ rb_define_singleton_method(cSigner, "new", (ruby_method*) &signer_new, 3);
117
+ rb_define_method(cSigner, "initialize", (ruby_method*) &signer_init, 0);
118
+ rb_define_method(cSigner, "sign", (ruby_method*) &signer_sign, 1);
119
+ }
@@ -0,0 +1,90 @@
1
+ WebMoney Transfer Root Authority
2
+ ================================
3
+ SHA1 Fingerprint: 76:7C:A8:69:09:10:F0:69:32:33:66:A9:C4:5D:78:6B:D1:37:17:16
4
+ PEM Data:
5
+ -----BEGIN CERTIFICATE-----
6
+ MIIEGTCCAwGgAwIBAgIQNHU6UsCDcLJD7Qw+0yqyRjANBgkqhkiG9w0BAQUFADBv
7
+ MRowGAYDVQQKExFXZWJNb25leSBUcmFuc2ZlcjEmMCQGA1UECxMdV2ViTW9uZXkg
8
+ Q2VydGlmaWNhdGlvbiBDZW50ZXIxKTAnBgNVBAMTIFdlYk1vbmV5IFRyYW5zZmVy
9
+ IFJvb3QgQXV0aG9yaXR5MB4XDTAxMDQwNDEzNDcwOVoXDTEwMDYwNzE5NDcxOFow
10
+ bzEaMBgGA1UEChMRV2ViTW9uZXkgVHJhbnNmZXIxJjAkBgNVBAsTHVdlYk1vbmV5
11
+ IENlcnRpZmljYXRpb24gQ2VudGVyMSkwJwYDVQQDEyBXZWJNb25leSBUcmFuc2Zl
12
+ ciBSb290IEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
13
+ AO9V0RYrJYPCOR7odiyICWNuoZj0tN9Z1mY10s+QIYGsMZCNG0meQymt5jTuhD/E
14
+ GNAHVVR9st3C92pqy2UAvQyAxMmzg5SJbuo/39YSAqx0vEtehl4QfHWHSiFStbbt
15
+ ZslHdl1jYKLwm6B88XI3OpiAoMAccntSazvim1k18lZ2bsTJeiH4s8BLP5T0Yw+R
16
+ belHaJe1DiRWChoKqoVqsDp5mH7v0cEpD78KltHo57zUuH+rzTcTeCKkO4/9CWiF
17
+ qY2FzC09wekFJ8LZ0HMlcANdLYSvmz3Ux3BvFqy8Jyt8dBhq8MRUkzZC8Cg5/lfs
18
+ ZSMHHsr1PnsIuM0OGbb1GJMCAwEAAaOBsDCBrTALBgNVHQ8EBAMCAcYwDwYDVR0T
19
+ AQH/BAUwAwEB/zAdBgNVHQ4EFgQUy51+UX4IIMT1cJShzlLHBU0/M/MwXAYDVR0f
20
+ BFUwUzBRoE+gTYZLaHR0cDovL3d3dy53bWNlcnQuY29tL0NlcnRFbnJvbGwvV2Vi
21
+ TW9uZXklMjBUcmFuc2ZlciUyMFJvb3QlMjBBdXRob3JpdHkuY3JsMBAGCSsGAQQB
22
+ gjcVAQQDAgECMA0GCSqGSIb3DQEBBQUAA4IBAQBqGyv5FVpV4MK0VYXPFqUhsyVc
23
+ SDqM+hu4U0OA0cIKHOXRV6BcbDzsNi1+6HVA2vr9PIcIVTRlGXcU95JcQe3tjbXQ
24
+ NNMpKcgL0YMW0ifMA2qu5y6nJTIu7rKCESUtsMzQUnccaXmYn0DChYuvPObb5suf
25
+ RVlsHL9Gc90eRiR8lofaDqIM82vETsQEIj1M1ifUgD5LxZuwQ8fdESZ/GHkxCosa
26
+ 9YG7WZKTMEgPSXpLmd+y24NklMi9cb+0dJce84OgMUfFAxYO71lkc0dJ5B7TJsqS
27
+ Ymwnj0x4w32Av3TiEJOQMghAJVsdPJiEzUiHMVDsAbyXQ03gZIyexFpl4QDy
28
+ -----END CERTIFICATE-----
29
+ Certificate Ingredients:
30
+ Data:
31
+ Version: 3 (0x2)
32
+ Serial Number:
33
+ 34:75:3a:52:c0:83:70:b2:43:ed:0c:3e:d3:2a:b2:46
34
+ Signature Algorithm: sha1WithRSAEncryption
35
+ Issuer: O=WebMoney Transfer, OU=WebMoney Certification Center, CN=WebMoney Transfer Root Authority
36
+ Validity
37
+ Not Before: Apr 4 13:47:09 2001 GMT
38
+ Not After : Jun 7 19:47:18 2010 GMT
39
+ Subject: O=WebMoney Transfer, OU=WebMoney Certification Center, CN=WebMoney Transfer Root Authority
40
+ Subject Public Key Info:
41
+ Public Key Algorithm: rsaEncryption
42
+ RSA Public Key: (2048 bit)
43
+ Modulus (2048 bit):
44
+ 00:ef:55:d1:16:2b:25:83:c2:39:1e:e8:76:2c:88:
45
+ 09:63:6e:a1:98:f4:b4:df:59:d6:66:35:d2:cf:90:
46
+ 21:81:ac:31:90:8d:1b:49:9e:43:29:ad:e6:34:ee:
47
+ 84:3f:c4:18:d0:07:55:54:7d:b2:dd:c2:f7:6a:6a:
48
+ cb:65:00:bd:0c:80:c4:c9:b3:83:94:89:6e:ea:3f:
49
+ df:d6:12:02:ac:74:bc:4b:5e:86:5e:10:7c:75:87:
50
+ 4a:21:52:b5:b6:ed:66:c9:47:76:5d:63:60:a2:f0:
51
+ 9b:a0:7c:f1:72:37:3a:98:80:a0:c0:1c:72:7b:52:
52
+ 6b:3b:e2:9b:59:35:f2:56:76:6e:c4:c9:7a:21:f8:
53
+ b3:c0:4b:3f:94:f4:63:0f:91:6d:e9:47:68:97:b5:
54
+ 0e:24:56:0a:1a:0a:aa:85:6a:b0:3a:79:98:7e:ef:
55
+ d1:c1:29:0f:bf:0a:96:d1:e8:e7:bc:d4:b8:7f:ab:
56
+ cd:37:13:78:22:a4:3b:8f:fd:09:68:85:a9:8d:85:
57
+ cc:2d:3d:c1:e9:05:27:c2:d9:d0:73:25:70:03:5d:
58
+ 2d:84:af:9b:3d:d4:c7:70:6f:16:ac:bc:27:2b:7c:
59
+ 74:18:6a:f0:c4:54:93:36:42:f0:28:39:fe:57:ec:
60
+ 65:23:07:1e:ca:f5:3e:7b:08:b8:cd:0e:19:b6:f5:
61
+ 18:93
62
+ Exponent: 65537 (0x10001)
63
+ X509v3 extensions:
64
+ X509v3 Key Usage:
65
+ Digital Signature, Non Repudiation, Certificate Sign, CRL Sign
66
+ X509v3 Basic Constraints: critical
67
+ CA:TRUE
68
+ X509v3 Subject Key Identifier:
69
+ CB:9D:7E:51:7E:08:20:C4:F5:70:94:A1:CE:52:C7:05:4D:3F:33:F3
70
+ X509v3 CRL Distribution Points:
71
+ URI:http://www.wmcert.com/CertEnroll/WebMoney%20Transfer%20Root%20Authority.crl
72
+
73
+ 1.3.6.1.4.1.311.21.1:
74
+ ...
75
+ Signature Algorithm: sha1WithRSAEncryption
76
+ 6a:1b:2b:f9:15:5a:55:e0:c2:b4:55:85:cf:16:a5:21:b3:25:
77
+ 5c:48:3a:8c:fa:1b:b8:53:43:80:d1:c2:0a:1c:e5:d1:57:a0:
78
+ 5c:6c:3c:ec:36:2d:7e:e8:75:40:da:fa:fd:3c:87:08:55:34:
79
+ 65:19:77:14:f7:92:5c:41:ed:ed:8d:b5:d0:34:d3:29:29:c8:
80
+ 0b:d1:83:16:d2:27:cc:03:6a:ae:e7:2e:a7:25:32:2e:ee:b2:
81
+ 82:11:25:2d:b0:cc:d0:52:77:1c:69:79:98:9f:40:c2:85:8b:
82
+ af:3c:e6:db:e6:cb:9f:45:59:6c:1c:bf:46:73:dd:1e:46:24:
83
+ 7c:96:87:da:0e:a2:0c:f3:6b:c4:4e:c4:04:22:3d:4c:d6:27:
84
+ d4:80:3e:4b:c5:9b:b0:43:c7:dd:11:26:7f:18:79:31:0a:8b:
85
+ 1a:f5:81:bb:59:92:93:30:48:0f:49:7a:4b:99:df:b2:db:83:
86
+ 64:94:c8:bd:71:bf:b4:74:97:1e:f3:83:a0:31:47:c5:03:16:
87
+ 0e:ef:59:64:73:47:49:e4:1e:d3:26:ca:92:62:6c:27:8f:4c:
88
+ 78:c3:7d:80:bf:74:e2:10:93:90:32:08:40:25:5b:1d:3c:98:
89
+ 84:cd:48:87:31:50:ec:01:bc:97:43:4d:e0:64:8c:9e:c4:5a:
90
+ 65:e1:00:f2
data/lib/messenger.rb ADDED
@@ -0,0 +1,37 @@
1
+ require 'iconv'
2
+ require 'thread'
3
+
4
+ class Webmoney
5
+
6
+ class Messenger
7
+
8
+ def initialize(owner)
9
+ @webmoney = owner
10
+ @queue = Queue.new
11
+ @thread = Thread.new(@queue) do |q|
12
+ loop do
13
+ msg = q.pop
14
+ unless msg.nil?
15
+ begin
16
+ result = @webmoney.request(:send_message, msg)
17
+ @queue.push(msg) unless result.kind_of?(Hash)
18
+ rescue ResultError
19
+ puts "ResultError: #{@webmoney.error} #{@webmoney.errormsg}"
20
+ # Silent drop message
21
+ rescue ResponseError
22
+ puts "ResponseError: #{@webmoney.error}"
23
+ # Requeue message
24
+ @queue.push(msg)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ def push(msg)
32
+ @queue.push(msg)
33
+ end
34
+
35
+ end
36
+
37
+ end
data/lib/passport.rb ADDED
@@ -0,0 +1,44 @@
1
+ require 'hpricot'
2
+
3
+ # Class for store attestat information
4
+ class Webmoney
5
+ class Passport < Wmid
6
+
7
+ # doc - Hpricot::Doc or xml-string
8
+ def initialize(doc)
9
+ doc = Hpricot.XML(doc) unless doc.kind_of?(Hpricot::Doc)
10
+ root = doc.at('/response')
11
+ if root && root['retval'] && root['retval'].to_i == 0
12
+ super(doc.at('/response/certinfo')['wmid'])
13
+ tid = doc.at('/response/certinfo/attestat/row')['tid'].to_i
14
+ recalled = doc.at('/response/certinfo/attestat/row')['recalled'].to_i
15
+ locked = doc.at('/response/certinfo/userinfo/value/row')['locked'].to_i
16
+ @attestat = ( recalled + locked > 0) ? ALIAS : tid
17
+ @created_at = Time.xmlschema(doc.at('/response/certinfo/attestat/row')['datecrt'])
18
+
19
+ # TODO more attestat fields...
20
+
21
+ # Make all instance variables readable
22
+ instance_variables.each do |n|
23
+ class << self; self; end.instance_eval {
24
+ attr_reader n.sub(/^@/, '')
25
+ }
26
+ end
27
+ end
28
+ end
29
+
30
+ # Attestate types
31
+ ALIAS = 100
32
+ FORMAL = 110
33
+ START = 120
34
+ PERSONAL = 130
35
+ PAYER = 135
36
+ CAPITALLER = 136
37
+ DEVELOPER = 140
38
+ REGISTRATOR = 150
39
+ GARANT = 170
40
+ SERVICE = 190
41
+ SERVICE2 = 200
42
+ OPERATOR = 300
43
+ end
44
+ end
data/lib/webmoney.rb ADDED
@@ -0,0 +1,237 @@
1
+ require File.dirname(__FILE__) +'/wmsigner'
2
+ require 'time'
3
+ require 'net/http'
4
+ require 'net/https'
5
+ require 'rubygems'
6
+ require 'iconv'
7
+ require 'builder'
8
+ require 'hpricot'
9
+
10
+ class Object
11
+ def blank?
12
+ respond_to?(:empty?) ? empty? : !self
13
+ end
14
+ end
15
+
16
+ # Main class for Webmoney lib. Instance contain info
17
+ # for Webmoney interfaces requests (wmid, key, etc).
18
+ # Implement base requests to Webmoney.
19
+ class Webmoney
20
+
21
+ # Error classes
22
+ class WebmoneyError < StandardError; end
23
+ class RequestError < WebmoneyError; end
24
+ class ResultError < WebmoneyError; end
25
+ class IncorrectWmidError < WebmoneyError; end
26
+ class CaCertificateError < WebmoneyError; end
27
+
28
+ require File.dirname(__FILE__) + '/../lib/wmid'
29
+ require File.dirname(__FILE__) + '/../lib/passport'
30
+ require File.dirname(__FILE__) + '/../lib/messenger'
31
+
32
+ attr_reader :wmid, :error, :errormsg, :last_request, :messenger
33
+
34
+ # Required options:
35
+ # :wmid (WMID)
36
+ # :password (on Classic key or Light X509 certtificate & key)
37
+ # :key (Base64 string for Classic key)
38
+ # OR TODO!
39
+ # :key (OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object) AND
40
+ # :cert OpenSSL::X509::Certificate object
41
+ # Optional:
42
+ # :ca_cert (path of a CA certification file in PEM format)
43
+ def initialize(opt = {})
44
+ @wmid = Wmid.new(opt[:wmid])
45
+
46
+ # classic or light
47
+ case opt[:key]
48
+ when String
49
+ @signer = Signer.new(@wmid, opt[:password], opt[:key])
50
+ when OpenSSL::PKey::RSA, OpenSSL::PKey::DSA
51
+ @key = opt[:key]
52
+ @cert = opt[:cert]
53
+ @password = opt[:password]
54
+ end
55
+
56
+ # ca_cert or default
57
+ @ca_cert =
58
+ if opt[:ca_cert].nil?
59
+ File.dirname(__FILE__) + '/../lib/WebMoneyCA.crt'
60
+ else
61
+ opt[:ca_cert]
62
+ end
63
+
64
+ w3s = 'https://w3s.wmtransfer.com/asp/'
65
+
66
+ @interfaces = {
67
+ 'create_invoice' => URI.parse( w3s + 'XMLInvoice.asp' ), # x1
68
+ 'create_transaction' => URI.parse( w3s + 'XMLTrans.asp' ), # x2
69
+ 'operation_history' => URI.parse( w3s + 'XMLOperations.asp' ), # x3
70
+ 'outgoing_invoices' => URI.parse( w3s + 'XMLOutInvoices.asp' ), # x4
71
+ 'finish_protect' => URI.parse( w3s + 'XMLFinishProtect.asp' ), # x5
72
+ 'send_message' => URI.parse( w3s + 'XMLSendMsg.asp'), # x6
73
+ 'check_sign' => URI.parse( w3s + 'XMLClassicAuth.asp'), # x7
74
+ 'find_wm' => URI.parse( w3s + 'XMLFindWMPurse.asp'), # x8
75
+ 'balance' => URI.parse( w3s + 'XMLPurses.asp'), # x9
76
+ 'incoming_invoices' => URI.parse( w3s + 'XMLInInvoices.asp'), # x10
77
+ 'get_passport' => URI.parse( 'https://passport.webmoney.ru/asp/XMLGetWMPassport.asp'), # x11
78
+ 'reject_protection' => URI.parse( w3s + 'XMLRejectProtect.asp'), # x13
79
+ 'transaction_moneyback' => URI.parse( w3s + 'XMLTransMoneyback.asp'), # 14
80
+ 'i_trust' => URI.parse( w3s + 'XMLTrustList.asp'), # x15
81
+ 'trust_me' => URI.parse( w3s + 'XMLTrustList2.asp'), # x15
82
+ 'trust_save' => URI.parse( w3s + 'XMLTrustSave2.asp'), # x15
83
+ 'create_purse' => URI.parse( w3s + 'XMLCreatePurse.asp'), # x16
84
+ 'bussines_level' => URI.parse( 'https://stats.wmtransfer.com/levels/XMLWMIDLevel.aspx')
85
+ }
86
+ # Iconv.new(to, from)
87
+ @ic_in = Iconv.new('UTF-8', 'CP1251')
88
+ @ic_out = Iconv.new('CP1251', 'UTF-8')
89
+ end
90
+
91
+ def classic?
92
+ ! @signer.nil?
93
+ end
94
+
95
+ # Send message through Queue and Thread
96
+ # Params - :wmid, :subj, :text
97
+ def send_message(params)
98
+ @messenger = Messenger.new(self) if @messenger.nil?
99
+ @messenger.push(params)
100
+ end
101
+
102
+ # ================================================
103
+ # Main interface function
104
+ # ================================================
105
+ def request(iface, opt ={})
106
+ reqn = reqn()
107
+ raise ArgumentError unless opt.kind_of?(Hash)
108
+ opt[:wmid] = @wmid if opt[:wmid].nil?
109
+ x = Builder::XmlMarkup.new(:indent => 1)
110
+ x.instruct!(:xml, :version=>"1.0", :encoding=>"windows-1251")
111
+ unless [:get_passport, :bussines_level].include?(iface)
112
+ x.tag!('w3s.request') do
113
+ x.wmid @wmid
114
+ case iface
115
+ when :check_sign then
116
+ plan_out = @ic_out.iconv(opt[:plan])
117
+ x.testsign do
118
+ x.wmid opt[:wmid]
119
+ x.plan { x.cdata! plan_out }
120
+ x.sign opt[:sign]
121
+ end
122
+ plan = @wmid + opt[:wmid] + plan_out + opt[:sign]
123
+ when :send_message
124
+ x.reqn reqn
125
+ msgsubj = @ic_out.iconv(opt[:subj])
126
+ msgtext = @ic_out.iconv(opt[:text])
127
+ x.message do
128
+ x.receiverwmid opt[:wmid]
129
+ x.msgsubj { x.cdata! msgsubj }
130
+ x.msgtext { x.cdata! msgtext }
131
+ end
132
+ plan = opt[:wmid] + reqn + msgtext + msgsubj
133
+ end
134
+ x.sign sign(plan) if classic?
135
+ end
136
+ else
137
+ case iface
138
+ when :bussines_level
139
+ x.tag!('WMIDLevel.request') do
140
+ x.signerwmid @wmid
141
+ x.wmid opt[:wmid]
142
+ end
143
+ when :get_passport
144
+ x.request do
145
+ x.wmid @wmid
146
+ x.passportwmid opt[:wmid]
147
+ x.params { x.dict 0; x.info 1; x.mode 0 }
148
+ x.sign sign(@wmid + opt[:wmid]) if classic?
149
+ end
150
+ end
151
+ end
152
+
153
+ # Request do!
154
+ res = https_request(iface, x.target!)
155
+
156
+ # Parse response
157
+ parse_retval(res)
158
+ doc = Hpricot.XML(res)
159
+ case iface
160
+ when :check_sign
161
+ return doc.at('//testsign/res').inner_html == 'yes' ? true : false
162
+ when :get_passport
163
+ return Passport.new(doc)
164
+ when :bussines_level
165
+ return doc.at('//level').inner_html.to_i
166
+ when :send_message
167
+ time = doc.at('//message/datecrt').inner_html
168
+ m = time.match(/(\d{4})(\d{2})(\d{2}) (\d{2}):(\d{2}):(\d{2})/)
169
+ time = Time.mktime(*m[1..6])
170
+ return {:id => doc.at('//message')['id'], :date => time}
171
+ end
172
+ end
173
+
174
+ protected
175
+
176
+ # Signing string by instance wmid's
177
+ # Return signed string
178
+ def sign(str)
179
+ @signer.sign(str) unless str.blank?
180
+ end
181
+
182
+ # Make HTTPS request, return result body if 200 OK
183
+ def https_request(iface, xml)
184
+ url = case iface
185
+ when Symbol
186
+ @interfaces[iface.to_s]
187
+ when String
188
+ URI.parse(iface)
189
+ end
190
+ http = Net::HTTP.new(url.host, url.port)
191
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
192
+ if File.file? @ca_cert
193
+ http.ca_file = @ca_cert
194
+ else
195
+ raise CaCertificateError
196
+ end
197
+ http.use_ssl = true
198
+ @last_request = xml
199
+ result = http.post( url.path, xml, "Content-Type" => "text/xml" )
200
+ case result
201
+ when Net::HTTPSuccess
202
+ # replace root tag for Hpricot
203
+ res = result.body.gsub(/(w3s\.response|WMIDLevel\.response)/,'w3s_response')
204
+ return @ic_in.iconv(res)
205
+ else
206
+ @error = result.code
207
+ @errormsg = result.body if result.class.body_permitted?()
208
+ raise RequestError
209
+ end
210
+ end
211
+
212
+ def parse_retval(response_xml)
213
+ doc = Hpricot.XML(response_xml)
214
+ retval_element = doc.at('//retval')
215
+ # Workaround for passport interface
216
+ unless retval_element.nil?
217
+ retval = retval_element.inner_html.to_i
218
+ retdesc = doc.at('//retdesc').inner_html unless doc.at('//retdesc').nil?
219
+ else
220
+ retval = doc.at('//response')['retval'].to_i
221
+ retdesc = doc.at('//response')['retdesc']
222
+ end
223
+ unless retval == 0
224
+ @error = retval
225
+ @errormsg = retdesc
226
+ raise ResultError
227
+ end
228
+ end
229
+
230
+ # Create unique Request Number based on time
231
+ # Return 16 digits string
232
+ def reqn
233
+ t = Time.now
234
+ t.strftime('%Y%m%d%H%M%S') + t.to_f.to_s.match(/\.(\d\d)/)[1]
235
+ end
236
+
237
+ end