File Coverage

blib/lib/EAFDSS/Dummy.pm
Criterion Covered Total %
statement 165 489 33.7
branch 11 104 10.5
condition n/a
subroutine 23 28 82.1
pod 18 18 100.0
total 217 639 33.9


line stmt bran cond sub pod time code
1             # EAFDSS - Electronic Fiscal Signature Devices Library
2             # Ειδική Ασφαλής Φορολογική Διάταξη Σήμανσης (ΕΑΦΔΣΣ)
3             #
4             # Copyright (C) 2008 Hasiotis Nikos
5             #
6             # ID: $Id: Dummy.pm 105 2009-05-18 10:52:03Z hasiotis $
7              
8             package EAFDSS::Dummy;
9              
10             =head1 NAME
11              
12             EAFDSS::Dummy - EAFDSS Driver for a Dummy filesystem based device
13              
14             =head1 DESCRIPTION
15              
16             You can't directly use that module. Read EAFDSS manual page on how to use the library. What
17             follows is a list of all the functions that the Dummy driver implements in order to be complete
18             EAFDSS driver. This driver is not to be used on production. It is used for automated test of
19             the "Base" Class. Also it could be used during the development of applications without a device
20             or the emulator
21              
22             =cut
23              
24 1     1   32 use 5.006_000;
  1         4  
  1         60  
25 1     1   8 use strict;
  1         2  
  1         54  
26 1     1   6 use warnings;
  1         2  
  1         36  
27 1     1   6 use Carp;
  1         1  
  1         972  
28 1     1   6 use Class::Base;
  1         2  
  1         21  
29 1     1   1103 use Switch;
  1         83773  
  1         7  
30 1     1   303707 use Digest::SHA1 qw(sha1_hex);
  1         869  
  1         72  
31 1     1   1029 use Config::IniFiles;
  1         31208  
  1         46  
32              
33 1     1   11 use base qw ( EAFDSS::Base );
  1         24  
  1         811  
