improve treatment of multi-line replies, ignore empty lines
[python/dscho.git] / Modules / rotormodule.c
blob60d9257179824a3a26831e611ce3728717583266
1 /***********************************************************
2 Copyright 1994 by Lance Ellinghouse,
3 Cathedral City, California Republic, United States of America.
5 All Rights Reserved
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the name of Lance Ellinghouse
12 not be used in advertising or publicity pertaining to distribution
13 of the software without specific, written prior permission.
15 LANCE ELLINGHOUSE DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL LANCE ELLINGHOUSE BE LIABLE FOR ANY SPECIAL,
18 INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
19 FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20 NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
25 /* This creates an encryption and decryption engine I am calling
26 a rotor due to the original design was a harware rotor with
27 contacts used in Germany during WWII.
29 Rotor Module:
31 - rotor.newrotor('key') -> rotorobject (default of 6 rotors)
32 - rotor.newrotor('key', num_rotors) -> rotorobject
34 Rotor Objects:
36 - ro.setkey('string') -> None (resets the key as defined in newrotor().
37 - ro.encrypt('string') -> encrypted string
38 - ro.decrypt('encrypted string') -> unencrypted string
40 - ro.encryptmore('string') -> encrypted string
41 - ro.decryptmore('encrypted string') -> unencrypted string
43 NOTE: the {en,de}cryptmore() methods use the setup that was
44 established via the {en,de}crypt calls. They will NOT
45 re-initalize the rotors unless: 1) They have not been
46 initalized with {en,de}crypt since the last setkey() call;
47 2) {en,de}crypt has not been called for this rotor yet.
49 NOTE: you MUST use the SAME key in rotor.newrotor()
50 if you wish to decrypt an encrypted string.
51 Also, the encrypted string is NOT 0-127 ASCII.
52 It is considered BINARY data.
56 /* Rotor objects */
58 #include "Python.h"
60 #include <math.h>
62 #define TRUE 1
63 #define FALSE 0
65 typedef struct {
66 PyObject_HEAD
67 int seed[3];
68 short key[5];
69 int isinited;
70 int size;
71 int size_mask;
72 int rotors;
73 unsigned char *e_rotor; /* [num_rotors][size] */
74 unsigned char *d_rotor; /* [num_rotors][size] */
75 unsigned char *positions; /* [num_rotors] */
76 unsigned char *advances; /* [num_rotors] */
77 } PyRotorObject;
79 staticforward PyTypeObject PyRotor_Type;
81 #define PyRotor_Check(v) ((v)->ob_type == &PyRotor_Type)
84 This defines the necessary routines to manage rotor objects
87 static void set_seed( r )
88 PyRotorObject *r;
90 r->seed[0] = r->key[0];
91 r->seed[1] = r->key[1];
92 r->seed[2] = r->key[2];
93 r->isinited = FALSE;
96 /* Return the next random number in the range [0.0 .. 1.0) */
97 static float r_random( r )
98 PyRotorObject *r;
100 int x, y, z;
101 float val, term;
103 x = r->seed[0];
104 y = r->seed[1];
105 z = r->seed[2];
107 x = 171 * (x % 177) - 2 * (x/177);
108 y = 172 * (y % 176) - 35 * (y/176);
109 z = 170 * (z % 178) - 63 * (z/178);
111 if (x < 0) x = x + 30269;
112 if (y < 0) y = y + 30307;
113 if (z < 0) z = z + 30323;
115 r->seed[0] = x;
116 r->seed[1] = y;
117 r->seed[2] = z;
119 term = (float)(
120 (((float)x)/(float)30269.0) +
121 (((float)y)/(float)30307.0) +
122 (((float)z)/(float)30323.0)
124 val = term - (float)floor((double)term);
126 if (val >= 1.0) val = 0.0;
128 return val;
131 static short r_rand(r,s)
132 PyRotorObject *r;
133 short s;
135 /*short tmp = (short)((int)(r_random(r) * (float)32768.0) % 32768);*/
136 short tmp = (short)((short)(r_random(r) * (float)s) % s);
137 return tmp;
140 static void set_key(r, key)
141 PyRotorObject *r;
142 char *key;
144 #ifdef BUGGY_CODE_BW_COMPAT
145 /* See comments below */
146 int k1=995, k2=576, k3=767, k4=671, k5=463;
147 #else
148 unsigned long k1=995, k2=576, k3=767, k4=671, k5=463;
149 #endif
150 int i;
151 int len=strlen(key);
152 for (i=0;i<len;i++) {
153 #ifdef BUGGY_CODE_BW_COMPAT
154 /* This is the code as it was originally released.
155 It causes warnings on many systems and can generate
156 different results as well. If you have files
157 encrypted using an older version you may want to
158 #define BUGGY_CODE_BW_COMPAT so as to be able to
159 decrypt them... */
160 k1 = (((k1<<3 | k1<<-13) + key[i]) & 65535);
161 k2 = (((k2<<3 | k2<<-13) ^ key[i]) & 65535);
162 k3 = (((k3<<3 | k3<<-13) - key[i]) & 65535);
163 k4 = ((key[i] - (k4<<3 | k4<<-13)) & 65535);
164 k5 = (((k5<<3 | k5<<-13) ^ ~key[i]) & 65535);
165 #else
166 /* This code should be more portable */
167 k1 = (((k1<<3 | k1>>13) + key[i]) & 65535);
168 k2 = (((k2<<3 | k2>>13) ^ key[i]) & 65535);
169 k3 = (((k3<<3 | k3>>13) - key[i]) & 65535);
170 k4 = ((key[i] - (k4<<3 | k4>>13)) & 65535);
171 k5 = (((k5<<3 | k5>>13) ^ ~key[i]) & 65535);
172 #endif
174 r->key[0] = (short)k1;
175 r->key[1] = (short)(k2|1);
176 r->key[2] = (short)k3;
177 r->key[3] = (short)k4;
178 r->key[4] = (short)k5;
180 set_seed(r);
183 /* These define the interface to a rotor object */
184 static PyRotorObject *
185 PyRotor_New(num_rotors, key)
186 int num_rotors;
187 char *key;
189 PyRotorObject *xp;
190 xp = PyObject_NEW(PyRotorObject, &PyRotor_Type);
191 if (xp == NULL)
192 return NULL;
193 set_key(xp, key);
195 xp->size = 256;
196 xp->size_mask = xp->size - 1;
197 xp->size_mask = 0;
198 xp->rotors = num_rotors;
199 xp->e_rotor = NULL;
200 xp->d_rotor = NULL;
201 xp->positions = NULL;
202 xp->advances = NULL;
204 xp->e_rotor =
205 (unsigned char *)malloc((num_rotors * (xp->size * sizeof(char))));
206 if (xp->e_rotor == (unsigned char *)NULL)
207 goto fail;
208 xp->d_rotor =
209 (unsigned char *)malloc((num_rotors * (xp->size * sizeof(char))));
210 if (xp->d_rotor == (unsigned char *)NULL)
211 goto fail;
212 xp->positions = (unsigned char *)malloc(num_rotors * sizeof(char));
213 if (xp->positions == (unsigned char *)NULL)
214 goto fail;
215 xp->advances = (unsigned char *)malloc(num_rotors * sizeof(char));
216 if (xp->advances == (unsigned char *)NULL)
217 goto fail;
218 return xp;
219 fail:
220 Py_DECREF(xp);
221 return (PyRotorObject *)PyErr_NoMemory();
224 /* These routines impliment the rotor itself */
226 /* Here is a fairly sofisticated {en,de}cryption system. It is bassed
227 on the idea of a "rotor" machine. A bunch of rotors, each with a
228 different permutation of the alphabet, rotate around a different
229 amount after encrypting one character. The current state of the
230 rotors is used to encrypt one character.
232 The code is smart enought to tell if your alphabet has a number of
233 characters equal to a power of two. If it does, it uses logical
234 operations, if not it uses div and mod (both require a division).
236 You will need to make two changes to the code 1) convert to c, and
237 customize for an alphabet of 255 chars 2) add a filter at the
238 begining, and end, which subtracts one on the way in, and adds one on
239 the way out.
241 You might wish to do some timing studies. Another viable
242 alternative is to "byte stuff" the encrypted data of a normal (perhaps
243 this one) encryption routine.
248 /*(defun RTR-make-id-rotor (rotor)
249 "Set ROTOR to the identity permutation"
250 (let ((j 0))
251 (while (< j RTR-size)
252 (aset rotor j j)
253 (setq j (+ 1 j)))
254 rotor))*/
255 static void RTR_make_id_rotor(r, rtr)
256 PyRotorObject *r;
257 unsigned char *rtr;
259 register int j;
260 register int size = r->size;
261 for (j=0;j<size;j++) {
262 rtr[j] = (unsigned char)j;
267 /*(defvar RTR-e-rotors
268 (let ((rv (make-vector RTR-number-of-rotors 0))
269 (i 0)
271 (while (< i RTR-number-of-rotors)
272 (setq tr (make-vector RTR-size 0))
273 (RTR-make-id-rotor tr)
274 (aset rv i tr)
275 (setq i (+ 1 i)))
277 "The current set of encryption rotors")*/
278 static void RTR_e_rotors(r)
279 PyRotorObject *r;
281 int i;
282 for (i=0;i<r->rotors;i++) {
283 RTR_make_id_rotor(r,&(r->e_rotor[(i*r->size)]));
287 /*(defvar RTR-d-rotors
288 (let ((rv (make-vector RTR-number-of-rotors 0))
289 (i 0)
291 (while (< i RTR-number-of-rotors)
292 (setq tr (make-vector RTR-size 0))
293 (setq j 0)
294 (while (< j RTR-size)
295 (aset tr j j)
296 (setq j (+ 1 j)))
297 (aset rv i tr)
298 (setq i (+ 1 i)))
300 "The current set of decryption rotors")*/
301 static void RTR_d_rotors(r)
302 PyRotorObject *r;
304 register int i, j;
305 for (i=0;i<r->rotors;i++) {
306 for (j=0;j<r->size;j++) {
307 r->d_rotor[((i*r->size)+j)] = (unsigned char)j;
312 /*(defvar RTR-positions (make-vector RTR-number-of-rotors 1)
313 "The positions of the rotors at this time")*/
314 static void RTR_positions(r)
315 PyRotorObject *r;
317 int i;
318 for (i=0;i<r->rotors;i++) {
319 r->positions[i] = 1;
323 /*(defvar RTR-advances (make-vector RTR-number-of-rotors 1)
324 "The number of positions to advance the rotors at a time")*/
325 static void RTR_advances(r)
326 PyRotorObject *r;
328 int i;
329 for (i=0;i<r->rotors;i++) {
330 r->advances[i] = 1;
334 /*(defun RTR-permute-rotor (e d)
335 "Permute the E rotor, and make the D rotor its inverse"
336 ;; see Knuth for explaination of algorythm.
337 (RTR-make-id-rotor e)
338 (let ((i RTR-size)
339 q j)
340 (while (<= 2 i)
341 (setq q (fair16 i)) ; a little tricky, decrement here
342 (setq i (- i 1)) ; since we have origin 0 array's
343 (setq j (aref e q))
344 (aset e q (aref e i))
345 (aset e i j)
346 (aset d j i))
347 (aset e 0 (aref e 0)) ; don't forget e[0] and d[0]
348 (aset d (aref e 0) 0)))*/
349 static void RTR_permute_rotor(r, e, d)
350 PyRotorObject *r;
351 unsigned char *e;
352 unsigned char *d;
354 short i = r->size;
355 short q;
356 unsigned char j;
357 RTR_make_id_rotor(r,e);
358 while (2 <= i) {
359 q = r_rand(r,i);
360 i--;
361 j = e[q];
362 e[q] = (unsigned char)e[i];
363 e[i] = (unsigned char)j;
364 d[j] = (unsigned char)i;
366 e[0] = (unsigned char)e[0];
367 d[(e[0])] = (unsigned char)0;
370 /*(defun RTR-init (key)
371 "Given KEY (a list of 5 16 bit numbers), initialize the rotor machine.
372 Set the advancement, position, and permutation of the rotors"
373 (R16-set-state key)
374 (let (i)
375 (setq i 0)
376 (while (< i RTR-number-of-rotors)
377 (aset RTR-positions i (fair16 RTR-size))
378 (aset RTR-advances i (+ 1 (* 2 (fair16 (/ RTR-size 2)))))
379 (message "Initializing rotor %d..." i)
380 (RTR-permute-rotor (aref RTR-e-rotors i) (aref RTR-d-rotors i))
381 (setq i (+ 1 i)))))*/
382 static void RTR_init(r)
383 PyRotorObject *r;
385 int i;
386 set_seed(r);
387 RTR_positions(r);
388 RTR_advances(r);
389 RTR_e_rotors(r);
390 RTR_d_rotors(r);
391 for(i=0;i<r->rotors;i++) {
392 r->positions[i] = r_rand(r,r->size);
393 r->advances[i] = (1+(2*(r_rand(r,r->size/2))));
394 RTR_permute_rotor(r,&(r->e_rotor[(i*r->size)]),&(r->d_rotor[(i*r->size)]));
396 r->isinited = TRUE;
399 /*(defun RTR-advance ()
400 "Change the RTR-positions vector, using the RTR-advances vector"
401 (let ((i 0)
402 (temp 0))
403 (if RTR-size-mask
404 (while (< i RTR-number-of-rotors)
405 (setq temp (+ (aref RTR-positions i) (aref RTR-advances i)))
406 (aset RTR-positions i (logand temp RTR-size-mask))
407 (if (and (>= temp RTR-size)
408 (< i (- RTR-number-of-rotors 1)))
409 (aset RTR-positions (+ i 1)
410 (+ 1 (aref RTR-positions (+ i 1)))))
411 (setq i (+ i 1)))
412 (while (< i RTR-number-of-rotors)
413 (setq temp (+ (aref RTR-positions i) (aref RTR-advances i)))
414 (aset RTR-positions i (% temp RTR-size))
415 (if (and (>= temp RTR-size)
416 (< i (- RTR-number-of-rotors 1)))
417 (aset RTR-positions (+ i 1)
418 (+ 1 (aref RTR-positions (+ i 1)))))
419 (setq i (+ i 1))))))*/
420 static void RTR_advance(r)
421 PyRotorObject *r;
423 register int i=0, temp=0;
424 if (r->size_mask) {
425 while (i<r->rotors) {
426 temp = r->positions[i] + r->advances[i];
427 r->positions[i] = temp & r->size_mask;
428 if ((temp >= r->size) && (i < (r->rotors - 1))) {
429 r->positions[(i+1)] = 1 + r->positions[(i+1)];
431 i++;
433 } else {
434 while (i<r->rotors) {
435 temp = r->positions[i] + r->advances[i];
436 r->positions[i] = temp%r->size;
437 if ((temp >= r->size) && (i < (r->rotors - 1))) {
438 r->positions[(i+1)] = 1 + r->positions[(i+1)];
440 i++;
445 /*(defun RTR-e-char (p)
446 "Encrypt the character P with the current rotor machine"
447 (let ((i 0))
448 (if RTR-size-mask
449 (while (< i RTR-number-of-rotors)
450 (setq p (aref (aref RTR-e-rotors i)
451 (logand (logxor (aref RTR-positions i)
453 RTR-size-mask)))
454 (setq i (+ 1 i)))
455 (while (< i RTR-number-of-rotors)
456 (setq p (aref (aref RTR-e-rotors i)
457 (% (logxor (aref RTR-positions i)
459 RTR-size)))
460 (setq i (+ 1 i))))
461 (RTR-advance)
462 p))*/
463 static unsigned char RTR_e_char(r, p)
464 PyRotorObject *r;
465 unsigned char p;
467 register int i=0;
468 register unsigned char tp=p;
469 if (r->size_mask) {
470 while (i < r->rotors) {
471 tp = r->e_rotor[(i*r->size)+(((r->positions[i] ^ tp) & r->size_mask))];
472 i++;
474 } else {
475 while (i < r->rotors) {
476 tp = r->e_rotor[(i*r->size)+(((r->positions[i] ^ tp) % (unsigned int) r->size))];
477 i++;
480 RTR_advance(r);
481 return ((unsigned char)tp);
484 /*(defun RTR-d-char (c)
485 "Decrypt the character C with the current rotor machine"
486 (let ((i (- RTR-number-of-rotors 1)))
487 (if RTR-size-mask
488 (while (<= 0 i)
489 (setq c (logand (logxor (aref RTR-positions i)
490 (aref (aref RTR-d-rotors i)
492 RTR-size-mask))
493 (setq i (- i 1)))
494 (while (<= 0 i)
495 (setq c (% (logxor (aref RTR-positions i)
496 (aref (aref RTR-d-rotors i)
498 RTR-size))
499 (setq i (- i 1))))
500 (RTR-advance)
501 c))*/
502 static unsigned char RTR_d_char(r, c)
503 PyRotorObject *r;
504 unsigned char c;
506 register int i=r->rotors - 1;
507 register unsigned char tc=c;
508 if (r->size_mask) {
509 while (0 <= i) {
510 tc = (r->positions[i] ^ r->d_rotor[(i*r->size)+tc]) & r->size_mask;
511 i--;
513 } else {
514 while (0 <= i) {
515 tc = (r->positions[i] ^ r->d_rotor[(i*r->size)+tc]) % (unsigned int) r->size;
516 i--;
519 RTR_advance(r);
520 return(tc);
523 /*(defun RTR-e-region (beg end key)
524 "Perform a rotor encryption of the region from BEG to END by KEY"
525 (save-excursion
526 (let ((tenth (/ (- end beg) 10)))
527 (RTR-init key)
528 (goto-char beg)
529 ;; ### make it stop evry 10% or so to tell us
530 (while (< (point) end)
531 (let ((fc (following-char)))
532 (insert-char (RTR-e-char fc) 1)
533 (delete-char 1))))))*/
534 static void RTR_e_region(r, beg, len, doinit)
535 PyRotorObject *r;
536 unsigned char *beg;
537 int len;
538 int doinit;
540 register int i;
541 if (doinit || r->isinited == FALSE)
542 RTR_init(r);
543 for (i=0;i<len;i++) {
544 beg[i]=RTR_e_char(r,beg[i]);
548 /*(defun RTR-d-region (beg end key)
549 "Perform a rotor decryption of the region from BEG to END by KEY"
550 (save-excursion
551 (progn
552 (RTR-init key)
553 (goto-char beg)
554 (while (< (point) end)
555 (let ((fc (following-char)))
556 (insert-char (RTR-d-char fc) 1)
557 (delete-char 1))))))*/
558 static void RTR_d_region(r, beg, len, doinit)
559 PyRotorObject *r;
560 unsigned char *beg;
561 int len;
562 int doinit;
564 register int i;
565 if (doinit || r->isinited == FALSE)
566 RTR_init(r);
567 for (i=0;i<len;i++) {
568 beg[i]=RTR_d_char(r,beg[i]);
573 /*(defun RTR-key-string-to-ints (key)
574 "Convert a string into a list of 4 numbers"
575 (let ((k1 995)
576 (k2 576)
577 (k3 767)
578 (k4 671)
579 (k5 463)
580 (i 0))
581 (while (< i (length key))
582 (setq k1 (logand (+ (logior (lsh k1 3) (lsh k1 -13)) (aref key i)) 65535))
583 (setq k2 (logand (logxor (logior (lsh k2 3) (lsh k2 -13)) (aref key i)) 65535))
584 (setq k3 (logand (- (logior (lsh k3 3) (lsh k3 -13)) (aref key i)) 65535))
585 (setq k4 (logand (- (aref key i) (logior (lsh k4 3) (lsh k4 -13))) 65535))
586 (setq k5 (logand (logxor (logior (lsh k5 3) (lsh k5 -13)) (lognot (aref key i))) 65535))
587 (setq i (+ i 1)))
588 (list k1 (logior 1 k2) k3 k4 k5)))*/
589 /* This is done in set_key() above */
591 #if 0
592 /*(defun encrypt-region (beg end key)
593 "Interactivly encrypt the region"
594 (interactive "r\nsKey:")
595 (RTR-e-region beg end (RTR-key-string-to-ints key)))*/
596 static void encrypt_region(r, region, len)
597 PyRotorObject *r;
598 unsigned char *region;
599 int len;
601 RTR_e_region(r,region,len,TRUE);
604 /*(defun decrypt-region (beg end key)
605 "Interactivly decrypt the region"
606 (interactive "r\nsKey:")
607 (RTR-d-region beg end (RTR-key-string-to-ints key)))*/
608 static void decrypt_region(r, region, len)
609 PyRotorObject *r;
610 unsigned char *region;
611 int len;
613 RTR_d_region(r,region,len,TRUE);
615 #endif
617 /* Rotor methods */
619 static void
620 PyRotor_Dealloc(xp)
621 PyRotorObject *xp;
623 PyMem_XDEL(xp->e_rotor);
624 PyMem_XDEL(xp->d_rotor);
625 PyMem_XDEL(xp->positions);
626 PyMem_XDEL(xp->advances);
627 PyMem_DEL(xp);
630 static PyObject *
631 PyRotor_Encrypt(self, args)
632 PyRotorObject *self;
633 PyObject * args;
635 char *string = (char *)NULL;
636 int len = 0;
637 PyObject * rtn = (PyObject * )NULL;
638 char *tmp;
640 if (!PyArg_Parse(args,"s#",&string, &len))
641 return NULL;
642 if (!(tmp = (char *)malloc(len+5))) {
643 PyErr_NoMemory();
644 return NULL;
646 memset(tmp,'\0',len+1);
647 memcpy(tmp,string,len);
648 RTR_e_region(self,(unsigned char *)tmp,len, TRUE);
649 rtn = PyString_FromStringAndSize(tmp,len);
650 free(tmp);
651 return(rtn);
654 static PyObject *
655 PyRotor_EncryptMore(self, args)
656 PyRotorObject *self;
657 PyObject * args;
659 char *string = (char *)NULL;
660 int len = 0;
661 PyObject * rtn = (PyObject * )NULL;
662 char *tmp;
664 if (!PyArg_Parse(args,"s#",&string, &len))
665 return NULL;
666 if (!(tmp = (char *)malloc(len+5))) {
667 PyErr_NoMemory();
668 return NULL;
670 memset(tmp,'\0',len+1);
671 memcpy(tmp,string,len);
672 RTR_e_region(self,(unsigned char *)tmp,len, FALSE);
673 rtn = PyString_FromStringAndSize(tmp,len);
674 free(tmp);
675 return(rtn);
678 static PyObject *
679 PyRotor_Decrypt(self, args)
680 PyRotorObject *self;
681 PyObject * args;
683 char *string = (char *)NULL;
684 int len = 0;
685 PyObject * rtn = (PyObject * )NULL;
686 char *tmp;
688 if (!PyArg_Parse(args,"s#",&string, &len))
689 return NULL;
690 if (!(tmp = (char *)malloc(len+5))) {
691 PyErr_NoMemory();
692 return NULL;
694 memset(tmp,'\0',len+1);
695 memcpy(tmp,string,len);
696 RTR_d_region(self,(unsigned char *)tmp,len, TRUE);
697 rtn = PyString_FromStringAndSize(tmp,len);
698 free(tmp);
699 return(rtn);
702 static PyObject *
703 PyRotor_DecryptMore(self, args)
704 PyRotorObject *self;
705 PyObject * args;
707 char *string = (char *)NULL;
708 int len = 0;
709 PyObject * rtn = (PyObject * )NULL;
710 char *tmp;
712 if (!PyArg_Parse(args,"s#",&string, &len))
713 return NULL;
714 if (!(tmp = (char *)malloc(len+5))) {
715 PyErr_NoMemory();
716 return NULL;
718 memset(tmp,'\0',len+1);
719 memcpy(tmp,string,len);
720 RTR_d_region(self,(unsigned char *)tmp,len, FALSE);
721 rtn = PyString_FromStringAndSize(tmp,len);
722 free(tmp);
723 return(rtn);
726 static PyObject *
727 PyRotor_SetKey(self, args)
728 PyRotorObject *self;
729 PyObject * args;
731 char *string;
733 if (PyArg_Parse(args,"s",&string))
734 set_key(self,string);
735 Py_INCREF(Py_None);
736 return Py_None;
739 static struct PyMethodDef PyRotor_Methods[] = {
740 {"encrypt", (PyCFunction)PyRotor_Encrypt},
741 {"encryptmore", (PyCFunction)PyRotor_EncryptMore},
742 {"decrypt", (PyCFunction)PyRotor_Decrypt},
743 {"decryptmore", (PyCFunction)PyRotor_DecryptMore},
744 {"setkey", (PyCFunction)PyRotor_SetKey},
745 {NULL, NULL} /* sentinel */
749 /* Return a rotor object's named attribute. */
750 static PyObject *
751 PyRotor_GetAttr(s, name)
752 PyRotorObject *s;
753 char *name;
755 return Py_FindMethod(PyRotor_Methods, (PyObject * ) s, name);
758 static PyTypeObject PyRotor_Type = {
759 PyObject_HEAD_INIT(&PyType_Type)
760 0, /*ob_size*/
761 "rotor", /*tp_name*/
762 sizeof(PyRotorObject), /*tp_size*/
763 0, /*tp_itemsize*/
764 /* methods */
765 (destructor)PyRotor_Dealloc, /*tp_dealloc*/
766 0, /*tp_print*/
767 (getattrfunc)PyRotor_GetAttr, /*tp_getattr*/
768 0, /*tp_setattr*/
769 0, /*tp_compare*/
770 0, /*tp_repr*/
771 0, /*tp_hash*/
775 static PyObject *
776 PyRotor_Rotor(self, args)
777 PyObject * self;
778 PyObject * args;
780 char *string;
781 PyRotorObject *r;
782 int len;
783 int num_rotors;
785 if (PyArg_Parse(args,"s#", &string, &len)) {
786 num_rotors = 6;
787 } else {
788 PyErr_Clear();
789 if (!PyArg_Parse(args,"(s#i)", &string, &len, &num_rotors))
790 return NULL;
792 r = PyRotor_New(num_rotors, string);
793 return (PyObject * )r;
796 static struct PyMethodDef PyRotor_Rotor_Methods[] = {
797 {"newrotor", (PyCFunction)PyRotor_Rotor},
798 {NULL, NULL} /* Sentinel */
802 /* Initialize this module.
803 This is called when the first 'import rotor' is done,
804 via a table in config.c, if config.c is compiled with USE_ROTOR
805 defined. */
807 void
808 initrotor()
810 PyObject * m;
812 m = Py_InitModule("rotor", PyRotor_Rotor_Methods);