Welcome to mirror list, hosted at ThFree Co, Russian Federation.

xmpp_codec.spec « tools - github.com/processone/ejabberd.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: ebcb77e96c639536fc102a679ba4c3a8858221e5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
{spec, last,
 #spec{name = <<"query">>,
       min = 0, max = 1,
       xmlns = <<"jabber:iq:last">>,
       result = {last, '$seconds', '$text'},
       attrs = [#attr{name = <<"seconds">>,
                      default = undefined,
                      enc = {enc_int, []},
                      dec = {dec_int, [0, infinity]}}],
       cdata = #cdata{label = '$text'}}}.

{spec, version,
 #spec{name = <<"query">>,
       xmlns = <<"jabber:iq:version">>,
       min = 0, max = 1,
       result = {version, '$name', '$version', '$os'},
       els = [#spec{name = <<"name">>,
                    min = 0, max = 1,
                    result = '$cdata',
                    cdata = #cdata{label = '$cdata', required = true}},
              #spec{name = <<"version">>,
                    min = 0, max = 1,
                    result = '$cdata',
                    cdata = #cdata{label = '$cdata', required = true}},
              #spec{name = <<"os">>,
                    min = 0, max = 1,
                    result = '$cdata',
                    cdata = #cdata{label = '$cdata', required = true}}]}}.

{spec, roster,
 #spec{name = <<"query">>,
       xmlns = <<"jabber:iq:roster">>,
       result = {roster, '$item', '$ver'},
       min = 0, max = 1,
       attrs = [#attr{name = <<"ver">>}],
       els = [#spec{name = <<"item">>,
                    result = {roster_item, '$jid', '$name',
                              '$groups', '$subscription', '$ask'},
                    attrs = [#attr{name = <<"jid">>,
                                   required = true,
                                   dec = {dec_jid, []},
                                   enc = {enc_jid, []}},
                             #attr{name = <<"name">>},
                             #attr{name = <<"subscription">>,
                                   default = none,
                                   enc = {enc_enum, []},
                                   dec = {dec_enum, [[none,to,from,both,remove]]}},
                             #attr{name = <<"ask">>,
                                   default = undefined,
                                   enc = {enc_enum, []},
                                   dec = {dec_enum, [[subscribe]]}}],
                    els = [#spec{name = <<"group">>,
                                 label = '$groups',
                                 result = '$cdata',
                                 cdata = #cdata{required = true,
                                                label = '$cdata'}}]}]}}.

{spec, privacy_item,
 #spec{name = <<"item">>,
       result = {privacy_item, '$order', '$action', '$type',
                 '$value', '$stanza'},
       label = '$privacy_item',
       attrs = [#attr{name = <<"action">>,
                      required = true,
                      dec = {dec_enum, [[allow, deny]]},
                      enc = {enc_enum, []}},
                #attr{name = <<"order">>,
                      required = true,
                      dec = {dec_int, [0, infinity]},
                      enc = {enc_int, []}},
                #attr{name = <<"type">>,
                      dec = {dec_enum, [[group, jid, subscription]]},
                      enc = {enc_enum, []}},
                #attr{name = <<"value">>}],
       els = [#spec{name = <<"message">>,
                    min = 0, max = 1,
                    label = '$stanza',
                    result = message},
              #spec{name = <<"iq">>,
                    min = 0, max = 1,
                    label = '$stanza',
                    result = iq},
              #spec{name = <<"presence-in">>,
                    min = 0, max = 1,
                    label = '$stanza',
                    result = 'presence-in'},
              #spec{name = <<"presence-out">>,
                    min = 0, max = 1,
                    label = '$stanza',
                    result = 'presence-out'}]}}.

{spec, privacy,
 #spec{name = <<"query">>,
       min = 0, max = 1,
       xmlns = <<"jabber:iq:privacy">>,
       result = {privacy, '$list', '$default', '$active'},
       els = [#spec{name = <<"list">>,
                    result = {privacy_list, '$name', '$privacy_item'},
                    attrs = [#attr{name = <<"name">>,
                                   required = true}],
                    els = [privacy_item]},
              #spec{name = <<"default">>,
                    min = 0, max = 1,
                    result = '$name',
                    attrs = [#attr{name = <<"name">>,
                                   default = none}]},
              #spec{name = <<"active">>,
                    min = 0, max = 1,
                    result = '$name',
                    attrs = [#attr{name = <<"name">>,
                                   default = none}]}]}}.

{spec, block_item,
 #spec{name = <<"item">>,
       label = '$block_item',
       result = '$jid',
       attrs = [#attr{name = <<"jid">>,
                      required = true,
                      dec = {dec_jid, []},
                      enc = {enc_jid, []}}]}}.

{spec, block,
 #spec{name = <<"block">>,
       xmlns = <<"urn:xmpp:blocking">>,
       min = 0, max = 1,
       result = {block, '$block_item'},
       els = [block_item]}}.

{spec, unblock,
 #spec{name = <<"unblock">>,
       xmlns = <<"urn:xmpp:blocking">>,
       min = 0, max = 1,
       result = {unblock, '$block_item'},
       els = [block_item]}}.

