123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211(* $Id$ *)(* TODO:
- verify strings
*)openNetasn1exceptionEncode_errorofstringlettag_of_value=function|Value.Bool_->Value.Universal,1|Value.Integer_->Value.Universal,2|Value.Bitstring_->Value.Universal,3|Value.Octetstring_->Value.Universal,4|Value.Null->Value.Universal,5|Value.OID_->Value.Universal,6|Value.ObjectDescriptor_->Value.Universal,7|Value.External_->Value.Universal,8|Value.Real_->Value.Universal,9|Value.Enum_->Value.Universal,10|Value.Embedded_PDV_->Value.Universal,11|Value.UTF8String_->Value.Universal,12|Value.ROID_->Value.Universal,13|Value.Seq_->Value.Universal,16|Value.Set_->Value.Universal,17|Value.NumericString_->Value.Universal,18|Value.PrintableString_->Value.Universal,19|Value.TeletexString_->Value.Universal,20|Value.VideotexString_->Value.Universal,21|Value.IA5String_->Value.Universal,22|Value.UTCTime_->Value.Universal,23|Value.GeneralizedTime_->Value.Universal,24|Value.GraphicString_->Value.Universal,25|Value.VisibleString_->Value.Universal,26|Value.GeneralString_->Value.Universal,27|Value.UniversalString_->Value.Universal,28|Value.CharString_->Value.Universal,29|Value.BMPString_->Value.Universal,30|Value.ITag(tc,tag,_)->iftag<0thenfailwith"Netasn1_encode.tag_of_value";tc,tag|Value.Tag(tc,tag,_,_)->iftag<0thenfailwith "Netasn1_encode.tag_of_value";tc,tag|Value.Tagptr(tc,tag,_,_,_,_)->iftag<0then failwith"Netasn1_encode.tag_of_value";tc,tagletencode_errors=raise(Encode_errors)letencode_base128 bufn=letrecencoden=ifn<128then[n]else(nland127)::encode(nlsr7)inifn<0thenencode_error"bad input";letl=List.rev(encoden)inletlen=List.lengthlinletl=List.mapi(funik->ifi<len-1thenChar.chr(klor128)elseChar.chrk)linList.iter(Netbuffer.add_charbuf)lletrecencode_ber_contentsbufv=matchvwith|Value.Null ->Value.Primitive|Value.Boolb->Netbuffer.add_charbuf(ifbthen'\xff'else'\x00');Value.Primitive|Value.Integern|Value.Enumn->lets=Value.get_int_reprninNetbuffer.add_stringbufs;Value.Primitive|Value.Realn->lets=Value.get_real_reprninNetbuffer.add_stringbufs;Value.Primitive|Value.OIDoid->ifArray.lengthoid<=2thenencode_error"bad OID in input";letx=oid.(0)inlety=oid.(1)inifx<0||x>2||y<0||y>39thenencode_error"badOID in input";encode_base128buf(x*40+y);fork=2toArray.lengthoid-1doencode_base128bufoid.(k)done;Value.Primitive|Value.ROIDoid->fork=0toArray.lengthoid-1doencode_base128bufoid.(k)done;Value.Primitive|Value.Octetstrings|Value.ObjectDescriptors|Value.UTF8Strings|Value.NumericStrings|Value.PrintableStrings|Value.TeletexStrings|Value.VideotexStrings|Value.IA5Strings|Value.GraphicStrings|Value.VisibleStrings|Value.GeneralStrings|Value.UniversalStrings|Value.CharStrings|Value.BMPStrings->Netbuffer.add_stringbufs;Value.Primitive|Value.UTCTimet->ifValue.get_time_subtypet<>`Uthenencode_error"wrong time format for UTCTime";lets=Value.get_time_reprtinNetbuffer.add_stringbufs;Value.Primitive|Value.GeneralizedTimet->ifValue.get_time_subtypet<>`Gthenencode_error"wrong time format for GeneralizedTime";lets=Value.get_time_reprtinNetbuffer.add_stringbufs;Value.Primitive|Value.Bitstringbs->lets=Value.get_bitstring_reprbsinNetbuffer.add_stringbuf s;Value.Primitive|Value.Seqvals|Value.Setvals|Value.Externalvals|Value.Embedded_PDVvals->List.iter(funv->ignore(encode_berbufv))vals;Value.Constructed|Value.ITag(_,_,v)->(matchvwith|Value.ITag_|Value.Tagptr_->encode_berbufv|_->encode_ber_contentsbufv)|Value.Tag(_,_,_,v)->encode_berbufv|Value.Tagptr(_,_,pc,box,pos,len)->letNetstring_tstring.Tstring_polybox(ops,s)=boxinNetbuffer.add_subtstring_polybufopssposlen;pcandencode_berbufv=letbuf'=Netbuffer.create80inletpc=encode_ber_contentsbuf'vinlet length=Netbuffer.lengthbuf'inlettc,tag=tag_of_valuevinlettc_bits=matchtcwith|Value.Universal->0|Value.Application->1|Value.Context->2|Value.Private->3inletpc_bit=matchpcwith|Value.Primitive->0|Value.Constructed->1inletoctet0=(tc_bitslsl6)lor(pc_bitlsl5)lor(iftag<=30thentagelse31)inNetbuffer.add_charbuf (Char.chroctet0);iftag>30thenencode_base128 buftag;iflength<128thenNetbuffer.add_charbuf(Char.chrlength)else(iflength<=0xffthen (Netbuffer.add_charbuf'\x81';Netbuffer.add_charbuf (Char.chrlength);)elseiflength<=0xffff then(Netbuffer.add_charbuf'\x82';Netbuffer.add_charbuf (Char.chr(lengthlsr8));Netbuffer.add_char buf (Char.chr(lengthland0xff));)else(leti=Value.intlengthinlets0=Value.get_int_repriinlets1=(* integers are signed, but we need here unsigned ints: *)ifs0.[0]='\x00'thenString.subs01(String.lengths0-1)elses0inNetbuffer.add_charbuf(Char.chr(0x80+String.lengths1));Netbuffer.add_stringbufs1;));Netbuffer.add_bufferbufbuf';pc