1 #ifdef __cplusplus
2 extern "C" {
3 #endif
4 
5 #include "EXTERN.h"
6 #include "perl.h"
7 #include "XSUB.h"
8 
9 #ifdef __cplusplus
10 }
11 #endif
12 
13 #include <botan/asn1_obj.h>
14 #include <botan/asn1_oid.h>
15 #include <botan/filters.h>
16 #include <botan/init.h>
17 #include <botan/oids.h>
18 #include <botan/x509cert.h>
19 #include <botan/x509_ext.h>
20 
21 
22 /* xsubpp converts ':' to '_' in typemap. We create our types without ':' */
23 
24 typedef Botan::ASN1_String		Botan__ASN1_String;
25 typedef Botan::AlgorithmIdentifier	Botan__AlgorithmIdentifier;
26 typedef Botan::AlternativeName		Botan__AlternativeName;
27 typedef Botan::Attribute		Botan__Attribute;
28 typedef Botan::Base64_Decoder		Botan__Base64_Decoder;
29 typedef Botan::Base64_Encoder		Botan__Base64_Encoder;
30 typedef Botan::Chain			Botan__Chain;
31 typedef Botan::Certificate_Extension	Botan__Extension;
32 typedef Botan::Filter			Botan__Filter;
33 typedef Botan::Fork			Botan__Fork;
34 typedef Botan::Hex_Decoder		Botan__Hex_Decoder;
35 typedef Botan::Hex_Encoder		Botan__Hex_Encoder;
36 typedef Botan::OID			Botan__OID;
37 typedef Botan::Pipe			Botan__Pipe;
38 typedef Botan::X509_Certificate		Botan__X509_Certificate;
39 typedef Botan::X509_DN			Botan__X509_DN;
40 typedef Botan::X509_Time		Botan__X509_Time;
41 typedef Botan::u32bit			Botan__u32bit;
42 
43 
44 /* Types to keep track of destruction C++ objects passed
45  * into other objects...
46  * An Botan object is deleted by his parent object into which is passed,
47  * e.g. some Filter is deleted when his Pipe is destructed. We must
48  * track this and not to delete object again in Perls destructor.
49  */
50 
51 class ObjectInfo
52 {
53 private:
54     I32	    d_signature;
55     bool    d_del;
56 public:
57     static I32 const SIGNVAL = 0x696a626f;
ObjectInfo()58     ObjectInfo() : d_signature(SIGNVAL),
59 		    d_del(true)		    {};
~ObjectInfo()60     ~ObjectInfo()			    {};
61     void    set_delete(bool del = true)	    { d_del = del; };
set_delete_no()62     void    set_delete_no()		    { set_delete(false); };
set_delete_yes()63     void    set_delete_yes()		    { set_delete(true); };
should_delete()64     bool    should_delete() const	    { return d_del; };
65 };
66 
67 /* Constant object in initial state - template */
68 
69 ObjectInfo const oi_init;
70 
71 
72 /* Botan library initializer ... */
73 
74 Botan::LibraryInitializer botan_init;
75 
76 
77 
78 /*============================================================================*/
79 
80 MODULE = Botan				    PACKAGE = Botan
81 
82 PROTOTYPES: ENABLE
83 
84 void
85 constant(char *name)
86     CODE:
87 	using namespace Botan;
88 	errno = 0;
89 	switch (name[0])
90 	{
91 	    case 'F':
92 	        if ( strEQ(name, "FULL_CHECK") )
93 		    XSRETURN_IV( FULL_CHECK );	    // Decoder_Checking enum
94 		break;
95 	    case 'I':
96 	        if ( strEQ(name, "IGNORE_WS") )
97 		    XSRETURN_IV( IGNORE_WS );	    // Decoder_Checking enum
98 		break;
99 	    case 'N':
100 	        if ( strEQ(name, "NONE") )
101 		    XSRETURN_IV( NONE );	    // Decoder_Checking enum
102 		break;
103 	}
104 	errno = EINVAL;
105 	XSRETURN_UNDEF;
106 
107 
108 # =========================== Botan::Chain ==========================
109 
110 MODULE = Botan				    PACKAGE = Botan::Chain
111 
112 Botan__Chain *
113 Botan__Chain::new(f1 = 0, f2 = 0, f3 = 0, f4 = 0)
114 	Botan__Filter	*f1;
115 	Botan__Filter	*f2;
116 	Botan__Filter	*f3;
117 	Botan__Filter	*f4;
118     PREINIT:
119 	ObjectInfo	*f1_oi;
120 	ObjectInfo	*f2_oi;
121 	ObjectInfo	*f3_oi;
122 	ObjectInfo	*f4_oi;
123     CODE:
124 	try {
125 	    RETVAL = new Botan__Chain(f1, f2, f3, f4);
126 	    if ( f1 ) f1_oi->set_delete_no();
127 	    if ( f2 ) f2_oi->set_delete_no();
128 	    if ( f3 ) f3_oi->set_delete_no();
129 	    if ( f4 ) f4_oi->set_delete_no();
130 	}
catch(const std::exception & e)131 	catch (const std::exception &e) {
132 	    croak(e.what());
133 	}
134     OUTPUT:
135 	RETVAL
136 
137 void
138 Botan__Chain::DESTROY()
139     PREINIT:
140 	ObjectInfo	*THIS_oi;
141     CODE:
142 	if ( THIS_oi->should_delete() )
143 	    try {
144 		delete THIS;
145 	    }
catch(const std::exception & e)146 	    catch (const std::exception &e) {
147 		croak(e.what());
148 	    }
149 
150 
151 # =========================== Botan::Fork ==========================
152 
153 MODULE = Botan				    PACKAGE = Botan::Fork
154 
155 Botan__Fork *
156 Botan__Fork::new(f1 = 0, f2 = 0, f3 = 0, f4 = 0)
157 	Botan__Filter	*f1;
158 	Botan__Filter	*f2;
159 	Botan__Filter	*f3;
160 	Botan__Filter	*f4;
161     PREINIT:
162 	ObjectInfo	*f1_oi;
163 	ObjectInfo	*f2_oi;
164 	ObjectInfo	*f3_oi;
165 	ObjectInfo	*f4_oi;
166     CODE:
167 	try {
168 	    RETVAL = new Botan__Fork(f1, f2, f3, f4);
169 	    if ( f1 ) f1_oi->set_delete_no();
170 	    if ( f2 ) f2_oi->set_delete_no();
171 	    if ( f3 ) f3_oi->set_delete_no();
172 	    if ( f4 ) f4_oi->set_delete_no();
173 	}
catch(const std::exception & e)174 	catch (const std::exception &e) {
175 	    croak(e.what());
176 	}
177     OUTPUT:
178 	RETVAL
179 
180 void
181 Botan__Fork::DESTROY()
182     PREINIT:
183 	ObjectInfo	*THIS_oi;
184     CODE:
185 	if ( THIS_oi->should_delete() )
186 	    try {
187 		delete THIS;
188 	    }
catch(const std::exception & e)189 	    catch (const std::exception &e) {
190 		croak(e.what());
191 	    }
192 
193 
194 # ============================ Botan::Base64_Decoder ============================
195 
196 MODULE = Botan				    PACKAGE = Botan::Base64_Decoder
197 
198 Botan__Base64_Decoder *
199 Botan__Base64_Decoder::new(checking = Botan::NONE)
200 	int	checking;
201     CODE:
202 	try {
203 	    using namespace Botan;
204 	    RETVAL = new Base64_Decoder((Decoder_Checking)checking);
205 	}
catch(const std::exception & e)206 	catch (const std::exception &e) {
207 	    croak(e.what());
208 	}
209     OUTPUT:
210 	RETVAL
211 
212 void
213 Botan__Base64_Decoder::DESTROY()
214     PREINIT:
215 	ObjectInfo	*THIS_oi;
216     CODE:
217 	if ( THIS_oi->should_delete() )
218 	    try {
219 		delete THIS;
220 	    }
catch(const std::exception & e)221 	    catch (const std::exception &e) {
222 		croak(e.what());
223 	    }
224 
225 
226 # =========================== Botan::Base64_Encoder ==========================
227 
228 MODULE = Botan				    PACKAGE = Botan::Base64_Encoder
229 
230 Botan__Base64_Encoder *
231 Botan__Base64_Encoder::new(breaks = false, length = 72)
232 	bool		breaks;
233        	Botan__u32bit	length;
234     CODE:
235 	try {
236 	    RETVAL = new Botan__Base64_Encoder(breaks, length);
237 	}
catch(const std::exception & e)238 	catch (const std::exception &e) {
239 	    croak(e.what());
240 	}
241     OUTPUT:
242 	RETVAL
243 
244 void
245 Botan__Base64_Encoder::DESTROY()
246     PREINIT:
247 	ObjectInfo	*THIS_oi;
248     CODE:
249 	if ( THIS_oi->should_delete() )
250 	    try {
251 		delete THIS;
252 	    }
catch(const std::exception & e)253 	    catch (const std::exception &e) {
254 		croak(e.what());
255 	    }
256 
257 
258 # ============================ Botan::Hex_Decoder ============================
259 
260 MODULE = Botan				    PACKAGE = Botan::Hex_Decoder
261 
262 Botan__Hex_Decoder *
263 Botan__Hex_Decoder::new(checking = Botan::NONE)
264 	int	checking;
265     CODE:
266 	try {
267 	    using namespace Botan;
268 	    RETVAL = new Hex_Decoder((Decoder_Checking)checking);
269 	}
catch(const std::exception & e)270 	catch (const std::exception &e) {
271 	    croak(e.what());
272 	}
273     OUTPUT:
274 	RETVAL
275 
276 void
277 Botan__Hex_Decoder::DESTROY()
278     PREINIT:
279 	ObjectInfo	*THIS_oi;
280     CODE:
281 	if ( THIS_oi->should_delete() )
282 	    try {
283 		delete THIS;
284 	    }
catch(const std::exception & e)285 	    catch (const std::exception &e) {
286 		croak(e.what());
287 	    }
288 
289 
290 # ============================ Botan::Hex_Encoder ============================
291 
292 MODULE = Botan				    PACKAGE = Botan::Hex_Encoder
293 
294 Botan__Hex_Encoder *
295 Botan__Hex_Encoder::new(breaks = false, length = 72, lcase = false)
296 	bool		breaks;
297        	Botan__u32bit	length;
298 	bool		lcase;
299     CODE:
300 	try {
301 	    using Botan::Hex_Encoder;
302 	    RETVAL = new Hex_Encoder(breaks, length,
303 		    lcase ? Hex_Encoder::Lowercase : Hex_Encoder::Uppercase);
304 	}
catch(const std::exception & e)305 	catch (const std::exception &e) {
306 	    croak(e.what());
307 	}
308     OUTPUT:
309 	RETVAL
310 
311 void
312 Botan__Hex_Encoder::DESTROY()
313     PREINIT:
314 	ObjectInfo	*THIS_oi;
315     CODE:
316 	if ( THIS_oi->should_delete() )
317 	    try {
318 		delete THIS;
319 	    }
catch(const std::exception & e)320 	    catch (const std::exception &e) {
321 		croak(e.what());
322 	    }
323 
324 
325 # ================================ Botan::OID ================================
326 
327 MODULE = Botan				    PACKAGE = Botan::OID
328 
329 Botan__OID *
new(s)330 Botan__OID::new(s)
331 	char *s;
332     CODE:
333 	try {
334 	    RETVAL = new Botan__OID(s);
335 	}
catch(const std::exception & e)336 	catch (const std::exception &e) {
337 	    croak(e.what());
338 	}
339     OUTPUT:
340 	RETVAL
341 
342 void
DESTROY()343 Botan__OID::DESTROY()
344     CODE:
345 	try {
346 	    delete THIS;
347 	}
catch(const std::exception & e)348 	catch (const std::exception &e) {
349 	    croak(e.what());
350 	}
351 
352 char *
as_string()353 Botan__OID::as_string()
354     CODE:
355 	try {
356 	    RETVAL = const_cast<char *>(THIS->as_string().c_str());
357 	}
catch(const std::exception & e)358 	catch (const std::exception &e) {
359 	    croak(e.what());
360 	}
361     OUTPUT:
362 	RETVAL
363 
364 
365 # ================================ Botan::OIDS ================================
366 
367 MODULE = Botan				    PACKAGE = Botan::OIDS
368 
369 void
add_oid(oid,name)370 add_oid(oid, name)
371 	Botan__OID  *oid;
372        	char	    *name;
373     CODE:
374 	try {
375 	    Botan::OIDS::add_oid(*oid, name);
376 	}
catch(const std::exception & e)377 	catch (const std::exception &e) {
378 	    croak(e.what());
379 	}
380 
381 char *
lookup_by_oid(oid)382 lookup_by_oid(oid)
383 	Botan__OID *oid;
384     CODE:
385 	try {
386 	    RETVAL = const_cast<char *>(Botan::OIDS::lookup(*oid).c_str());
387 	}
catch(const std::exception & e)388 	catch (const std::exception &e) {
389 	    croak(e.what());
390 	}
391     OUTPUT:
392 	RETVAL
393 
394 Botan__OID *
lookup_by_name(name)395 lookup_by_name(name)
396 	char *name;
397     CODE:
398 	try {
399 	    RETVAL = new Botan__OID(Botan::OIDS::lookup(name));
400 	}
catch(const std::exception & e)401 	catch (const std::exception &e) {
402 	    croak(e.what());
403 	}
404 	char const * CLASS = "Botan::OID";
405     OUTPUT:
406 	RETVAL
407 
408 int
have_oid(name)409 have_oid(name)
410 	char *name;
411     CODE:
412 	try {
413 	    RETVAL = Botan::OIDS::have_oid(name);
414 	}
catch(const std::exception & e)415 	catch (const std::exception &e) {
416 	    croak(e.what());
417 	}
418     OUTPUT:
419 	RETVAL
420 
421 
422 # ================================ Botan::Pipe ================================
423 
424 MODULE = Botan				    PACKAGE = Botan::Pipe
425 
426 Botan__Pipe *
427 Botan__Pipe::new(...)
428     CODE:
429 	for (I32 i = 1; i < items; i++)
430 	{
431 	    if ( !sv_isobject(ST(i)) || (SvTYPE(SvRV(ST(i))) != SVt_PVMG) )
432 		croak("Botan::Pipe::new() -- arg %u is not "
433 			"a blessed SV reference", i +1);
434 	    if ( !sv_derived_from(ST(i), "Botan::Filter") )
435 		croak("Botan::Pipe::new() -- arg %u is not "
436 			"an object derived from Botan::Filter", i +1);
437 	    MAGIC *mg = mg_find(SvRV(ST(i)), '~');
438 	    if ( mg == 0
439 		    || mg->mg_len != sizeof(ObjectInfo)
440 		    || *(I32 *)(mg->mg_ptr) != ObjectInfo::SIGNVAL )
441 		croak("Botan::Pipe::new() -- arg %u has no "
442 			"valid private magic data (ObjectInfo)", i +1);
443 	}
444 	try {
445 	    RETVAL = new Botan__Pipe();
446 	    for (I32 i = 1; i < items; i++)
447 	    {
448 		SV *osv = (SV *)SvRV(ST(i));
449 		ObjectInfo *oi = (ObjectInfo *)(mg_find(osv, '~')->mg_ptr);
450 		RETVAL->append((Botan__Filter *)(SvIV(osv)));
451 		oi->set_delete_no();
452 	    }
453 	}
catch(const std::exception & e)454 	catch (const std::exception &e) {
455 	    croak(e.what());
456 	}
457     OUTPUT:
458 	RETVAL
459 
460 void
461 Botan__Pipe::DESTROY()
462     PREINIT:
463 	ObjectInfo	*THIS_oi;
464     CODE:
465 	try {
466 	    delete THIS;
467 	}
catch(const std::exception & e)468 	catch (const std::exception &e) {
469 	    croak(e.what());
470 	}
471 
472 void
473 Botan__Pipe::write(s)
474 	SV *s;
475     PREINIT:
476 	ObjectInfo	*THIS_oi;
477     CODE:
478 	STRLEN len;
479 	char *ptr = SvPV(s, len);
480 	try {
481 	    THIS->write((unsigned char *)ptr, len);
482 	}
catch(const std::exception & e)483 	catch (const std::exception &e) {
484 	    croak(e.what());
485 	}
486 
487 void
488 Botan__Pipe::process_msg(s)
489 	SV *s;
490     PREINIT:
491 	ObjectInfo	*THIS_oi;
492     CODE:
493 	STRLEN len;
494 	char *ptr = SvPV(s, len);
495 	try {
496 	    THIS->process_msg((unsigned char *)ptr, len);
497 	}
catch(const std::exception & e)498 	catch (const std::exception &e) {
499 	    croak(e.what());
500 	}
501 
502 Botan__u32bit
503 Botan__Pipe::remaining(msgno = Botan::Pipe::DEFAULT_MESSAGE)
504 	Botan__u32bit msgno;
505     PREINIT:
506 	ObjectInfo	*THIS_oi;
507     CODE:
508 	try {
509 	    RETVAL = THIS->remaining(msgno);
510 	}
catch(const std::exception & e)511 	catch (const std::exception &e) {
512 	    croak(e.what());
513 	}
514     OUTPUT:
515 	RETVAL
516 
517 SV *
518 Botan__Pipe::read(len = 0xFFFFFFFF, msgno = Botan::Pipe::DEFAULT_MESSAGE)
519 	Botan__u32bit len;
520 	Botan__u32bit msgno;
521     PREINIT:
522 	ObjectInfo	*THIS_oi;
523     CODE:
524 	try {
525 	    if ( len > THIS->remaining(msgno) )
526 		len = THIS->remaining(msgno);
527 	    RETVAL = NEWSV(0, len);
528 	    SvPOK_on(RETVAL);
529 	    if ( len > 0 )
530 		SvCUR_set(RETVAL, THIS->read((unsigned char *)SvPVX(RETVAL),
531 			    len, msgno));
532 	}
catch(const std::exception & e)533 	catch (const std::exception &e) {
534 	    croak(e.what());
535 	}
536     OUTPUT:
537 	RETVAL
538 
539 SV *
540 Botan__Pipe::peek(len = 0xFFFFFFFF, offset = 0, \
541 		msgno = Botan::Pipe::DEFAULT_MESSAGE)
542 	Botan__u32bit len;
543 	Botan__u32bit offset;
544 	Botan__u32bit msgno;
545     PREINIT:
546 	ObjectInfo	*THIS_oi;
547     CODE:
548 	try {
549 	    if ( len > THIS->remaining(msgno) )
550 		len = THIS->remaining(msgno);
551 	    RETVAL = NEWSV(0, len);
552 	    SvPOK_on(RETVAL);
553 	    if ( len > 0 )
554 		SvCUR_set(RETVAL, THIS->peek((unsigned char *)SvPVX(RETVAL),
555 			    len, offset, msgno));
556 	}
catch(const std::exception & e)557 	catch (const std::exception &e) {
558 	    croak(e.what());
559 	}
560     OUTPUT:
561 	RETVAL
562 
563 Botan__u32bit
564 Botan__Pipe::default_msg()
565     PREINIT:
566 	ObjectInfo	*THIS_oi;
567     CODE:
568 	try {
569 	    RETVAL = THIS->default_msg();
570 	}
catch(const std::exception & e)571 	catch (const std::exception &e) {
572 	    croak(e.what());
573 	}
574     OUTPUT:
575 	RETVAL
576 
577 void
578 Botan__Pipe::set_default_msg(msgno)
579 	Botan__u32bit msgno;
580     PREINIT:
581 	ObjectInfo	*THIS_oi;
582     CODE:
583 	try {
584 	    THIS->set_default_msg(msgno);
585 	}
catch(const std::exception & e)586 	catch (const std::exception &e) {
587 	    croak(e.what());
588 	}
589 
590 Botan__u32bit
591 Botan__Pipe::message_count()
592     PREINIT:
593 	ObjectInfo	*THIS_oi;
594     CODE:
595 	try {
596 	    RETVAL = THIS->message_count();
597 	}
catch(const std::exception & e)598 	catch (const std::exception &e) {
599 	    croak(e.what());
600 	}
601     OUTPUT:
602 	RETVAL
603 
604 bool
605 Botan__Pipe::end_of_data()
606     PREINIT:
607 	ObjectInfo	*THIS_oi;
608     CODE:
609 	try {
610 	    RETVAL = THIS->end_of_data();
611 	}
catch(const std::exception & e)612 	catch (const std::exception &e) {
613 	    croak(e.what());
614 	}
615     OUTPUT:
616 	RETVAL
617 
618 void
619 Botan__Pipe::start_msg()
620     PREINIT:
621 	ObjectInfo	*THIS_oi;
622     CODE:
623 	try {
624 	    THIS->start_msg();
625 	}
catch(const std::exception & e)626 	catch (const std::exception &e) {
627 	    croak(e.what());
628 	}
629 
630 void
631 Botan__Pipe::end_msg()
632     PREINIT:
633 	ObjectInfo	*THIS_oi;
634     CODE:
635 	try {
636 	    THIS->end_msg();
637 	}
catch(const std::exception & e)638 	catch (const std::exception &e) {
639 	    croak(e.what());
640 	}
641 
642 void
643 Botan__Pipe::reset()
644     PREINIT:
645 	ObjectInfo	*THIS_oi;
646     CODE:
647 	try {
648 	    THIS->reset();
649 	}
catch(const std::exception & e)650 	catch (const std::exception &e) {
651 	    croak(e.what());
652 	}
653 
654 
655 # ========================== Botan::X509_Certificate ==========================
656 
657 MODULE = Botan				    PACKAGE = Botan::X509_Certificate
658 
659 Botan__X509_Certificate *
new(char * fn)660 Botan__X509_Certificate::new(char *fn)
661     CODE:
662 	try {
663 	    RETVAL = new Botan__X509_Certificate(fn);
664 	}
catch(const std::exception & e)665 	catch (const std::exception &e) {
666 	    croak(e.what());
667 	}
668     OUTPUT:
669 	RETVAL
670 
671 void
DESTROY()672 Botan__X509_Certificate::DESTROY()
673     CODE:
674 	try {
675 	    delete THIS;
676 	}
catch(const std::exception & e)677 	catch (const std::exception &e) {
678 	    croak(e.what());
679 	}
680 
681 unsigned int
x509_version()682 Botan__X509_Certificate::x509_version()
683     CODE:
684 	try {
685 	    RETVAL = THIS->x509_version();
686 	}
catch(const std::exception & e)687 	catch (const std::exception &e) {
688 	    croak(e.what());
689 	}
690     OUTPUT:
691 	RETVAL
692 
693 char *
start_time()694 Botan__X509_Certificate::start_time()
695     CODE:
696 	try {
697 	    RETVAL = const_cast<char *>(THIS->start_time().c_str());
698 	}
catch(const std::exception & e)699 	catch (const std::exception &e) {
700 	    croak(e.what());
701 	}
702     OUTPUT:
703 	RETVAL
704 
705 char *
end_time()706 Botan__X509_Certificate::end_time()
707     CODE:
708 	try {
709 	    RETVAL = const_cast<char *>(THIS->end_time().c_str());
710 	}
catch(const std::exception & e)711 	catch (const std::exception &e) {
712 	    croak(e.what());
713 	}
714     OUTPUT:
715 	RETVAL
716 
717 char *
subject_info(char * info)718 Botan__X509_Certificate::subject_info(char *info)
719     CODE:
720 	try {
721             std::vector<std::string> s = THIS->subject_info(info);
722 
723             if(s.size() > 0)
724                 RETVAL = const_cast<char *>(s[0].c_str());
725             else
726                 RETVAL = "err";
727 	}
catch(const std::exception & e)728 	catch (const std::exception &e) {
729 	    croak(e.what());
730 	}
731     OUTPUT:
732 	RETVAL
733 
734 char *
issuer_info(char * info)735 Botan__X509_Certificate::issuer_info(char *info)
736     CODE:
737 	try {
738             std::vector<std::string> s = THIS->subject_info(info);
739 
740             if(s.size() > 0)
741                 RETVAL = const_cast<char *>(s[0].c_str());
742             else
743                 RETVAL = "err";
744 	}
catch(const std::exception & e)745 	catch (const std::exception &e) {
746 	    croak(e.what());
747 	}
748     OUTPUT:
749 	RETVAL
750 
751 Botan__X509_DN *
subject_dn()752 Botan__X509_Certificate::subject_dn()
753     CODE:
754 	try {
755 	    RETVAL = new Botan__X509_DN(THIS->subject_dn());
756 	}
catch(const std::exception & e)757 	catch (const std::exception &e) {
758 	    croak(e.what());
759 	}
760 	char const * CLASS = "Botan::X509_DN";
761     OUTPUT:
762 	RETVAL
763 
764 Botan__X509_DN *
issuer_dn()765 Botan__X509_Certificate::issuer_dn()
766     CODE:
767 	try {
768 	    RETVAL = new Botan__X509_DN(THIS->issuer_dn());
769 	}
catch(const std::exception & e)770 	catch (const std::exception &e) {
771 	    croak(e.what());
772 	}
773 	char const * CLASS = "Botan::X509_DN";
774     OUTPUT:
775 	RETVAL
776 
777 
778 # ============================== Botan::X509_DN ==============================
779 
780 MODULE = Botan				    PACKAGE = Botan::X509_DN
781 
782 Botan__X509_DN *
new()783 Botan__X509_DN::new()
784     CODE:
785 	try {
786 	    RETVAL = new Botan__X509_DN();
787 	}
catch(const std::exception & e)788 	catch (const std::exception &e) {
789 	    croak(e.what());
790 	}
791     OUTPUT:
792 	RETVAL
793 
794 void
DESTROY()795 Botan__X509_DN::DESTROY()
796     CODE:
797 	try {
798 	    delete THIS;
799 	}
catch(const std::exception & e)800 	catch (const std::exception &e) {
801 	    croak(e.what());
802 	}
803 
804 AV *
get_attributes()805 Botan__X509_DN::get_attributes()
806     CODE:
807 	try {
808 	    using namespace std;
809 	    using namespace Botan;
810 
811 	    typedef multimap<OID, string>::const_iterator rdn_iter;
812 
813 	    multimap<OID, string> const &atrmmap = THIS->get_attributes();
814 	    RETVAL = newAV();
815 	    for(rdn_iter i = atrmmap.begin(); i != atrmmap.end(); i++)
816 	    {
817 		string const &atr = i->first.as_string();
818 		string const &val = i->second;
819 		av_push(RETVAL, newSVpvn(atr.c_str(), atr.length()));
820 		av_push(RETVAL, newSVpvn(val.c_str(), val.length()));
821 	    }
822 	}
catch(const std::exception & e)823 	catch (const std::exception &e) {
824 	    croak(e.what());
825 	}
826     OUTPUT:
827 	RETVAL
828