{spec, block_list,
 #spec{name = <<"blocklist">>,
       xmlns = <<"urn:xmpp:blocking">>,
       result = {block_list},
       min = 0, max = 1}}.

{spec, disco_info,
 #spec{name = <<"query">>,
       min = 0, max = 1,
       xmlns = <<"http://jabber.org/protocol/disco#info">>,
       result = {disco_info, '$node', '$identity', '$feature', '$xdata'},
       attrs = [#attr{name = <<"node">>}],
       els = [#spec{name = <<"identity">>,
                    result = {'$category', '$type', '$name'},
                    attrs = [#attr{name = <<"category">>,
                                   required = true},
                             #attr{name = <<"type">>,
                                   required = true},
                             #attr{name = <<"name">>}]},
              #spec{name = <<"feature">>,
                    result = '$var',
                    attrs = [#attr{name = <<"var">>,
                                   required = true}]},
              xdata]}}.

{spec, disco_items,
 #spec{name = <<"query">>,
       min = 0, max = 1,
       xmlns = <<"http://jabber.org/protocol/disco#items">>,
       result = {disco_items, '$node', '$items'},
       attrs = [#attr{name = <<"node">>}],
       els = [#spec{name = <<"item">>,
                    label = '$items',
                    result = {disco_item, '$jid', '$name', '$node'},
                    cdata = #cdata{label = '$cdata'},
                    attrs = [#attr{name = <<"jid">>,
                                   dec = {dec_jid, []},
                                   enc = {enc_jid, []},
                                   required = true},
                             #attr{name = <<"name">>},
                             #attr{name = <<"node">>}]}]}}.

{spec, private,
 #spec{name = <<"query">>,
       min = 0, max = 1,
       xmlns = <<"jabber:iq:private">>,
       result = {private, '$_els'}}}.

{spec, bookmark_conference,
 #spec{name = <<"conference">>,
       result = {bookmark_conference, '$name', '$jid',
                 '$autojoin', '$nick', '$password'},
       attrs = [#attr{name = <<"name">>,
                      required = true},
                #attr{name = <<"jid">>,
                      required = true,
                      dec = {dec_jid, []},
                      enc = {enc_jid, []}},
                #attr{name = <<"autojoin">>,
                      default = false,
                      dec = {dec_bool, []},
                      enc = {enc_bool, []}}],
       els = [#spec{name = <<"nick">>,
                    min = 0, max = 1,
                    result = '$cdata'},
              #spec{name = <<"password">>,
                    min = 0, max = 1,
                    result = '$cdata'}]}}.

{spec, storage_bookmarks,
 #spec{name = <<"storage">>,
       xmlns = <<"storage:bookmarks">>,
       min = 0, max = 1,
       result = {bookmark_storage, '$conference', '$url'},
       els = [bookmark_conference,
              #spec{name = <<"url">>,
                    result = {bookmark_url, '$name', '$url'},
                    attrs = [#attr{name = <<"name">>,
                                   required = true},
                             #attr{name = <<"url">>,
                                   required = true}]}]}}.

{spec, stats,
 #spec{name = <<"query">>,
       min = 0, max = 1,
       xmlns = <<"http://jabber.org/protocol/stats">>,
       result = {stats, '$stat'},
       els = [#spec{name = <<"stat">>,
                    result = {stat, '$name', '$units', '$value', '$error'},
                    attrs = [#attr{name = <<"name">>,
                                   required = true},
                             #attr{name = <<"units">>},
                             #attr{name = <<"value">>}],
                    els = [#spec{name = <<"error">>,
                                 result = {'$code', '$cdata'},
                                 attrs = [#attr{name = <<"code">>,
                                                required = true,
                                                enc = {enc_int, []},
                                                dec = {dec_int, []}}]}]}]}}.

{spec, iq,
 #spec{name = <<"iq">>,
       min = 0, max = 1,
       result = {iq, '$id', '$type', '$lang', '$from', '$to',
                 '$error', '$_els'},
       attrs = [#attr{name = <<"id">>,
                      required = true},
                #attr{name = <<"type">>,
                      required = true,
                      enc = {enc_enum, []},
                      dec = {dec_enum, [[get, set, result, error]]}},
                #attr{name = <<"from">>,
                      dec = {dec_jid, []},
                      enc = {enc_jid, []}},
                #attr{name = <<"to">>,
                      dec = {dec_jid, []},
                      enc = {enc_jid, []}},
                #attr{name = <<"xml:lang">>,
                      label = '$lang'}],
       els = [error]}}.

{spec, message,
 #spec{name = <<"message">>,
       min = 0, max = 1,
       result = {message, '$id', '$type', '$lang', '$from', '$to',
                 '$subject', '$body', '$thread', '$error', '$_els'},
       attrs = [#attr{name = <<"id">>},
                #attr{name = <<"type">>,
                      default = normal,
                      enc = {enc_enum, []},
                      dec = {dec_enum, [[chat, normal, groupchat,
                                         headline, error]]}},
                #attr{name = <<"from">>,
                      dec = {dec_jid, []},
                      enc = {enc_jid, []}},
                #attr{name = <<"to">>,
                      dec = {dec_jid, []},
                      enc = {enc_jid, []}},
                #attr{name = <<"xml:lang">>,
                      label = '$lang'}],
       els = [error,
              #spec{name = <<"subject">>,
                    result = {'$subject_lang', '$cdata'},
                    attrs = [#attr{name = <<"xml:lang">>,
                                   label = '$subject_lang'}]},
              #spec{name = <<"body">>,
                    result = {'$body_lang', '$cdata'},
                    attrs = [#attr{name = <<"xml:lang">>,
                                   label = '$body_lang'}]},
              #spec{name = <<"thread">>,
                    min = 0, max = 1,
                    result = '$cdata'}]}}.

