summaryrefslogtreecommitdiff
path: root/egg
diff options
context:
space:
mode:
authorStef Walter <stefw@collabora.co.uk>2010-11-23 02:48:38 +0000
committerStef Walter <stefw@collabora.co.uk>2010-11-23 02:48:38 +0000
commitd19b6988da4ab506a1a443be1bd17ba872c29dfc (patch)
tree4e30141eed18806d6071f2bffff5990e326da5c7 /egg
parentca9961d8b2204ba15155e148d41ba7664356164e (diff)
downloadgnome-keyring-d19b6988da4ab506a1a443be1bd17ba872c29dfc.tar.gz
[egg] Encode empty SET OF and SEQUENCE OF properly.
Make choices based on whether they contain any other real valid elements inside.
Diffstat (limited to 'egg')
-rw-r--r--egg/egg-asn1x.c44
1 files changed, 31 insertions, 13 deletions
diff --git a/egg/egg-asn1x.c b/egg/egg-asn1x.c
index ce1be8b6..7226c7c9 100644
--- a/egg/egg-asn1x.c
+++ b/egg/egg-asn1x.c
@@ -159,7 +159,7 @@ struct _Abits {
static gboolean anode_decode_anything (GNode*, Atlv*);
static gboolean anode_decode_anything_for_flags (GNode *, Atlv*, gint);
static gboolean anode_validate_anything (GNode*);
-static gboolean anode_encode_prepare (GNode*);
+static gboolean anode_encode_prepare (GNode*, gboolean want);
static gint
atoin (const char *p, gint digits)
@@ -1555,7 +1555,7 @@ anode_encoder_bit_string (gpointer user_data, guchar *data, gsize n_data)
}
static gboolean
-anode_encode_prepare_simple (GNode *node)
+anode_encode_prepare_simple (GNode *node, gboolean want)
{
Aenc *enc;
Atlv *tlv;
@@ -1574,7 +1574,7 @@ anode_encode_prepare_simple (GNode *node)
}
static gboolean
-anode_encode_prepare_choice (GNode *node)
+anode_encode_prepare_choice (GNode *node, gboolean want)
{
Atlv *tlv;
GNode *child;
@@ -1587,7 +1587,7 @@ anode_encode_prepare_choice (GNode *node)
if (!child)
return FALSE;
- if (!anode_encode_prepare (child))
+ if (!anode_encode_prepare (child, want))
return FALSE;
tlv = anode_get_tlv_data (child);
@@ -1601,22 +1601,39 @@ anode_encode_prepare_choice (GNode *node)
}
static gboolean
-anode_encode_prepare_structured (GNode *node)
+anode_encode_prepare_structured (GNode *node, gboolean want)
{
- gsize length = 0;
+ gboolean child_want;
+ gsize length;
+ gboolean had;
Atlv *tlv;
GNode *child;
gint type;
type = anode_def_type (node);
-
+ child_want = want;
+ had = FALSE;
length = 0;
+ if (type == TYPE_SEQUENCE_OF || type == TYPE_SET_OF)
+ child_want = FALSE;
+
for (child = node->children; child; child = child->next) {
- if (anode_encode_prepare (child)) {
+ if (anode_encode_prepare (child, child_want)) {
tlv = anode_get_tlv_data (child);
g_return_val_if_fail (tlv, FALSE);
length += tlv->off + tlv->len;
+ had = TRUE;
+ }
+ }
+
+ if (had == FALSE) {
+ /* See if we should encode an empty set or seq of */
+ if (type == TYPE_SEQUENCE_OF || type == TYPE_SET_OF) {
+ if (!want)
+ return FALSE;
+ } else {
+ return FALSE;
}
}
@@ -1625,7 +1642,7 @@ anode_encode_prepare_structured (GNode *node)
}
static gboolean
-anode_encode_prepare (GNode *node)
+anode_encode_prepare (GNode *node, gboolean want)
{
switch (anode_def_type (node)) {
case TYPE_INTEGER:
@@ -1637,16 +1654,16 @@ anode_encode_prepare (GNode *node)
case TYPE_ENUMERATED:
case TYPE_GENERALSTRING:
case TYPE_ANY:
- return anode_encode_prepare_simple (node);
+ return anode_encode_prepare_simple (node, want);
break;
case TYPE_SEQUENCE:
case TYPE_SEQUENCE_OF:
case TYPE_SET:
case TYPE_SET_OF:
- return anode_encode_prepare_structured (node);
+ return anode_encode_prepare_structured (node, want);
break;
case TYPE_CHOICE:
- return anode_encode_prepare_choice (node);
+ return anode_encode_prepare_choice (node, want);
break;
default:
g_return_val_if_reached (FALSE);
@@ -1667,7 +1684,7 @@ egg_asn1x_encode (GNode *asn, EggAllocator allocator, gsize *n_data)
if (!allocator)
allocator = g_realloc;
- if (!anode_encode_prepare (asn)) {
+ if (!anode_encode_prepare (asn, TRUE)) {
anode_failure (asn, "missing value(s)");
return NULL;
}
@@ -3091,6 +3108,7 @@ egg_asn1x_set_choice (GNode *node, GNode *choice)
Anode *an;
g_return_val_if_fail (node, FALSE);
+ g_return_val_if_fail (anode_def_type (node) == TYPE_CHOICE, FALSE);
/* One and only one of the children must be set */
for (child = node->children; child; child = child->next) {