34              
35             our($VERSION) = '0.80';
36              
37             =head1 Methods
38              
39             =head2 init
40              
41             =cut
42              
43             sub init {
44 4     4 1 92 my($class) = shift @_;
45 4         8 my($config) = @_;
46 4         27 my($self) = $class->SUPER::init(@_);
47              
48 4         22 $self->debug(" [PROTO] Initializing");
49              
50 4 50       16 if (! exists $config->{PARAMS}) {
51 0         0 return $self->error("No parameters have been given!");
52             } else {
53 4         11 $self->{FILENAME} = $config->{PARAMS};
54             }
55              
56 4 50       92 if ( ! -e $self->{FILENAME} ) {
57 4 50       320 open(DUMMY, ">", $self->{FILENAME}) || croak "Error: $!";
58 4         36 print(DUMMY "[MAIN]\n");
59 4         12 print(DUMMY "VERSION = Dummy EAFDSS\n");
60 4         17 print(DUMMY "SERIAL = $self->{SN}\n");
61 4         8 print(DUMMY "MAX_FISCAL = 100\n");
62 4         7 print(DUMMY "MAX_SIGNS = 2400\n");
63 4         9 print(DUMMY "CUR_FISCAL = 1\n");
64 4         8 print(DUMMY "CUR_SIGN = 1\n");
65 4         8 print(DUMMY "TOTAL_SIGN = 1\n\n");
66 4         9 print(DUMMY "CMOS_ERROR = 0\n\n");
67 4         6 print(DUMMY "[FISCAL]\n\n");
68 4         8 print(DUMMY "[SIGNS]\n");
69 4         187 close(DUMMY);
70             }
71              
72 4         13 return $self;
73             }
74              
75             =head1 Methods
76              
77             =head2 PROTO_GetSign
78              
79             =cut
80              
81             sub PROTO_GetSign {
82 5     5 1 15 my($self) = shift @_;
83 5         14 my($invoice) = shift @_;
84              
85 5         9 my($replyCode, $totalSigns, $dailySigns, $date, $time, $sign, $nextZ, $maxFiscal, $maxSigns);
86              
87 5         21 $self->debug(" [PROTO] Get Sign");
88              
89 5         188 my($sec, $min, $hour, $mday, $mon, $year) = localtime();
90 5         33 $date = sprintf("%02d%02d%02d", $mday, $mon+1, $year - 100);
91 5         17 $time = sprintf("%02d%02d%02d", $hour, $min, $sec);
92              
93 5         53 my($dummy) = Config::IniFiles->new(-file => $self->{FILENAME});
94              
95 5         15344 $totalSigns = $dummy->val('MAIN', 'TOTAL_SIGN');
96 5         126 $dailySigns = $dummy->val('MAIN', 'CUR_SIGN');
97 5         104 $nextZ = $dummy->val('MAIN', 'CUR_FISCAL');
98              
99 5         96 $maxFiscal = $dummy->val('MAIN', 'MAX_FISCAL');
100 5         100 $maxSigns = $dummy->val('MAIN', 'MAX_SIGNS');
101              
102 5 50       108 if ($dailySigns >= $maxSigns) {
103 0         0 return (-1);
104             }
105              
106 5         21 $dummy->newval('MAIN', 'TOTAL_SIGN', $totalSigns + 1);
107 5         395 $dummy->newval('MAIN', 'CUR_SIGN', $dailySigns + 1);
108              
109 5         385 $invoice .= sprintf("%s%08d%04d%s%s", $self->{SN}, $totalSigns, $dailySigns, $self->UTIL_date6ToHost($date), $self->UTIL_time6toHost($time));
110              
111 5         62 $sign = uc(sha1_hex($invoice));
112 5         23 my($sign_entry) = sprintf("%s,%s,%s,%s,%s", $date, $time, $dailySigns, $totalSigns, $sign);
113 5         20 $dummy->newval('SIGNS', $dailySigns, $sign_entry);
114              
115 5         403 $dummy->RewriteConfig();
116              
117 5         7069 return (0, $totalSigns, $dailySigns, $date, $time, $nextZ, $sign);
118             }
119              
120             =head2 PROTO_SetHeader
121              
122             =cut
123              
124             sub PROTO_SetHeader {
125 0     0 1 0 my($self) = shift @_;
126 0         0 my($headers) = shift @_;
127              
128 0         0 $self->debug(" [PROTO] Set Headers");
129 0         0 return 64+04;
130             }
131              
132             =head2 PROTO_GetStatus
133              
134             =cut
135              
136             sub PROTO_GetStatus {
137 8     8 1 21 my($self) = shift @_;
138              
139 8         26 $self->debug(" [PROTO] Get Status");
140 8 50       120 if (-e $self->{FILENAME}) {
141 8         30 $self->debug(" [SPECIAL] Setting CMOS to error");
142 8         131 my($dummy) = Config::IniFiles->new(-file => $self->{FILENAME});
143 8         25865 my($cmos) = $dummy->val('MAIN', 'CMOS_ERROR');
144 8 100       280 if ($cmos) {
145 1         21 return (0, "00010000", 0);
146             } else {
147 7         152 return (0, 0, 0);
148             }
149             } else {
150 0         0 return ($self->error());
151             }
152             }
153              
154             =head2 PROTO_GetHeader
155              
156             =cut
157              
158             sub PROTO_GetHeader {
159 0     0 1 0 my($self) = shift @_;
160              
161 0         0 $self->debug(" [PROTO] Get Headers");
162 0         0 return 64+04;
163             }
164              
165             =head2 PROTO_ReadTime
166              
167             =cut
168              
169             sub PROTO_ReadTime {
170 1     1 1 4 my($self) = shift @_;
171              
172 1         5 $self->debug(" [PROTO] Read Time");
173 1         37 my($sec, $min, $hour, $mday, $mon, $year) = localtime();
174 1         10 return (0, sprintf("%02d/%02d/%02d %02d:%02d:%02d", $mday, $mon+1, $year-100, $hour, $min, $sec));
175             }
176              
177             =head2 PROTO_SetTime
178              
179             =cut
180              
181             sub PROTO_SetTime {
182 0     0 1 0 my($self) = shift @_;
183 0         0 my($time) = shift @_;
184              
185 0         0 $self->debug(" [PROTO] Set Time");
186 0         0 return 64+04;
187             }
188              
189             =head2 PROTO_ReadDeviceID
190              
191             =cut
192              
193             sub PROTO_ReadDeviceID {
194 0     0 1 0 my($self) = shift @_;
195              
196 0         0 $self->debug(" [PROTO] Read Device ID");
197 0         0 my($dummy) = Config::IniFiles->new(-file => $self->{FILENAME});
198              
199 0 0       0 if ($dummy) {
200 0         0 my($deviceId) = $dummy->val('MAIN', 'SERIAL');
201 0         0 return (0, $deviceId);
202             } else {
203 0         0 return (-1);
204             }
205             }
206              
207             =head2 PROTO_VersionInfo
208              
209             =cut
210              
211             sub PROTO_VersionInfo {
212 1     1 1 4 my($self) = shift @_;
213              
214 1         5 $self->debug(" [PROTO] Read Device Version");
215 1         13 my($dummy) = Config::IniFiles->new(-file => $self->{FILENAME});
216              
217 1 50       3460 if ($dummy) {
218 1         6 my($version) = $dummy->val('MAIN', 'VERSION');
219 1         41 return (0, $version);
220             } else {
221 0         0 return (-1);
222             }
223             }
224              
225             =head2 PROTO_ReadSignEntry
226              
227             =cut
228              
229             sub PROTO_ReadSignEntry {
230 1     1 1 3 my($self) = shift @_;
231 1         3 my($index) = shift @_;
232              
233 1         5 $self->debug(" [PROTO] Read Sign Entry");
234 1         11 my($dummy) = Config::IniFiles->new(-file => $self->{FILENAME});
235              
236 1 50       3407 if ($dummy) {
237 1         13 my($date, $time, $dailySigns, $totalSigns, $sign, $closure) = split(/,/, $dummy->val('SIGNS', $index));
238 1         48 return (0, 1, 1, $totalSigns, $dailySigns, $date, $time, $sign, $self->{SN}, $closure);
239             } else {
240 0         0 return (-1);
241             }
242              
243             }
244              
245             =head2 PROTO_ReadClosure
246              
247             =cut
248              
249             sub PROTO_ReadClosure {
250 6     6 1 13 my($self) = shift @_;
251 6         12 my($index) = shift @_;
252 6         12 my(%reply, $replyCode, $z, $curZ, $date, $time, $dailySigns, $totalSigns, $closure);
253              
254 6         29 $self->debug(" [PROTO] Read Closure [%d]", $index);
255 6         68 my($dummy) = Config::IniFiles->new(-file => $self->{FILENAME});
256              
257 6         25223 $curZ = $dummy->val('MAIN', 'CUR_FISCAL');
258 6 100       157 if ($index == 0) {
259 5         27 ($date, $time, $dailySigns, $totalSigns, $z) = split(/,/, $dummy->val('FISCAL', $curZ-1));
260             } else {
261 1         8 ($date, $time, $dailySigns, $totalSigns, $z) = split(/,/, $dummy->val('FISCAL', $index));
262             }
263 6         165 $closure = $curZ-1;
264              
265 6         36 return (0, 1, 1, $totalSigns, $dailySigns, $self->UTIL_date6ToHost($date), $self->UTIL_time6toHost($time), $z, $self->{SN}, $closure);
266             }
267              
268             =head2 PROTO_ReadSummary
269              
270             =cut
271              
272             sub PROTO_ReadSummary {
273 12     12 1 29 my($self) = shift @_;
274 12         23 my(%reply, $replyCode, $status1, $status2, $lastZ, $totalSigns, $dailySigns, $maxSigns);
275              
276 12         38 $self->debug(" [PROTO] Read Summary");
277 12         107 my($dummy) = Config::IniFiles->new(-file => $self->{FILENAME});
278              
279 12         36777 $totalSigns = $dummy->val('MAIN', 'TOTAL_SIGN');
280 12         294 $dailySigns = $dummy->val('MAIN', 'CUR_SIGN');
281 12         259 $lastZ = $dummy->val('MAIN', 'CUR_FISCAL');
282              
283 12         236 $maxSigns = $dummy->val('MAIN', 'MAX_SIGNS');
284              
285 12         466 return (0, 0, 0, $lastZ-1, $totalSigns-1, $dailySigns-1, 0, $maxSigns - $dailySigns + 1);
286             }
287              
288             =head2 PROTO_IssueReport
289              
290             =cut
291              
292             sub PROTO_IssueReport {
293 5     5 1 13 my($self) = shift @_;
294 5         10 my(%reply, $replyCode, $status1, $status2, $dailySigns, $lastZ, $i, $z, $data, $time, $date, $totalSigns);
295              
296 5         16 $self->debug(" [PROTO] Issue Report");
297 5         54 my($dummy) = Config::IniFiles->new(-file => $self->{FILENAME});
298              
299 5         15752 my($sec, $min, $hour, $mday, $mon, $year) = localtime();
300 5         36 $date = sprintf("%02d%02d%02d", $mday, $mon+1, $year - 100);
301 5         18 $time = sprintf("%02d%02d%02d", $hour, $min, $sec);
302              
303 5         24 $totalSigns = $dummy->val('MAIN', 'TOTAL_SIGN');
304 5         119 $dailySigns = $dummy->val('MAIN', 'CUR_SIGN');
305 5         102 $lastZ = $dummy->val('MAIN', 'CUR_FISCAL');
306              
307 5         99 $dummy->newval('MAIN', 'CUR_FISCAL', $dummy->val('MAIN', 'CUR_FISCAL') + 1);
308              
309 5         463 $data = "";
310 5         22 for ($i=1; $i < $dummy->val('MAIN', 'CUR_SIGN'); $i++) {
311 2         48 $data .= $dummy->val('SIGNS', $i);
312             }
313              
314 5         205 $z = uc(sha1_hex($data));
315              
316 5         24 for ($i=1; $i < $dummy->val('MAIN', 'CUR_SIGN'); $i++) {
317 2         48 $dummy->delval('SIGNS', $i);
318             }
319              
320 5         261 my($z_entry) = sprintf("%s,%s,%s,%s,%s", $date, $time, $dailySigns, $totalSigns, $z);
321 5         18 $dummy->newval('FISCAL', $lastZ, $z_entry);
322 5         379 $dummy->newval('MAIN', 'CUR_SIGN', 1);
323              
324 5         365 $dummy->RewriteConfig();
325              
326 5         6744 return (0);
327             }
328              
329             =head2 errMessage
330              
331             =cut
332              
333             sub errMessage {
334 0     0 1 0 my($self) = shift @_;
335 0         0 my($errCode) = shift @_;
336              
337 0         0 switch ($errCode) {
  0         0  
  0         0  
  0         0  
338 0 0       0 case 00+0x00 { return "No errors - success"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
339              
340 0 0       0 case 00+0x01 { return "Wrong number of fields"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
341 0 0       0 case 00+0x02 { return "Field too long"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
342 0 0       0 case 00+0x03 { return "Field too small"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
343 0 0       0 case 00+0x04 { return "Field fixed size mismatch"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
344 0 0       0 case 00+0x05 { return "Field range or type check failed"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
345 0 0       0 case 00+0x06 { return "Bad request code"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
346 0 0       0 case 00+0x09 { return "Printing type bad"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
347 0 0       0 case 00+0x0A { return "Cannot execute with day open"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
348 0 0       0 case 00+0x0B { return "RTC programming requires jumper"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
349 0 0       0 case 00+0x0C { return "RTC date or time invalid"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
350 0 0       0 case 00+0x0D { return "No records in fiscal period"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
351 0 0       0 case 00+0x0E { return "Device is busy in another task"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
352 0 0       0 case 00+0x0F { return "No more header records allowed"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
353 0 0       0 case 00+0x10 { return "Cannot execute with block open"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
354 0 0       0 case 00+0x11 { return "Block not open"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
355 0 0       0 case 00+0x12 { return "Bad data stream"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
356 0 0       0 case 00+0x13 { return "Bad signature field"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
357 0 0       0 case 00+0x14 { return "Z closure time limit"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
358 0 0       0 case 00+0x15 { return "Z closure not found"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
359 0 0       0 case 00+0x16 { return "Z closure record bad"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
360 0 0       0 case 00+0x17 { return "User browsing in progress"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
361 0 0       0 case 00+0x18 { return "Signature daily limit reached"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
362 0 0       0 case 00+0x19 { return "Printer paper end detected"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
363 0 0       0 case 00+0x1A { return "Printer is offline"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
364 0 0       0 case 00+0x1B { return "Fiscal unit is offline"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
365 0 0       0 case 00+0x1C { return "Fatal hardware error"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
366 0 0       0 case 00+0x1D { return "Fiscal unit is full"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
367 0 0       0 case 00+0x1E { return "No data passed for signature"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
368 0 0       0 case 00+0x1F { return "Signature does not exist"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
369 0 0       0 case 00+0x20 { return "Battery fault detected"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
370 0 0       0 case 00+0x21 { return "Recovery in progress"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
371 0 0       0 case 00+0x22 { return "Recovery only after CMOS reset"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
372 0 0       0 case 00+0x23 { return "Real-Time Clock needs programming"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
373 0 0       0 case 00+0x24 { return "Z closure date warning"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
374 0 0       0 case 00+0x25 { return "Bad character in stream"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
375 0 0       0 case 00+0x26 { return ""}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
376 0 0       0 case 00+0x01 { return "Device not accessible"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
377              
378 0 0       0 case 64+0x01 { return "Device not accessible"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
379 0 0       0 case 64+0x02 { return "No such file"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
380 0 0       0 case 64+0x03 { return "Device Sync Failed"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
381 0 0       0 case 64+0x04 { return "Function not supported"}
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
382              
383 0         0 else { return undef}
384             }
385             }
386              
387             =head2 UTIL_devStatus
388              
389             =cut
390              
391             sub UTIL_devStatus {
392 8     8 1 20 my($self) = shift @_;
393 8         48 my($status) = sprintf("%08b", shift);
394 8         68 my(@status) = split(//, $status);
395              
396 8         38 my($busy, $fatal, $paper, $cmos, $printer, $user, $fiscal, $battery) =
397             ($status[7],$status[6],$status[5],$status[4],$status[3],$status[2],$status[1],$status[0]);
398              
399 8         68 return ($busy, $fatal, $paper, $cmos, $printer, $user, $fiscal, $battery);
400             }
401              
402             =head2 UTIL_appStatus
403              
404             =cut
405              
406             sub UTIL_appStatus {
407 1     1 1 3 my($self) = shift @_;
408              
409 1         4 my($status) = sprintf("%08b", shift);
410 1         7 my(@status) = split(//, $status);
411              
412 1         5 my($day, $signature, $recovery, $fiscalWarn, $dailyFull, $fiscalFull) =
413             ($status[6],$status[5],$status[4],$status[2],$status[1],$status[0]);
414              
415 1         6 return ($day, $signature, $recovery, $fiscalWarn, $dailyFull, $fiscalFull);
416             }
417              
418             =head2 UTIL_date6ToHost
419              
420             =cut
421              
422             sub UTIL_date6ToHost {
423 25     25 1 50 my($self) = shift @_;
424 25         41 my($var) = shift @_;
425              
426 25         234 $var =~ s/(\d\d)(\d\d)(\d\d)/$3$2$1/;
427              
428 25         176 return $var;
429             }
430              
431             =head2 UTIL_time6toHost
432              
433             =cut
434              
435             sub UTIL_time6toHost {
436 16     16 1 34 my($self) = shift @_;
437 16         37 my($var) = shift @_;
438              
439 16         73 $var =~ s/(\d\d)(\d\d)(\d\d)/$1$2/;
440              
441 16         226 return $var;
442             }
443              
444             sub _SetCMOSError {
445 1     1   10 my($self) = shift @_;
446 1         3 my($i);
447              
448 1         4 $self->debug(" [SPECIAL] Setting CMOS to error");
449 1         12 my($dummy) = Config::IniFiles->new(-file => $self->{FILENAME});
450              
451 1         3122 $dummy->newval('MAIN', 'CMOS_ERROR', 1);
452 1         82 for ($i=1; $i < $dummy->val('MAIN', 'CUR_SIGN'); $i++) {
453 1         30 $dummy->delval('SIGNS', $i);
454             }
455 1         70 $dummy->newval('MAIN', 'CUR_SIGN', 1);
456              
457 1         81 $dummy->RewriteConfig();
458             }
459              
460             # Preloaded methods go here.
461              
462             1;
463              
464             =head1 VERSION
465              
466             This is version 0.80.
467              
468             =head1 AUTHOR
469              
470             Hasiotis Nikos, Ehasiotis@gmail.comE
471              
472             =head1 COPYRIGHT AND LICENSE
473              
474             Copyright (C) 2008 by Hasiotis Nikos
475              
476             This library is free software; you can redistribute it and/or modify
477             it under the terms of the LGPL or the same terms as Perl itself,
478             either Perl version 5.8.8 or, at your option, any later version of
479             Perl 5 you may have available.
480              
481             =cut