{spec, presence,
 #spec{name = <<"presence">>,
       min = 0, max = 1,
       result = {presence, '$id', '$type', '$lang', '$from', '$to',
                 '$show', '$status', '$priority', '$error', '$_els'},
       attrs = [#attr{name = <<"id">>},
                #attr{name = <<"type">>,
                      enc = {enc_enum, []},
                      dec = {dec_enum, [[unavailable, subscribe, subscribed,
                                         unsubscribe, unsubscribed,
                                         probe, error]]}},
                #attr{name = <<"from">>,
                      dec = {dec_jid, []},
                      enc = {enc_jid, []}},
                #attr{name = <<"to">>,
                      dec = {dec_jid, []},
                      enc = {enc_jid, []}},
                #attr{name = <<"xml:lang">>,
                      label = '$lang'}],
       els = [error,
              #spec{name = <<"show">>,
                    min = 0, max = 1,
                    result = '$cdata',
                    cdata = #cdata{enc = {enc_enum, []},
                                   dec = {dec_enum, [[away, chat, dnd, xa]]}}},
              #spec{name = <<"status">>,
                    result = {'$status_lang', '$cdata'},
                    attrs = [#attr{name = <<"xml:lang">>,
                                   label = '$status_lang'}]},
              #spec{name = <<"priority">>,
                    min = 0, max = 1,
                    result = '$cdata',
                    cdata = #cdata{enc = {enc_int, []},
                                   dec = {dec_int, [-128, 127]}}}]}}.

{spec, error,
 #spec{name = <<"error">>,
       min = 0, max = 1,
       result = {error, '$error_type', '$by', '$reason', '$text'},
       attrs = [#attr{name = <<"type">>,
                      label = '$error_type',
                      required = true,
                      dec = {dec_enum, [[auth, cancel, continue,
                                         modify, wait]]},
                      enc = {enc_enum, []}},
                #attr{name = <<"by">>}],
       els = [#spec{name = <<"text">>,
                    min = 0, max = 1,
                    result = {'$text_lang', '$cdata'},
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
                    attrs = [#attr{name = <<"xml:lang">>,
                                   label = '$text_lang'}]},
              #spec{name = <<"bad-request">>, 
                    result = 'bad-request',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"conflict">>, 
                    result = 'conflict',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"feature-not-implemented">>, 
                    result = 'feature-not-implemented',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"forbidden">>, 
                    result = 'forbidden',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"gone">>, 
                    result = {'gone', '$cdata'},
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"internal-server-error">>, 
                    result = 'internal-server-error',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"item-not-found">>, 
                    result = 'item-not-found',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"jid-malformed">>, 
                    result = 'jid-malformed',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"not-acceptable">>, 
                    result = 'not-acceptable',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"not-allowed">>, 
                    result = 'not-allowed',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"not-authorized">>, 
                    result = 'not-authorized',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"policy-violation">>, 
                    result = 'policy-violation',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"recipient-unavailable">>, 
                    result = 'recipient-unavailable',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"redirect">>, 
                    result = {'redirect', '$cdata'},
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"registration-required">>, 
                    result = 'registration-required',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"remote-server-not-found">>, 
                    result = 'remote-server-not-found',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"remote-server-timeout">>, 
                    result = 'remote-server-timeout',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"resource-constraint">>, 
                    result = 'resource-constraint',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"service-unavailable">>, 
                    result = 'service-unavailable',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"subscription-required">>, 
                    result = 'subscription-required',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"undefined-condition">>, 
                    result = 'undefined-condition',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"unexpected-request">>, 
                    result = 'unexpected-request',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-stanzas">>,
                    min = 0, max = 1, label = '$reason'}]}}.
                     
{spec, bind,
 #spec{name = <<"bind">>,
       xmlns = <<"urn:ietf:params:xml:ns:xmpp-bind">>,
       min = 0, max = 1,
       result = {bind, '$jid', '$resource'},
       els = [#spec{name = <<"jid">>,
                    min = 0, max = 1,
                    result = '$cdata',
                    cdata = #cdata{dec = {dec_jid, []},
                                   enc = {enc_jid, []}}},
              #spec{name = <<"resource">>,
                    min = 0, max = 1,
                    result = '$cdata',
                    cdata = #cdata{dec = {resourceprep, []},
                                   enc = {resourceprep, []}}}]}}.

