Add the following packages libalgorithm-diff-perl libspiffy-perl libtext-diff-perl...
[pkg-perl] / deb-src / libfilter-perl / libfilter-perl-1.34 / decrypt / decrypt.xs
1 /* 
2  * Filename : decrypt.xs
3  * 
4  * Author   : Paul Marquess 
5  * Date     : 20th July 2000
6  * Version  : 1.05
7  *
8  */
9
10 #include "EXTERN.h"
11 #include "perl.h"
12 #include "XSUB.h"
13 #include "../Call/ppport.h"
14
15 #ifdef FDEBUG
16 static int fdebug = 0;
17 #endif
18
19 /* constants specific to the encryption format */
20 #define CRYPT_MAGIC_1   0xff
21 #define CRYPT_MAGIC_2   0x00
22
23 #define HEADERSIZE      2
24 #define BLOCKSIZE       4
25
26
27 #define SET_LEN(sv,len) \
28         do { SvPVX(sv)[len] = '\0'; SvCUR_set(sv, len); } while (0)
29
30
31 static unsigned XOR [BLOCKSIZE] = {'P', 'e', 'r', 'l' } ;
32
33
34 /* Internal defines */
35 #ifdef PERL_FILTER_EXISTS
36 #  define CORE_FILTER_COUNT \
37     (PL_parser && PL_parser->rsfp_filters ? av_len(PL_parser->rsfp_filters) : 0)
38 #else
39 #  define CORE_FILTER_COUNT \
40     (PL_rsfp_filters ? av_len(PL_rsfp_filters) : 0)
41 #endif
42
43 #define FILTER_COUNT(s)         IoPAGE(s)
44 #define FILTER_LINE_NO(s)       IoLINES(s)
45 #define FIRST_TIME(s)           IoLINES_LEFT(s)
46
47 #define ENCRYPT_GV(s)           IoTOP_GV(s)
48 #define ENCRYPT_SV(s)           ((SV*) ENCRYPT_GV(s))
49 #define ENCRYPT_BUFFER(s)       SvPVX(ENCRYPT_SV(s))
50 #define CLEAR_ENCRYPT_SV(s)     SvCUR_set(ENCRYPT_SV(s), 0)
51
52 #define DECRYPT_SV(s)           s
53 #define DECRYPT_BUFFER(s)       SvPVX(DECRYPT_SV(s))
54 #define CLEAR_DECRYPT_SV(s)     SvCUR_set(DECRYPT_SV(s), 0)
55 #define DECRYPT_BUFFER_LEN(s)   SvCUR(DECRYPT_SV(s))
56 #define DECRYPT_OFFSET(s)       IoPAGE_LEN(s)
57 #define SET_DECRYPT_BUFFER_LEN(s,n)     SvCUR_set(DECRYPT_SV(s), n)
58
59 static unsigned
60 Decrypt(SV *in_sv, SV *out_sv)
61 {
62         /* Here is where the actual decryption takes place */
63
64         unsigned char * in_buffer  = (unsigned char *) SvPVX(in_sv) ;
65         unsigned char * out_buffer ;
66         unsigned size = SvCUR(in_sv) ;
67         unsigned index = size ;
68         int i ;
69
70         /* make certain that the output buffer is big enough            */
71         /* as the output from the decryption can never be larger than   */
72         /* the input buffer, make it that size                          */
73         SvGROW(out_sv, size) ;
74         out_buffer = (unsigned char *) SvPVX(out_sv) ;
75
76         /* XOR */
77         for (i = 0 ; i < size ; ++i) 
78             out_buffer[i] = (unsigned char)( XOR[i] ^ in_buffer[i] ) ;
79
80         /* input has been consumed, so set length to 0 */
81         SET_LEN(in_sv, 0) ;
82
83         /* set decrypt buffer length */
84         SET_LEN(out_sv, index) ;
85
86         /* return the size of the decrypt buffer */
87         return (index) ;
88 }
89
90 static int
91 ReadBlock(int idx, SV *sv, unsigned size)
92 {   /* read *exactly* size bytes from the next filter */
93     int i = size;
94     while (1) {
95         int n = FILTER_READ(idx, sv, i) ;
96         if (n <= 0 && i==size)  /* eof/error when nothing read so far */
97             return n ;
98         if (n <= 0)             /* eof/error when something already read */
99             return size - i;
100         if (n == i)
101             return size ;
102         i -= n ;
103     }
104 }
105
106 static void
107 preDecrypt(int idx)
108 {
109     /*  If the encrypted data starts with a header or needs to do some
110         initialisation it can be done here 
111
112         In this case the encrypted data has to start with a fingerprint,
113         so that is checked.
114     */
115
116     SV * sv = FILTER_DATA(idx) ;
117     unsigned char * buffer ;
118
119
120     /* read the header */
121     if (ReadBlock(idx+1, sv, HEADERSIZE) != HEADERSIZE)
122         croak("truncated file") ;
123
124     buffer = (unsigned char *) SvPVX(sv) ;
125
126     /* check for fingerprint of encrypted data */
127     if (buffer[0] != CRYPT_MAGIC_1 || buffer[1] != CRYPT_MAGIC_2) 
128             croak( "bad encryption format" );
129 }
130
131 static void
132 postDecrypt()
133 {
134 }
135
136 static I32
137 filter_decrypt(pTHX_ int idx, SV *buf_sv, int maxlen)
138 {
139     SV   *my_sv = FILTER_DATA(idx);
140     char *nl = "\n";
141     char *p;
142     char *out_ptr;
143     int n;
144
145     /* check if this is the first time through */
146     if (FIRST_TIME(my_sv)) {
147
148         /* Mild paranoia mode - make sure that no extra filters have    */
149         /* been applied on the same line as the use Filter::decrypt     */
150         if (CORE_FILTER_COUNT > FILTER_COUNT(my_sv) )
151             croak("too many filters") ; 
152
153         /* As this is the first time through, so deal with any          */
154         /* initialisation required                                      */
155         preDecrypt(idx) ;
156
157         FIRST_TIME(my_sv) = FALSE ;
158         SET_LEN(DECRYPT_SV(my_sv), 0) ;
159         SET_LEN(ENCRYPT_SV(my_sv), 0) ;
160         DECRYPT_OFFSET(my_sv)    = 0 ;
161     }
162
163 #ifdef FDEBUG
164     if (fdebug)
165         warn("**** In filter_decrypt - maxlen = %d, len buf = %d idx = %d\n", 
166                 maxlen, SvCUR(buf_sv), idx ) ;
167 #endif
168
169     while (1) {
170
171         /* anything left from last time */
172         if ((n = SvCUR(DECRYPT_SV(my_sv)))) {
173
174             out_ptr = SvPVX(DECRYPT_SV(my_sv)) + DECRYPT_OFFSET(my_sv) ;
175
176             if (maxlen) { 
177                 /* want a block */ 
178 #ifdef FDEBUG
179                 if (fdebug)
180                     warn("BLOCK(%d): size = %d, maxlen = %d\n", 
181                         idx, n, maxlen) ;
182 #endif
183
184                 sv_catpvn(buf_sv, out_ptr, maxlen > n ? n : maxlen );
185                 if(n <= maxlen) {
186                     DECRYPT_OFFSET(my_sv) = 0 ;
187                     SET_LEN(DECRYPT_SV(my_sv), 0) ;
188                 }
189                 else {
190                     DECRYPT_OFFSET(my_sv) += maxlen ;
191                     SvCUR_set(DECRYPT_SV(my_sv), n - maxlen) ;
192                 }
193                 return SvCUR(buf_sv);
194             }
195             else {
196                 /* want lines */
197                 if ((p = ninstr(out_ptr, out_ptr + n, nl, nl + 1))) {
198
199                     sv_catpvn(buf_sv, out_ptr, p - out_ptr + 1);
200
201                     n = n - (p - out_ptr + 1);
202                     DECRYPT_OFFSET(my_sv) += (p - out_ptr + 1) ;
203                     SvCUR_set(DECRYPT_SV(my_sv), n) ;
204 #ifdef FDEBUG 
205                     if (fdebug)
206                         warn("recycle %d - leaving %d, returning %d [%.999s]", 
207                                 idx, n, SvCUR(buf_sv), SvPVX(buf_sv)) ;
208 #endif
209
210                     return SvCUR(buf_sv);
211                 }
212                 else /* no EOL, so append the complete buffer */
213                     sv_catpvn(buf_sv, out_ptr, n) ;
214             }
215             
216         }
217
218
219         SET_LEN(DECRYPT_SV(my_sv), 0) ;
220         DECRYPT_OFFSET(my_sv) = 0 ;
221
222         /* read from the file into the encrypt buffer */
223         if ( (n = ReadBlock(idx+1, ENCRYPT_SV(my_sv), BLOCKSIZE)) <= 0)
224         {
225             /* Either EOF or an error */
226
227 #ifdef FDEBUG
228             if (fdebug)
229                 warn ("filter_read %d returned %d , returning %d\n", idx, n,
230                     (SvCUR(buf_sv)>0) ? SvCUR(buf_sv) : n);
231 #endif
232
233             /* If the decrypt code needs to tidy up on EOF/error, 
234                 now is the time  - here is a hook */
235             postDecrypt() ; 
236
237             filter_del(filter_decrypt);  
238
239  
240             /* If error, return the code */
241             if (n < 0)
242                 return n ;
243
244             /* return what we have so far else signal eof */
245             return (SvCUR(buf_sv)>0) ? SvCUR(buf_sv) : n;
246         }
247
248 #ifdef FDEBUG
249         if (fdebug)
250             warn("  filter_decrypt(%d): sub-filter returned %d: '%.999s'",
251                 idx, n, SvPV(my_sv,PL_na));
252 #endif
253
254         /* Now decrypt a block */
255         n = Decrypt(ENCRYPT_SV(my_sv), DECRYPT_SV(my_sv)) ;
256
257 #ifdef FDEBUG 
258         if (fdebug) 
259             warn("Decrypt (%d) returned %d [%.999s]\n", idx, n, SvPVX(DECRYPT_SV(my_sv)) ) ;
260 #endif 
261
262     }
263 }
264
265
266 MODULE = Filter::decrypt        PACKAGE = Filter::decrypt
267
268 PROTOTYPES:     DISABLE
269
270 BOOT:
271     /* Check for the presence of the Perl Compiler */
272     if (gv_stashpvn("B", 1, FALSE))
273         croak("Aborting, Compiler detected") ;
274 #ifndef BYPASS
275     /* Don't run if this module is dynamically linked */
276     if (!isALPHA(SvPV(GvSV(CvFILEGV(cv)), PL_na)[0]))
277         croak("module is dynamically linked. Recompile as a static module") ;
278 #ifdef DEBUGGING
279         /* Don't run if compiled with DEBUGGING */
280         croak("recompile without -DDEBUGGING") ;
281 #endif
282         
283         /* Double check that DEBUGGING hasn't been enabled */
284         if (PL_debug)
285             croak("debugging flags detected") ;
286 #endif
287
288
289 void
290 import(module)
291     SV *        module
292     PPCODE:
293     {
294
295         SV * sv = newSV(BLOCKSIZE) ;
296
297         /* make sure the Perl debugger isn't enabled */
298         if( PL_perldb )
299             croak("debugger disabled") ;
300
301         filter_add(filter_decrypt, sv) ;
302         FIRST_TIME(sv) = TRUE ;
303
304         ENCRYPT_GV(sv) = (GV*) newSV(BLOCKSIZE) ;
305         (void)SvPOK_only(DECRYPT_SV(sv));
306         (void)SvPOK_only(ENCRYPT_SV(sv));
307         SET_LEN(DECRYPT_SV(sv), 0) ;
308         SET_LEN(ENCRYPT_SV(sv), 0) ;
309
310
311         /* remember how many filters are enabled */
312         FILTER_COUNT(sv) = CORE_FILTER_COUNT ;
313         /* and the line number */
314         FILTER_LINE_NO(sv) = PL_curcop->cop_line ;
315
316     }
317
318 void
319 unimport(...)
320     PPCODE:
321     /* filter_del(filter_decrypt); */