Example #1
0
int oid_dotstring_to_oid(const char *name, Odr_oid *oid)
{
    int i = 0;
    int val = 0;
    while (yaz_isdigit (*name))
    {
        val = val*10 + (*name - '0');
        name++;
        if (*name == '.')
        {
            if (i < OID_SIZE-1)
                oid[i++] = val;
            val = 0;
            name++;
        }
    }
    if (i == 0)
        return -1;
    oid[i] = val;
    oid[i+1] = -1;
    return 0;
}
Example #2
0
static int cs_complete_http(const char *buf, int len, int head_only)
{
    /* deal with HTTP request/response */
    int i, content_len = 0, chunked = 0;

    /* need at least one line followed by \n or \r .. */
    for (i = 0; ; i++)
        if (i == len)
            return 0; /* incomplete */
        else if (buf[i] == '\n' || buf[i] == '\r')
            break;

    /* check to see if it's a response with content */
    if (!head_only && !memcmp(buf, "HTTP/", 5))
    {
        int j;
        for (j = 5; j < i; j++)
            if (buf[j] == ' ')
            {
                ++j;
                if (buf[j] == '1') /* 1XX */
                    ;
                else if (!memcmp(buf + j, "204", 3))
                    ;
                else if (!memcmp(buf + j, "304", 3))
                    ;
                else
                    content_len = -1;
                break;
            }
    }
#if 0
    printf("len = %d\n", len);
    fwrite (buf, 1, len, stdout);
    printf("----------\n");
#endif
    for (i = 2; i <= len-2; )
    {
        if (i > 8192)
        {
            return i;  /* do not allow more than 8K HTTP header */
        }
        if (skip_crlf(buf, len, &i))
        {
            if (skip_crlf(buf, len, &i))
            {
                /* inside content */
                if (chunked)
                    return cs_read_chunk(buf, i, len);
                else
                {   /* not chunked ; inside body */
                    if (content_len == -1)
                        return 0;   /* no content length */
                    else if (len >= i + content_len)
                    {
                        return i + content_len;
                    }
                }
                break;
            }
            else if (i < len - 20 &&
                     !yaz_strncasecmp((const char *) buf+i,
                                      "Transfer-Encoding:", 18))
            {
                i+=18;
                while (buf[i] == ' ')
                    i++;
                if (i < len - 8)
                    if (!yaz_strncasecmp((const char *) buf+i, "chunked", 7))
                        chunked = 1;
            }
            else if (i < len - 17 &&
                     !yaz_strncasecmp((const char *)buf+i,
                                      "Content-Length:", 15))
            {
                i+= 15;
                while (buf[i] == ' ')
                    i++;
                content_len = 0;
                while (i <= len-4 && yaz_isdigit(buf[i]))
                    content_len = content_len*10 + (buf[i++] - '0');
                if (content_len < 0) /* prevent negative offsets */
                    content_len = 0;
            }
            else
                i++;
        }
        else
            i++;
    }
    return 0;
}
Example #3
0
static int cs_read_chunk(const char *buf, int i, int len)
{
    /* inside chunked body .. */
    while (1)
    {
        int chunk_len = 0;
#if CHUNK_DEBUG
        if (i < len-2)
        {
            int j;
            printf ("\n<<<");
            for (j = i; j <= i+3; j++)
                printf ("%c", buf[j]);
            printf (">>>\n");
        }
#endif
        /* read chunk length */
        while (1)
            if (i >= len-2) {
#if CHUNK_DEBUG
                printf ("returning incomplete read at 1\n");
                printf ("i=%d len=%d\n", i, len);
#endif
                return 0;
            } else if (yaz_isdigit(buf[i]))
                chunk_len = chunk_len * 16 +
                    (buf[i++] - '0');
            else if (yaz_isupper(buf[i]))
                chunk_len = chunk_len * 16 +
                    (buf[i++] - ('A'-10));
            else if (yaz_islower(buf[i]))
                chunk_len = chunk_len * 16 +
                    (buf[i++] - ('a'-10));
            else
                break;
        if (chunk_len == 0)
            break;
        if (chunk_len < 0)
            return i;

        while (1)
        {
            if (i >= len -1)
                return 0;
            if (skip_crlf(buf, len, &i))
                break;
            i++;
        }
        /* got CRLF */
#if CHUNK_DEBUG
        printf ("chunk_len=%d\n", chunk_len);
#endif
        i += chunk_len;
        if (i >= len-2)
            return 0;
        if (!skip_crlf(buf, len, &i))
            return 0;
    }
    /* consider trailing headers .. */
    while (i < len)
    {
        if (skip_crlf(buf, len, &i))
        {
            if (skip_crlf(buf, len, &i))
                return i;
        }
        else
            i++;
    }
#if CHUNK_DEBUG
    printf ("returning incomplete read at 2\n");
    printf ("i=%d len=%d\n", i, len);
#endif
    return 0;
}
Example #4
0
static int cql_transform_parse_tok_line(cql_transform_t ct,
                                        const char *pattern,
                                        yaz_tok_parse_t tp)
{
    int ae_num = 0;
    Z_AttributeElement *ae[20];
    int ret = 0; /* 0=OK, != 0 FAIL */
    int t;
    t = yaz_tok_move(tp);

    while (t == YAZ_TOK_STRING && ae_num < 20)
    {
        WRBUF type_str = wrbuf_alloc();
        WRBUF set_str = 0;
        Z_AttributeElement *elem = 0;
        const char *value_str = 0;
        /* attset type=value  OR  type=value */

        elem = (Z_AttributeElement *) nmem_malloc(ct->nmem, sizeof(*elem));
        elem->attributeSet = 0;
        ae[ae_num] = elem;
        wrbuf_puts(ct->w, yaz_tok_parse_string(tp));
        wrbuf_puts(type_str, yaz_tok_parse_string(tp));
        t = yaz_tok_move(tp);
        if (t == YAZ_TOK_EOF)
        {
            wrbuf_destroy(type_str);
            if (set_str)
                wrbuf_destroy(set_str);
            break;
        }
        if (t == YAZ_TOK_STRING)
        {
            wrbuf_puts(ct->w, " ");
            wrbuf_puts(ct->w, yaz_tok_parse_string(tp));
            set_str = type_str;

            elem->attributeSet =
                yaz_string_to_oid_nmem(yaz_oid_std(), CLASS_ATTSET,
                                       wrbuf_cstr(set_str), ct->nmem);

            type_str = wrbuf_alloc();
            wrbuf_puts(type_str, yaz_tok_parse_string(tp));
            t = yaz_tok_move(tp);
        }
        elem->attributeType = nmem_intdup(ct->nmem, 0);
        if (sscanf(wrbuf_cstr(type_str), ODR_INT_PRINTF, elem->attributeType)
            != 1)
        {
            wrbuf_destroy(type_str);
            if (set_str)
                wrbuf_destroy(set_str);
            yaz_log(YLOG_WARN, "Expected numeric attribute type");
            ret = -1;
            break;
        }

        wrbuf_destroy(type_str);
        if (set_str)
            wrbuf_destroy(set_str);

        if (t != '=')
        {
            yaz_log(YLOG_WARN, "Expected = after after attribute type");
            ret = -1;
            break;
        }
        t = yaz_tok_move(tp);
        if (t != YAZ_TOK_STRING) /* value */
        {
            yaz_log(YLOG_WARN, "Missing attribute value");
            ret = -1;
            break;
        }
        value_str = yaz_tok_parse_string(tp);
        if (yaz_isdigit(*value_str))
        {
            elem->which = Z_AttributeValue_numeric;
            elem->value.numeric =
                nmem_intdup(ct->nmem, atoi(value_str));
        }
        else
        {
            Z_ComplexAttribute *ca = (Z_ComplexAttribute *)
                nmem_malloc(ct->nmem, sizeof(*ca));
            elem->which = Z_AttributeValue_complex;
            elem->value.complex = ca;
            ca->num_list = 1;
            ca->list = (Z_StringOrNumeric **)
                nmem_malloc(ct->nmem, sizeof(Z_StringOrNumeric *));
            ca->list[0] = (Z_StringOrNumeric *)
                nmem_malloc(ct->nmem, sizeof(Z_StringOrNumeric));
            ca->list[0]->which = Z_StringOrNumeric_string;
            ca->list[0]->u.string = nmem_strdup(ct->nmem, value_str);
            ca->num_semanticAction = 0;
            ca->semanticAction = 0;
        }
        wrbuf_puts(ct->w, "=");
        wrbuf_puts(ct->w, yaz_tok_parse_string(tp));
        t = yaz_tok_move(tp);
        wrbuf_puts(ct->w, " ");
        ae_num++;
    }
    if (ret == 0) /* OK? */
    {
        struct cql_prop_entry **pp = &ct->entry;
        while (*pp)
            pp = &(*pp)->next;
        *pp = (struct cql_prop_entry *) xmalloc(sizeof(**pp));
        (*pp)->pattern = xstrdup(pattern);
        (*pp)->value = xstrdup(wrbuf_cstr(ct->w));

        (*pp)->attr_list.num_attributes = ae_num;
        if (ae_num == 0)
            (*pp)->attr_list.attributes = 0;
        else
        {
            (*pp)->attr_list.attributes = (Z_AttributeElement **)
                nmem_malloc(ct->nmem,
                            ae_num * sizeof(Z_AttributeElement *));
            memcpy((*pp)->attr_list.attributes, ae,
                   ae_num * sizeof(Z_AttributeElement *));
        }
        (*pp)->next = 0;

        if (0)
        {
            ODR pr = odr_createmem(ODR_PRINT);
            Z_AttributeList *alp = &(*pp)->attr_list;
            odr_setprint(pr, yaz_log_file());
            z_AttributeList(pr, &alp, 0, 0);
            odr_setprint(pr, 0);
            odr_destroy(pr);
        }
    }
    return ret;
}
Example #5
0
static void emit_term(cql_transform_t ct,
                      struct cql_node *cn,
                      const char *term, int length,
                      void (*pr)(const char *buf, void *client_data),
                      void *client_data)
{
    int i;
    const char *ns = cn->u.st.index_uri;
    int z3958_mode = 0;
    int process_term = 1;

    if (has_modifier(cn, "regexp"))
        process_term = 0;
    else if (cql_lookup_property(ct, "truncation", 0, "cql"))
    {
        process_term = 0;
        cql_pr_attr(ct, "truncation", "cql", 0,
                    pr, client_data, YAZ_SRW_MASKING_CHAR_UNSUPP);
    }
    assert(cn->which == CQL_NODE_ST);

    if (process_term)
    {
        unsigned anchor = 0;
        unsigned trunc = 0;
        for (i = 0; i < length; i++)
        {
            if (term[i] == '\\' && i < length - 1)
                i++;
            else
            {
                switch (term[i])
                {
                case '^':
                    if (i == 0)
                        anchor |= 1;
                    else if (i == length - 1)
                        anchor |= 2;
                    break;
                case '*':
                    if (i == 0)
                        trunc |= 1;
                    else if (i == length - 1)
                        trunc |= 2;
                    else
                        z3958_mode = 1;
                    break;
                case '?':
                    z3958_mode = 1;
                    break;
                }
            }
        }
        if (anchor == 3)
        {
            cql_pr_attr(ct, "position", "firstAndLast", 0,
                        pr, client_data, YAZ_SRW_ANCHORING_CHAR_IN_UNSUPP_POSITION);
            term++;
            length -= 2;
        }
        else if (anchor == 1)
        {
            cql_pr_attr(ct, "position", "first", 0,
                        pr, client_data, YAZ_SRW_ANCHORING_CHAR_IN_UNSUPP_POSITION);
            term++;
            length--;
        }
        else if (anchor == 2)
        {
            cql_pr_attr(ct, "position", "last", 0,
                        pr, client_data, YAZ_SRW_ANCHORING_CHAR_IN_UNSUPP_POSITION);
            length--;
        }
        else
        {
            cql_pr_attr(ct, "position", "any", 0,
                        pr, client_data, YAZ_SRW_ANCHORING_CHAR_IN_UNSUPP_POSITION);
        }
        if (z3958_mode == 0)
        {
            if (trunc == 3 && cql_pr_attr(ct, "truncation",
                                          "both", 0, pr, client_data, 0))
            {
                term++;
                length -= 2;
            }
            else if (trunc == 1 && cql_pr_attr(ct, "truncation",
                                               "left", 0, pr, client_data, 0))
            {
                term++;
                length--;
            }
            else if (trunc == 2 && cql_pr_attr(ct, "truncation", "right", 0,
                                               pr, client_data, 0))
            {
                length--;
            }
            else if (trunc)
                z3958_mode = 1;
            else
                cql_pr_attr(ct, "truncation", "none", 0,
                            pr, client_data, 0);
        }
        if (z3958_mode)
            cql_pr_attr(ct, "truncation", "z3958", 0,
                        pr, client_data, YAZ_SRW_MASKING_CHAR_UNSUPP);
    }
    if (ns) {
        cql_pr_attr_uri(ct, "index", ns,
                        cn->u.st.index, "serverChoice",
                        pr, client_data, YAZ_SRW_UNSUPP_INDEX);
    }
    if (cn->u.st.modifiers)
    {
        struct cql_node *mod = cn->u.st.modifiers;
        for (; mod; mod = mod->u.st.modifiers)
        {
            cql_pr_attr(ct, "relationModifier", mod->u.st.index, 0,
                        pr, client_data, YAZ_SRW_UNSUPP_RELATION_MODIFIER);
        }
    }
    (*pr)("\"", client_data);
    if (process_term)
        for (i = 0; i < length; i++)
        {
            char x[2]; /* temp buffer */
            if (term[i] == '\\' && i < length - 1)
            {
                i++;
                if (strchr("\"\\", term[i]))
                    pr("\\", client_data);
                if (z3958_mode && strchr("#?", term[i]))
                    pr("\\\\", client_data); /* double \\ to survive PQF parse */
                x[0] = term[i];
                x[1] = '\0';
                pr(x, client_data);
            }
            else if (z3958_mode && term[i] == '*')
            {
                pr("?", client_data);
                if (i < length - 1 && yaz_isdigit(term[i+1]))
                    pr("\\\\", client_data); /* dbl \\ to survive PQF parse */
            }
            else if (z3958_mode && term[i] == '?')
            {
                pr("#", client_data);
            }
            else
            {
                if (term[i] == '\"')
                    pr("\\", client_data);
                if (z3958_mode && strchr("#?", term[i]))
                    pr("\\\\", client_data); /* dbl \\ to survive PQF parse */
                x[0] = term[i];
                x[1] = '\0';
                pr(x, client_data);
            }
        }
    else
    {
        for (i = 0; i < length; i++)
        {
            char x[2];
            x[0] = term[i];
            x[1] = '\0';
            pr(x, client_data);
        }
    }
    (*pr)("\" ", client_data);
}
Example #6
0
File: http.c Project: nla/yaz
static int decode_headers_content(ODR o, int off, Z_HTTP_Header **headers,
                                  char **content_buf, int *content_len)
{
    int i = off;
    int chunked = 0;

    *headers = 0;
    while (i < o->size-1 && o->buf[i] == '\n')
    {
        int po;
        i++;
        if (o->buf[i] == '\r' && i < o->size-1 && o->buf[i+1] == '\n')
        {
            i++;
            break;
        }
        if (o->buf[i] == '\n')
            break;
        for (po = i; ; i++)
        {
            if (i == o->size)
            {
                o->error = OHTTP;
                return 0;
            }
            else if (o->buf[i] == ':')
                break;
        }
        *headers = (Z_HTTP_Header *) odr_malloc(o, sizeof(**headers));
        (*headers)->name = (char*) odr_malloc(o, i - po + 1);
        memcpy ((*headers)->name, o->buf + po, i - po);
        (*headers)->name[i - po] = '\0';
        i++;
        while (i < o->size-1 && o->buf[i] == ' ')
            i++;
        for (po = i; i < o->size-1 && !strchr("\r\n", o->buf[i]); i++)
            ;

        (*headers)->value = (char*) odr_malloc(o, i - po + 1);
        memcpy ((*headers)->value, o->buf + po, i - po);
        (*headers)->value[i - po] = '\0';

        if (!strcasecmp((*headers)->name, "Transfer-Encoding")
            &&
            !strcasecmp((*headers)->value, "chunked"))
            chunked = 1;
        headers = &(*headers)->next;
        if (i < o->size-1 && o->buf[i] == '\r')
            i++;
    }
    *headers = 0;
    if (o->buf[i] != '\n')
    {
        o->error = OHTTP;
        return 0;
    }
    i++;

    if (chunked)
    {
        int off = 0;

        /* we know buffer will be smaller than o->size - i*/
        *content_buf = (char*) odr_malloc(o, o->size - i);

        while (1)
        {
            /* chunk length .. */
            int chunk_len = 0;
            for (; i  < o->size-2; i++)
                if (yaz_isdigit(o->buf[i]))
                    chunk_len = chunk_len * 16 +
                        (o->buf[i] - '0');
                else if (yaz_isupper(o->buf[i]))
                    chunk_len = chunk_len * 16 +
                        (o->buf[i] - ('A'-10));
                else if (yaz_islower(o->buf[i]))
                    chunk_len = chunk_len * 16 +
                        (o->buf[i] - ('a'-10));
                else
                    break;
            /* chunk extension ... */
            while (o->buf[i] != '\r' && o->buf[i+1] != '\n')
            {
                if (i >= o->size-2)
                {
                    o->error = OHTTP;
                    return 0;
                }
                i++;
            }
            i += 2;  /* skip CRLF */
            if (chunk_len == 0)
                break;
            if (chunk_len < 0 || off + chunk_len > o->size)
            {
                o->error = OHTTP;
                return 0;
            }
            /* copy chunk .. */
            memcpy (*content_buf + off, o->buf + i, chunk_len);
            i += chunk_len + 2; /* skip chunk+CRLF */
            off += chunk_len;
        }
        if (!off)
            *content_buf = 0;
        *content_len = off;
    }
    else
    {
        if (i > o->size)
        {
            o->error = OHTTP;
            return 0;
        }
        else if (i == o->size)
        {
            *content_buf = 0;
            *content_len = 0;
        }
        else
        {
            *content_len = o->size - i;
            *content_buf = (char*) odr_malloc(o, *content_len + 1);
            memcpy(*content_buf, o->buf + i, *content_len);
            (*content_buf)[*content_len] = '\0';
        }
    }
    return 1;
}
Example #7
0
int yaz_marc_read_iso2709(yaz_marc_t mt, const char *buf, int bsize)
{
    int entry_p;
    int record_length;
    int indicator_length;
    int identifier_length;
    int end_of_directory;
    int base_address;
    int length_data_entry;
    int length_starting;
    int length_implementation;

    yaz_marc_reset(mt);

    if (!atoi_n_check(buf, 5, &record_length))
    {
        yaz_marc_cprintf(mt, "Bad leader");
        return -1;
    }
    if (record_length < 25)
    {
        yaz_marc_cprintf(mt, "Record length %d < 24", record_length);
        return -1;
    }
    /* ballout if bsize is known and record_length is less than that */
    if (bsize != -1 && record_length > bsize)
    {
        yaz_marc_cprintf(mt, "Record appears to be larger than buffer %d < %d",
                         record_length, bsize);
        return -1;
    }
    if (yaz_marc_get_debug(mt))
        yaz_marc_cprintf(mt, "Record length         %5d", record_length);

    yaz_marc_set_leader(mt, buf,
                        &indicator_length,
                        &identifier_length,
                        &base_address,
                        &length_data_entry,
                        &length_starting,
                        &length_implementation);

    /* First pass. determine length of directory & base of data */
    for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
    {
        /* length of directory entry */
        int l = 3 + length_data_entry + length_starting;
        if (entry_p + l >= record_length)
        {
            yaz_marc_cprintf(mt, "Directory offset %d: end of record."
                             " Missing FS char", entry_p);
            return -1;
        }
        if (yaz_marc_get_debug(mt))
        {
            WRBUF hex = wrbuf_alloc();

            wrbuf_puts(hex, "Tag ");
            wrbuf_write_escaped(hex, buf + entry_p, 3);
            wrbuf_puts(hex, ", length ");
            wrbuf_write_escaped(hex, buf + entry_p + 3,
                                length_data_entry);
            wrbuf_puts(hex, ", starting ");
            wrbuf_write_escaped(hex, buf + entry_p + 3 + length_data_entry,
                                length_starting);
            yaz_marc_cprintf(mt, "Directory offset %d: %s",
                             entry_p, wrbuf_cstr(hex));
            wrbuf_destroy(hex);
        }
        /* Check for digits in length+starting info */
        while (--l >= 3)
            if (!yaz_isdigit(buf[entry_p + l]))
                break;
        if (l >= 3)
        {
            WRBUF hex = wrbuf_alloc();
            /* Not all digits, so stop directory scan */
            wrbuf_write_escaped(hex, buf + entry_p,
                                length_data_entry + length_starting + 3);
            yaz_marc_cprintf(mt, "Directory offset %d: Bad value for data"
                             " length and/or length starting (%s)", entry_p,
                             wrbuf_cstr(hex));
            wrbuf_destroy(hex);
            break;
        }
        entry_p += 3 + length_data_entry + length_starting;
    }
    end_of_directory = entry_p;
    if (base_address != entry_p+1)
    {
        yaz_marc_cprintf(mt, "Base address not at end of directory,"
                         " base %d, end %d", base_address, entry_p+1);
    }

    /* Second pass. parse control - and datafields */
    for (entry_p = 24; entry_p != end_of_directory; )
    {
        int data_length;
        int data_offset;
        int end_offset;
        int i;
        char tag[4];
        int identifier_flag = 0;
        int entry_p0 = entry_p;

        memcpy (tag, buf+entry_p, 3);
        entry_p += 3;
        tag[3] = '\0';
        data_length = atoi_n(buf+entry_p, length_data_entry);
        entry_p += length_data_entry;
        data_offset = atoi_n(buf+entry_p, length_starting);
        entry_p += length_starting;
        i = data_offset + base_address;
        end_offset = i+data_length-1;

        if (data_length <= 0 || data_offset < 0)
            break;

        if (yaz_marc_get_debug(mt))
        {
            yaz_marc_cprintf(mt, "Tag: %s. Directory offset %d: data-length %d,"
                             " data-offset %d",
                             tag, entry_p0, data_length, data_offset);
        }
        if (end_offset >= record_length)
        {
            yaz_marc_cprintf(mt, "Directory offset %d: Data out of bounds %d >= %d",
                             entry_p0, end_offset, record_length);
            break;
        }

        if (memcmp (tag, "00", 2))
            identifier_flag = 1;  /* if not 00X assume subfields */
        else if (indicator_length < 4 && indicator_length > 0)
        {
            /* Danmarc 00X have subfields */
            if (buf[i + indicator_length] == ISO2709_IDFS)
                identifier_flag = 1;
            else if (buf[i + indicator_length + 1] == ISO2709_IDFS)
                identifier_flag = 2;
        }

        if (identifier_flag)
        {
            /* datafield */
            i += identifier_flag-1;
            if (indicator_length)
            {
                /* skip RS/FS bytes in indicator. They are not allowed there */
                int j;
                for (j = indicator_length; --j >= 0; )
                    if (buf[j+i] < ' ')
                    {
                        j++;
                        i += j;
                        end_offset += j;
                        yaz_marc_cprintf(mt, "Bad indicator data. "
                                         "Skipping %d bytes", j);
                        break;
                    }
                yaz_marc_add_datafield(mt, tag, buf+i, indicator_length);
                i += indicator_length;
            }

            while (i < end_offset &&
                    buf[i] != ISO2709_RS && buf[i] != ISO2709_FS)
            {
                int code_offset = i+1;

                i ++;
                while (i < end_offset &&
                        buf[i] != ISO2709_RS && buf[i] != ISO2709_IDFS &&
                       buf[i] != ISO2709_FS)
                    i++;
                if (i > code_offset)
                    yaz_marc_add_subfield(mt, buf+code_offset, i - code_offset);
            }
        }
        else
        {
            /* controlfield */
            int i0 = i;
            while (i < end_offset &&
                buf[i] != ISO2709_RS && buf[i] != ISO2709_FS)
                i++;
            yaz_marc_add_controlfield(mt, tag, buf+i0, i-i0);
        }
        if (i < end_offset)
        {
            yaz_marc_cprintf(mt, "Separator but not at end of field length=%d",
                    data_length);
        }
        if (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS)
        {
            yaz_marc_cprintf(mt, "No separator at end of field length=%d",
                             data_length);
        }
    }
    return record_length;
}