{spec, sasl_auth,
 #spec{name = <<"auth">>,
       xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>,
       min = 0, max = 1,
       cdata = #cdata{dec = {base64, decode, []},
                      enc = {base64, encode, []}},
       result = {sasl_auth, '$mechanism', '$cdata'},
       attrs = [#attr{name = <<"mechanism">>,
                      required = true}]}}.

{spec, sasl_abort,
 #spec{name = <<"abort">>,
       xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>,
       min = 0, max = 1,
       result = {sasl_abort}}}.

{spec, sasl_challenge,
 #spec{name = <<"challenge">>,
       xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>,
       min = 0, max = 1,
       cdata = #cdata{dec = {base64, decode, []},
                      enc = {base64, encode, []}},
       result = {sasl_challenge, '$cdata'}}}.

{spec, sasl_response,
 #spec{name = <<"response">>,
       xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>,
       min = 0, max = 1,
       cdata = #cdata{dec = {base64, decode, []},
                      enc = {base64, encode, []}},
       result = {sasl_response, '$cdata'}}}.

{spec, sasl_success,
 #spec{name = <<"success">>,
       xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>,
       min = 0, max = 1,
       cdata = #cdata{dec = {base64, decode, []},
                      enc = {base64, encode, []}},
       result = {sasl_success, '$cdata'}}}.

{spec, sasl_failure,
 #spec{name = <<"failure">>,
       xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>,
       min = 0, max = 1,
       result = {sasl_failure, '$reason', '$text'},
       els = [#spec{name = <<"text">>,
                    min = 0, max = 1,
                    result = {'$text_lang', '$cdata'},
                    attrs = [#attr{name = <<"xml:lang">>,
                                   label = '$text_lang'}]},
              #spec{name = <<"aborted">>,
                    result = 'aborted',
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"account-disabled">>,
                    result = 'account-disabled',
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"credentials-expired">>,
                    result = 'credentials-expired',
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"encryption-required">>,
                    result = 'encryption-required',
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"incorrect-encoding">>,
                    result = 'incorrect-encoding',
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"invalid-authzid">>,
                    result = 'invalid-authzid',
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"invalid-mechanism">>,
                    result = 'invalid-mechanism',
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"malformed-request">>,
                    result = 'malformed-request',
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"mechanism-too-weak">>,
                    result = 'mechanism-too-weak',
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"not-authorized">>,
                    result = 'not-authorized',
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"temporary-auth-failure">>,
                    result = 'temporary-auth-failure',
                    min = 0, max = 1, label = '$reason'}]}}.

{spec, sasl_mechanism,
 #spec{name = <<"mechanism">>,
       result = '$cdata',
       min = 1,
       cdata = #cdata{}}}.

{spec, sasl_mechanisms,
 #spec{name = <<"mechanisms">>,
       xmlns = <<"urn:ietf:params:xml:ns:xmpp-sasl">>,
       result = {sasl_mechanisms, '$mechanism'},
       min = 0, max = 1,
       els = [sasl_mechanism]}}.

{spec, starttls,
 #spec{name = <<"starttls">>,
       xmlns = <<"urn:ietf:params:xml:ns:xmpp-tls">>,
       min = 0, max = 1,
       result = {starttls, '$required'},
       els = [#spec{name = <<"required">>,
                    min = 0, max = 1,
                    default = false,
                    result = true}]}}.

{spec, starttls_proceed,
 #spec{name = <<"proceed">>,
       xmlns = <<"urn:ietf:params:xml:ns:xmpp-tls">>,
       min = 0, max = 1,
       result = {starttls_proceed}}}.

{spec, starttls_failure,
 #spec{name = <<"failure">>,
       xmlns = <<"urn:ietf:params:xml:ns:xmpp-tls">>,
       min = 0, max = 1,
       result = {starttls_failure}}}.

{spec, stream_features,
 #spec{name = <<"stream:features">>,
       min = 0, max = 1,
       result = {stream_features, '$_els'}}}.

{spec, p1_push,
 #spec{name = <<"push">>,
       min = 0, max = 1,
       result = {p1_push},
       xmlns = <<"p1:push">>}}.

{spec, p1_rebind,
 #spec{name = <<"rebind">>,
       min = 0, max = 1,
       result = {p1_rebind},
       xmlns = <<"p1:rebind">>}}.

{spec, p1_ack,
 #spec{name = <<"ack">>,
       min = 0, max = 1,
       result = {p1_ack},
       xmlns = <<"p1:ack">>}}.

{spec, caps,
 #spec{name = <<"c">>,
       min = 0, max = 1,
       xmlns = <<"http://jabber.org/protocol/caps">>,
       result = {caps, '$hash', '$node', '$ver'},
       attrs = [#attr{name = <<"hash">>},
                #attr{name = <<"node">>},
                #attr{name = <<"ver">>,
                      enc = {base64, encode, []},
                      dec = {base64, decode, []}}]}}.

{spec, register,
 #spec{name = <<"register">>,
       min = 0, max = 1,
       xmlns = <<"http://jabber.org/features/iq-register">>,
       result = {register}}}.

{spec, session,
 #spec{name = <<"session">>,
       min = 0, max = 1,
       xmlns = <<"urn:ietf:params:xml:ns:xmpp-session">>,
       result = {session}}}.

