Download | Plain Text | No Line Numbers
    - #include <assert.h>
- #include "EXTERN.h"
- #include "perl.h"
- #include "XSUB.h"
- #include "ppport.h"
- #include "../cipher.h"
-  
- #define BLOCKSIZE 8192
-  
- #define SET_LEN(sv, len) \
-   do { SvPVX(sv)[len] = '\0'; SvCUR_set(sv, len); } while (0)
-  
- /* Internal defines */
- #ifdef PERL_FILTER_EXISTS
- # define CORE_FILTER_COUNT \
-     ((PL_parser && PL_parser->rsfp_filters) ? av_len(PL_parser->rsfp_filters) : 0)
- #else
- # define CORE_FILTER_COUNT \
-     ((PL_rsfp_filters) ? av_len(PL_rsfp_filters) : 0)
- #endif
-  
- #define FILTER_COUNT(s)               IoPAGE(s)
- #define FILTER_LINE_NO(s)             IoLINES(s)
- #define FIRST_TIME(s)                 IoLINES_LEFT(s)
-  
- #define CIPHER_GV(s)                  IoFMT_GV(s)
- #define CIPHER_SV(s)                  ((SV *) CIPHER_GV(s))
- #define CIPHER_BUFFER(s)              ((ctx_t *)SvPVX(CIPHER_SV(s)))
- #define CLEAR_CIPHER_SV(s)            SvCUR_set(CIPHER_SV(s), 0)
-  
- #define ENCRYPT_GV(s)                 IoTOP_GV(s)
- #define ENCRYPT_SV(s)                 ((SV *) ENCRYPT_GV(s))
- #define ENCRYPT_BUFFER(s)             SvPVX(ENCRYPT_SV(s))
- #define CLEAR_ENCRYPT_SV(s)           SvCUR_set(ENCRYPT_SV(s), 0)
-  
- #define DECRYPT_SV(s)                 s
- #define DECRYPT_BUFFER(s)             SvPVX(DECRYPT_SV(s))
- #define CLEAR_DECRYPT_SV(s)           SvCUR_set(DECRYPT_SV(s), 0)
- #define DECRYPT_BUFFER_LEN(s)         SvCUR(DECRYPT_SV(s))
- #define DECRYPT_OFFSET(s)             IoPAGE_LEN(DECRYPT_SV(s))
- #define SET_DECRYPT_BUFFER_LEN(s, n)  SvCUR_set(DECRYPT_SV(s), n)
-  
- static unsigned
- decrypt(SV *in_cipher, SV *in_sv, SV *out_sv)
- {
-   /* here is where the actual decryption takes place */
-   ctx_t *cipher = (ctx_t *)SvPVX(in_cipher);
-   char *in_buffer = (char *)SvPVX(in_sv);
-   char *out_buffer;
-   size_t in_len = SvCUR(in_sv);
-   size_t out_len;
-  
-   /* make certain that the output buffer is big enough
-    * as the output from the decryption can never be larger than
-    * the input buffer, make it that size
-    */
-   SvGROW(out_sv, in_len);
-   out_buffer = (char *)SvPVX(out_sv);
-  
-   /* decrypt */
-   out_len = CipherUpdate(cipher, in_buffer, in_len);
-  
-   /* input has been consumed, so set length to 0 */
-   SET_LEN(in_sv, 0);
-  
-   /* set decrypt buffer length */
-   SET_LEN(out_sv, out_len);
-  
-   /* return the size of the decrypt buffer */
-   return out_len;
- }
-  
- static int
- readblock(int idx, SV *sv, unsigned size)
- {
-   /* read *exactly* size bytes from the next filter */
-   int i = size;
-   while (1)
-   {
-     int n = FILTER_READ(idx, sv, i);
-     /* eof/error when nothing read so far */
-     if (n <= 0 && i == size)
-       return n;
-     /* eof/error when something already read */
-     if (n <= 0)
-       return size - i;
-     if (n == i)
-       return size;
-     i -= n;
-   }
- }
-  
- static void
- pre_decrypt(int idx)
- {}
-  
- static void
- post_decrypt(int idx)
- {}
-  
- static I32
- filter_decrypt(pTHX_ int idx, SV *buf_sv, int maxlen)
- {
-   char *out_ptr;
-   char *p;
-   char *nl = "\n";
-   int n;
-   SV *my_sv = FILTER_DATA(idx);
-  
-   /* check if this is the first time through */
-   if (FIRST_TIME(my_sv))
-   {
-     /* mild paranoia mode - make sure that no extra filters have
-      * been applied on the same line as the use Filter::decrypt
-      */
-     if (CORE_FILTER_COUNT > FILTER_COUNT(my_sv))
-       croak("too many filters");
-  
-     /* as this is the first time through, so deal with any
-      * initialisation required
-      */
-     pre_decrypt(idx);
-  
-     FIRST_TIME(my_sv) = FALSE;
-     SET_LEN(DECRYPT_SV(my_sv), 0);
-     SET_LEN(ENCRYPT_SV(my_sv), 0);
-     DECRYPT_OFFSET(my_sv) = 0;
-   }
-  
- #ifdef DEBUG
-   warn("**** In filter_decrypt - maxlen = %d, len buf = %d idx = %d\n",
-     maxlen, SvCUR(buf_sv), idx);
- #endif
-  
-   while (1)
-   {
-     /* anything left from last time */
-     if ((n = SvCUR(DECRYPT_SV(my_sv))))
-     {
-       out_ptr = SvPVX(DECRYPT_SV(my_sv)) + DECRYPT_OFFSET(my_sv);
-       if (maxlen)
-       {
-         /* want a block */
- #ifdef DEBUG
-         warn("BLOCK(%d): size = %d, maxlen = %d\n", idx, n, maxlen);
- #endif
-  
-         sv_catpvn(buf_sv, out_ptr, (maxlen > n) ? n : maxlen);
-         if (n <= maxlen)
-         {
-           DECRYPT_OFFSET(my_sv) = 0;
-           SET_LEN(DECRYPT_SV(my_sv), 0);
-         }
-         else
-         {
-           DECRYPT_OFFSET(my_sv) += maxlen;
-           SvCUR_set(DECRYPT_SV(my_sv), n - maxlen);
-         }
-         return SvCUR(buf_sv);
-       }
-       else
-       {
-         /* want lines */
-         if ((p = ninstr(out_ptr, out_ptr + n, nl, nl + 1)))
-         {
-           sv_catpvn(buf_sv, out_ptr, p - out_ptr + 1);
-           n = n - (p - out_ptr + 1);
-           DECRYPT_OFFSET(my_sv) += (p - out_ptr + 1);
-           SvCUR_set(DECRYPT_SV(my_sv), n);
- #ifdef DEBUG
-           warn("recycle(%d): leaving %d, returning %d [%.999s]\n",
-             idx, n, SvCUR(buf_sv), SvPVX(buf_sv));
- #endif
-           return SvCUR(buf_sv);
-         }
-         else
-         {
-           /* no EOL, so append the complete buffer */
-           sv_catpvn(buf_sv, out_ptr, n);
-         }
-       }
-     }
-  
-     SET_LEN(DECRYPT_SV(my_sv), 0);
-     DECRYPT_OFFSET(my_sv) = 0;
-  
-     /* read at most BLOCKSIZE - 1 bytes from the file into the encrypt buffer:
-      *  - 1 char ("#"-char) will be prepended during first call of CipherUpdate()
-      *  - 1 char is needed for the string termination BUT perl already
-      *    allocates +1 byte with newSV()
-      */
-     if ((n = readblock(idx + 1, ENCRYPT_SV(my_sv), BLOCKSIZE - 1)) <= 0)
-     {
-       /* either EOF or an error */
- #ifdef DEBUG
-       warn("filter_read(%d): returned %d, returning %d\n", idx, n,
-         (SvCUR(buf_sv) > 0) ? SvCUR(buf_sv) : n);
- #endif
-  
-       /* if the decrypt code needs to tidy up on EOF/error,
-        * now is the time  - here is a hook
-        */
-       post_decrypt(idx);
-       filter_del(filter_decrypt);
-  
-       /* if error, return the code */
-       if (n < 0)
-         return n;
-  
-       /* return what we have so far else signal eof */
-       return (SvCUR(buf_sv) > 0) ? SvCUR(buf_sv) : n;
-     }
- #ifdef DEBUG
-     else
-       warn("filter_read(%d): read %d bytes\n", idx, n);
- #endif
-  
- #ifdef DEBUG
-     warn("filter_decrypt(%d): sub-filter returned %d: '%.999s'\n",
-       idx, n, SvPV(my_sv, PL_na));
- #endif
-  
-     /* now decrypt a block */
-     n = decrypt(CIPHER_SV(my_sv), ENCRYPT_SV(my_sv), DECRYPT_SV(my_sv));
-  
- #ifdef DEBUG
-     warn("decrypt(%d): returned %d [%.999s]\n", idx, n, SvPVX(DECRYPT_SV(my_sv)));
- #endif
-   }
- }
-  
-  
- MODULE = Confixx::Filter  PACKAGE = Confixx::Filter
-  
- PROTOTYPES: DISABLE
-  
- BOOT:
- {
- #ifndef BYPASS
-   /* don't run if this module is dynamically linked */
-   if (!isALPHA(SvPV(GvSV(CvFILEGV(cv)), PL_na)[0]))
-     croak("module is dynamically linked. Recompile as a static module");
- #ifdef DEBUGGING
-   /* don't run if compiled with DEBUGGING */
-   croak("recompile without -DDEBUGGING");
- #endif
-  
-   /* double check that DEBUGGING hasn't been enabled */
-   if (PL_debug)
-     croak("debugging flags detected");
- #endif
- }
-  
- void
- import(module)
-   SV *module
- PPCODE:
- {
-   int ret;
-   SV *sv;
-  
-   /* main/decrypted SV */
-   DECRYPT_SV(sv) = newSV(BLOCKSIZE);
-   (void) SvPOK_only(DECRYPT_SV(sv));
-   SET_LEN(DECRYPT_SV(sv), 0);
-  
-   /* add filter */
-   filter_add(filter_decrypt, DECRYPT_SV(sv));
-  
-   /* cipher SV */
-   CIPHER_GV(sv) = (GV *)newSV(sizeof(ctx_t));
-   (void) SvPOK_only(CIPHER_GV(sv));
-   ret = CipherInit(CIPHER_BUFFER(sv));
-   if (ret != 256)
-     croak("unexpected return value of CipherInit(): %d\n", ret);
-  
-   /* copy pointer to output buffer inside ciphers first bytes */
-   CIPHER_BUFFER(sv)->out = DECRYPT_BUFFER(sv);
-  
-   /* encrypted SV */
-   ENCRYPT_GV(sv) = (GV *)newSV(BLOCKSIZE);
-   (void) SvPOK_only(ENCRYPT_SV(sv));
-   SET_LEN(ENCRYPT_SV(sv), 0);
-  
-   /* enable first time flag */
-   FIRST_TIME(sv) = TRUE;
-   /* remember how many filters are enabled */
-   FILTER_COUNT(sv) = CORE_FILTER_COUNT;
-   /* and the line number */
-   FILTER_LINE_NO(sv) = PL_curcop->cop_line;
- }
-  
- void
- unimport(...)
- PPCODE:
-   //filter_del(filter_decrypt);
-