{spec, ping,
 #spec{name = <<"ping">>,
       min = 0, max = 1,
       xmlns = <<"urn:xmpp:ping">>,
       result = {ping}}}.

{spec, time,
 #spec{name = <<"time">>,
       min = 0, max = 1,
       xmlns = <<"urn:xmpp:time">>,
       result = {time, '$tzo', '$utc'},
       els = [#spec{name = <<"tzo">>,
                    min = 0, max = 1,
                    result = '$cdata',
                    cdata = #cdata{dec = {dec_tzo, []},
                                   enc = {enc_tzo, []}}},
              #spec{name = <<"utc">>,
                    min = 0, max = 1,
                    result = '$cdata',
                    cdata = #cdata{dec = {dec_utc, []},
                                   enc = {enc_utc, []}}}]}}.

{spec, stream_error,
 #spec{name = <<"stream:error">>,
       min = 0, max = 1,
       result = {stream_error, '$reason', '$text'},
       els = [#spec{name = <<"text">>,
                    min = 0, max = 1,
                    result = {'$text_lang', '$cdata'},
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>,
                    attrs = [#attr{name = <<"xml:lang">>,
                                   label = '$text_lang'}]},
              #spec{name = <<"bad-format">>,
                    result = 'bad-format',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"bad-namespace-prefix">>,
                    result = 'bad-namespace-prefix',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"conflict">>,
                    result = 'conflict',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"connection-timeout">>,
                    result = 'connection-timeout',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"host-gone">>,
                    result = 'host-gone',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"host-unknown">>,
                    result = 'host-unknown',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"improper-addressing">>,
                    result = 'improper-addressing',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"internal-server-error">>,
                    result = 'internal-server-error',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"invalid-from">>,
                    result = 'invalid-from',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"invalid-id">>,
                    result = 'invalid-id',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"invalid-namespace">>,
                    result = 'invalid-namespace',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"invalid-xml">>,
                    result = 'invalid-xml',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"not-authorized">>,
                    result = 'not-authorized',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"not-well-formed">>,
                    result = 'not-well-formed',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"policy-violation">>,
                    result = 'policy-violation',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"remote-connection-failed">>,
                    result = 'remote-connection-failed',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"reset">>,
                    result = 'reset',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"resource-constraint">>,
                    result = 'resource-constraint',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"restricted-xml">>,
                    result = 'restricted-xml',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"see-other-host">>,
                    result = {'see-other-host', '$cdata'},
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"system-shutdown">>,
                    result = 'system-shutdown',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"undefined-condition">>,
                    result = 'undefined-condition',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"unsupported-encoding">>,
                    result = 'unsupported-encoding',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"unsupported-stanza-type">>,
                    result = 'unsupported-stanza-type',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>,
                    min = 0, max = 1, label = '$reason'},
              #spec{name = <<"unsupported-version">>,
                    result = 'unsupported-version',
                    xmlns = <<"urn:ietf:params:xml:ns:xmpp-streams">>,
                    min = 0, max = 1, label = '$reason'}
             ]}}.

{spec, vcard_name,
 #spec{name = <<"N">>, label = '$n',
       min = 0, max = 1,
       result = {vcard_name, '$family', '$given', '$middle',
                 '$prefix', '$suffix'},
       els = [#spec{name = <<"FAMILY">>, label = '$family',
                    min = 0, max = 1, result = '$cdata'},
              #spec{name = <<"GIVEN">>, label = '$given',
                    min = 0, max = 1, result = '$cdata'},
              #spec{name = <<"MIDDLE">>, label = '$middle',
                    min = 0, max = 1, result = '$cdata'},
              #spec{name = <<"PREFIX">>, label = '$prefix',
                    min = 0, max = 1, result = '$cdata'},
              #spec{name = <<"SUFFIX">>, label = '$suffix',
                    min = 0, max = 1, result = '$cdata'}]}}.

{spec, vcard_adr,
 #spec{name = <<"ADR">>, label = '$adr',
       result = {vcard_adr, '$home', '$work', '$postal', '$parcel',
                '$dom', '$intl', '$pref', '$pobox', '$extadd', '$street',
                '$locality', '$region', '$pcode', '$ctry'},
       els = [#spec{name = <<"HOME">>, label = '$home',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"WORK">>, label = '$work',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"POSTAL">>, label = '$postal',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"PARCEL">>, label = '$parcel',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"DOM">>, label = '$dom',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"INTL">>, label = '$intl',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"PREF">>, label = '$pref',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"POBOX">>, label = '$pobox',
                    min = 0, max = 1, result = '$cdata'},
              #spec{name = <<"EXTADD">>, label = '$extadd',
                    min = 0, max = 1, result = '$cdata'},
              #spec{name = <<"STREET">>, label = '$street',
                    min = 0, max = 1, result = '$cdata'},
              #spec{name = <<"LOCALITY">>, label = '$locality',
                    min = 0, max = 1, result = '$cdata'},
              #spec{name = <<"REGION">>, label = '$region',
                    min = 0, max = 1, result = '$cdata'},
              #spec{name = <<"PCODE">>, label = '$pcode',
                    min = 0, max = 1, result = '$cdata'},
              #spec{name = <<"CTRY">>, label = '$ctry',
                    min = 0, max = 1, result = '$cdata'}]}}.

{spec, vcard_label,
 #spec{name = <<"LABEL">>, label = '$label',
       result = {vcard_label, '$home', '$work', '$postal', '$parcel',
                '$dom', '$intl', '$pref', '$line'},
       els = [#spec{name = <<"HOME">>, label = '$home',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"WORK">>, label = '$work',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"POSTAL">>, label = '$postal',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"PARCEL">>, label = '$parcel',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"DOM">>, label = '$dom',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"INTL">>, label = '$intl',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"PREF">>, label = '$pref',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"LINE">>, label = '$line',
                    result = '$cdata'}]}}.

{spec, vcard_tel,
 #spec{name = <<"TEL">>, label = '$tel',
       result = {vcard_tel, '$home', '$work', '$voice', '$fax',
                 '$pager', '$msg', '$cell', '$video', '$bbs',
                 '$modem', '$isdn', '$pcs', '$pref', '$number'},
       els = [#spec{name = <<"HOME">>, label = '$home',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"WORK">>, label = '$work',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"VOICE">>, label = '$voice',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"FAX">>, label = '$fax',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"PAGER">>, label = '$pager',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"MSG">>, label = '$msg',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"CELL">>, label = '$cell',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"VIDEO">>, label = '$video',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"BBS">>, label = '$bbs',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"MODEM">>, label = '$modem',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"ISDN">>, label = '$isdn',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"PCS">>, label = '$pcs',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"PREF">>, label = '$pref',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"NUMBER">>, label = '$number',
                    min = 1, max = 1, result = '$cdata'}]}}.

{spec, vcard_email,
 #spec{name = <<"EMAIL">>, label = '$email',
       result = {vcard_email, '$home', '$work',
                '$internet', '$pref', '$x400', '$userid'},
       els = [#spec{name = <<"HOME">>, label = '$home',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"WORK">>, label = '$work',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"INTERNET">>, label = '$internet',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"PREF">>, label = '$pref',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"X400">>, label = '$x400',
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"USERID">>, label = '$userid',
                    min = 1, max = 1, result = '$cdata'}]}}.

{spec, vcard_geo,
 #spec{name = <<"GEO">>, label = '$geo',
       min = 0, max = 1,
       result = {vcard_geo, '$lat', '$lon'},
       els = [#spec{name = <<"LAT">>, label = '$lat',
                    min = 1, max = 1, result = '$cdata'},
              #spec{name = <<"LON">>, label = '$lon',
                    min = 1, max = 1, result = '$cdata'}]}}.

{spec, vcard_type,
 #spec{name = <<"TYPE">>, label = '$type',
       min = 0, max = 1,
       result = '$cdata'}}.

{spec, vcard_binval,
 #spec{name = <<"BINVAL">>, label = '$binval',
       min = 0, max = 1,
       cdata = #cdata{dec = {base64, decode, []},
                      enc = {base64, encode, []}},
       result = '$cdata'}}.

{spec, vcard_extval,
 #spec{name = <<"EXTVAL">>, label = '$extval',
       min = 0, max = 1,
       result = '$cdata'}}.

{spec, vcard_logo,
 #spec{name = <<"LOGO">>, label = '$logo',
       min = 0, max = 1,
       result = {vcard_logo, '$type', '$binval', '$extval'},
       els = [vcard_type, vcard_binval, vcard_extval]}}.

{spec, vcard_photo,
 #spec{name = <<"PHOTO">>, label = '$photo',
       min = 0, max = 1,
       result = {vcard_photo, '$type', '$binval', '$extval'},
       els = [vcard_type, vcard_binval, vcard_extval]}}.

{spec, vcard_org,
  #spec{name = <<"ORG">>, label = '$org',
        min = 0, max = 1,
        result = {vcard_org, '$name', '$units'},
        els = [#spec{name = <<"ORGNAME">>,
                     label = '$name',
                     min = 1, max = 1,
                     result = '$cdata'},
               #spec{name = <<"ORGUNIT">>,
                     label = '$units',
                     result = '$cdata'}]}}.

{spec, vcard_sound,
 #spec{name = <<"SOUND">>, label = '$sound',
       min = 0, max = 1,
       result = {vcard_sound, '$phonetic', '$binval', '$extval'},
       els = [vcard_binval, vcard_extval,
              #spec{name = <<"PHONETIC">>,
                    min = 0, max = 1,
                    result = '$cdata'}]}}.

{spec, vcard_key,
 #spec{name = <<"KEY">>, label = '$key',
       min = 0, max = 1,
       result = {vcard_key, '$type', '$cred'},
       els = [vcard_type,
              #spec{name = <<"CRED">>,
                    min = 1, max = 1,
                    result = '$cdata'}]}}.

{spec, vcard,
 #spec{name = <<"vCard">>,
       xmlns = <<"vcard-temp">>,
       min = 0, max = 1,
       result = {vcard, '$version', '$fn', '$n', '$nickname', '$photo',
                 '$bday', '$adr', '$label', '$tel', '$email', '$jabberid',
                 '$mailer', '$tz', '$geo', '$title', '$role', '$logo',
                 %% '$agent' XXX: recursive specs are to be implemented
                 '$org', '$categories', '$note', '$prodid',
                 '$rev', '$sort-string', '$sound', '$uid', '$url', '$class',
                 '$key', '$desc'},
       els = [vcard_name, vcard_adr, vcard_label, vcard_tel,
              vcard_email, vcard_geo, vcard_logo, vcard_photo,
              vcard_org, vcard_sound, vcard_key,
              #spec{name = <<"VERSION">>, label = '$version',
                    min = 0, max = 1, result = '$cdata'},
              #spec{name = <<"FN">>, label = '$fn',
                    min = 0, max = 1, result = '$cdata'},
              #spec{name = <<"NICKNAME">>, label = '$nickname',
                    min = 0, max = 1, result = '$cdata'},
              #spec{name = <<"BDAY">>, label = '$bday',
                    min = 0, max = 1, result = '$cdata'},
              #spec{name = <<"JABBERID">>, label = '$jabberid',
                    min = 0, max = 1, result = '$cdata'},
              #spec{name = <<"MAILER">>, label = '$mailer',
                    min = 0, max = 1, result = '$cdata'},
              #spec{name = <<"TZ">>, label = '$tz',
                    min = 0, max = 1, result = '$cdata'},
              #spec{name = <<"TITLE">>, label = '$title',
                    min = 0, max = 1, result = '$cdata'},
              #spec{name = <<"ROLE">>, label = '$role',
                    min = 0, max = 1, result = '$cdata'},
              #spec{name = <<"CATEGORIES">>, label = '$categories',
                    default = [],
                    min = 0, max = 1,
                    result = '$keywords',
                    els = [#spec{name = <<"KEYWORD">>,
                                 label = '$keywords',
                                 result = '$cdata'}]},
              #spec{name = <<"NOTE">>, label = '$note',
                    min = 0, max = 1, result = '$cdata'},
              #spec{name = <<"PRODID">>, label = '$prodid',
                    min = 0, max = 1, result = '$cdata'},
              #spec{name = <<"REV">>, label = '$rev',
                    min = 0, max = 1, result = '$cdata'},
              #spec{name = <<"SORT-STRING">>, label = '$sort-string',
                    min = 0, max = 1, result = '$cdata'},
              #spec{name = <<"UID">>, label = '$uid',
                    min = 0, max = 1, result = '$cdata'},
              #spec{name = <<"URL">>, label = '$url',
                    min = 0, max = 1, result = '$cdata'},
              #spec{name = <<"CLASS">>, label = '$class',
                    min = 0, max = 1,
                    result = '$value',
                    els = [#spec{name = <<"PUBLIC">>,
                                 min = 0, max = 1,
                                 label = '$value',
                                 result = public},
                           #spec{name = <<"PRIVATE">>,
                                 label = '$value',
                                 min = 0, max = 1,
                                 result = private},
                           #spec{name = <<"CONFIDENTIAL">>,
                                 label = '$value',
                                 min = 0, max = 1,
                                 result = confidential}]},
              #spec{name = <<"DESC">>, label = '$desc',
                    min = 0, max = 1, result = '$cdata'}]}}.

{spec, xfield,
 #spec{name = <<"field">>,
       label = '$fields',
       result = {xfield, '$label', '$type', '$var',
                 '$required', '$desc', '$values', '$options'},
       attrs = [#attr{name = <<"label">>},
                #attr{name = <<"type">>,
                      enc = {enc_enum, []},
                      dec = {dec_enum, [['boolean',
                                         'fixed',
                                         'hidden',
                                         'jid-multi',
                                         'jid-single',
                                         'list-multi',
                                         'list-single',
                                         'text-multi',
                                         'text-private',
                                         'text-single']]}},
                #attr{name = <<"var">>}],
       els = [#spec{name = <<"required">>,
                    default = false, result = true,
                    min = 0, max = 1},
              #spec{name = <<"desc">>,
                    min = 0, max = 1,
                    result = '$cdata'},
              #spec{name = <<"value">>,
                    label = '$values',
                    result = '$cdata'},
              #spec{name = <<"option">>,
                    label = '$options',
                    result = '$value',
                    els = [#spec{name = <<"value">>,
                                 min = 1, max = 1,
                                 result = '$cdata'}]}]}}.

{spec, xdata,
 #spec{name = <<"x">>,
       label = '$xdata',
       xmlns = <<"jabber:x:data">>,
       result = {xdata, '$type', '$instructions', '$title',
                 '$reported', '$items', '$fields'},
       attrs = [#attr{name = <<"type">>,
                      required = true,
                      dec = {dec_enum, [[cancel, form, result, submit]]},
                      enc = {enc_enum, []}}],
       els = [#spec{name = <<"instructions">>,
                    result = '$cdata'},
              #spec{name = <<"title">>,
                    min = 0, max = 1,
                    result = '$cdata'},
              #spec{name = <<"reported">>,
                    min = 0, max = 1,
                    result = '$fields',
                    els = [xfield]},
              #spec{name = <<"item">>,
                    label = '$items',
                    result = '$fields',
                    els = [xfield]},
              xfield]}}.

{spec, pubsub_subscription,
 #spec{name = <<"subscription">>,
       label = '$pubsub_subscriptions',
       result = {pubsub_subscription, '$jid', '$node', '$subid',
                 '$type'},
       attrs = [#attr{name = <<"jid">>,
                      required = true,
                      dec = {dec_jid, []},
                      enc = {enc_jid, []}},
                #attr{name = <<"node">>},
                #attr{name = <<"subid">>},
                #attr{name = <<"subscription">>,
                      label = '$type',
                      dec = {dec_enum, [[none, pending, subscribed,
                                         unconfigured]]},
                      enc = {enc_enum, []}}]}}.

{spec, pubsub_affiliation,
 #spec{name = <<"affiliation">>,
       label = '$pubsub_affiliations',
       result = {pubsub_affiliation, '$node', '$type'},
       attrs = [#attr{name = <<"node">>,
                      required = true},
                #attr{name = <<"affiliation">>,
                      label = '$type',
                      required = true,
                      dec = {dec_enum, [[member, none, outcast, owner,
                                         publisher, 'publish-only']]},
                      enc = {enc_enum, []}}]}}.

{spec, pubsub_item,
 #spec{name = <<"item">>,
       result = {pubsub_item, '$id', '$_els'},
       attrs = [#attr{name = <<"id">>}]}}.

{spec, pubsub_items,
 #spec{name = <<"items">>,
       result = {pubsub_items, '$node', '$max_items',
                 '$subid', '$item'},
       attrs = [#attr{name = <<"max_items">>,
                      dec = {dec_int, [0, infinity]},
                      enc = {enc_int, []}},
                #attr{name = <<"node">>,
                      required = true},
                #attr{name = <<"subid">>}],
       els = [pubsub_item]}}.

{spec, pubsub_event,
 #spec{name = <<"event">>,
       min = 0, max = 1,
       xmlns = <<"http://jabber.org/protocol/pubsub#event">>,
       result = {pubsub_event, '$items'},
       els = [pubsub_items]}}.

{spec, pubsub,
 #spec{name = <<"pubsub">>,
       xmlns = <<"http://jabber.org/protocol/pubsub">>,
       result = {pubsub, '$subscriptions', '$affiliations', '$publish',
                 '$subscribe'},
       min = 0, max = 1,
       els = [#spec{name = <<"subscriptions">>,
                    min = 0, max = 1,
                    result = {'$node', '$pubsub_subscriptions'},
                    attrs = [#attr{name = <<"node">>,
                                   default = none}],
                    els = [pubsub_subscription]},
              #spec{name = <<"affiliations">>,
                    min = 0, max = 1,
                    result = '$pubsub_affiliations',
                    els = [pubsub_affiliation]},
              #spec{name = <<"subscribe">>,
                    min = 0, max = 1,
                    result = {'$node', '$jid'},
                    attrs = [#attr{name = <<"node">>},
                             #attr{name = <<"jid">>,
                                   required = true,
                                   dec = {dec_jid, []},
                                   enc = {enc_jid, []}}]},
              #spec{name = <<"publish">>,
                    min = 0, max = 1,
                    result = {'$node', '$item'},
                    attrs = [#attr{name = <<"node">>,
                                   required = true}],
                    els = [pubsub_item]}]}}.

{spec, delay,
 #spec{name = <<"delay">>,
       min = 0, max = 1,
       xmlns = <<"urn:xmpp:delay">>,
       result = {delay, '$stamp', '$from'},
       attrs = [#attr{name = <<"stamp">>,
                      required = true,
                      dec = {dec_utc, []},
                      enc = {enc_utc, []}},
                #attr{name = <<"from">>,
                      dec = {dec_jid, []},
                      enc = {enc_jid, []}}]}}.

dec_tzo(Val) ->
    [H1, M1] = str:tokens(Val, <<":">>),
    H = erlang:binary_to_integer(H1),
    M = erlang:binary_to_integer(M1),
    if H >= -12, H =< 12, M >= 0, M < 60  ->
            {H, M}
    end.

enc_tzo({H, M}) ->
    Sign = if H >= 0 ->
                   <<>>;
              true ->
                   <<"-">>
           end,
    list_to_binary([Sign, io_lib:format("~2..0w:~2..0w", [H, M])]).

dec_utc(Val) ->
    {_, _, _} = jlib:datetime_string_to_timestamp(Val).

enc_utc(Val) ->
    jlib:now_to_utc_string(Val).

dec_jid(Val) ->
    case jlib:string_to_jid(Val) of
        error ->
            erlang:error(badarg);
        J ->
            J
    end.

enc_jid(J) ->            
    jlib:jid_to_string(J).

resourceprep(R) ->
    case jlib:resourceprep(R) of
        error ->
            erlang:error(badarg);
        R1 ->
            R1
    end.

dec_bool(<<"false">>) -> false;
dec_bool(<<"true">>) -> true.

enc_bool(false) -> <<"false">>;
enc_bool(true) -> <<"true">>.

%% Local Variables:
%% mode: erlang
%% End:
%% vim: set filetype=erlang tabstop=8: