Пример #1
0
/* determines the size of the given AMF data */
size_t amf_data_size(const amf_data * data) {
    size_t s = 0;
    amf_node * node;
    if (data != NULL) {
        s += sizeof(byte);
        switch (data->type) {
        case AMF_TYPE_NUMBER:
            s += sizeof(number64_be);
            break;
        case AMF_TYPE_BOOLEAN:
            s += sizeof(uint8);
            break;
        case AMF_TYPE_STRING:
            s += sizeof(uint16) + (size_t)amf_string_get_size(data);
            break;
        case AMF_TYPE_OBJECT:
            node = amf_object_first(data);
            while (node != NULL) {
                s += sizeof(uint16) + (size_t)amf_string_get_size(amf_object_get_name(node));
                s += (size_t)amf_data_size(amf_object_get_data(node));
                node = amf_object_next(node);
            }
            s += sizeof(uint16) + sizeof(uint8);
            break;
        case AMF_TYPE_NULL:
        case AMF_TYPE_UNDEFINED:
            break;
        /*case AMF_TYPE_REFERENCE:*/
        case AMF_TYPE_ASSOCIATIVE_ARRAY:
            s += sizeof(uint32);
            node = amf_associative_array_first(data);
            while (node != NULL) {
                s += sizeof(uint16) + (size_t)amf_string_get_size(amf_associative_array_get_name(node));
                s += (size_t)amf_data_size(amf_associative_array_get_data(node));
                node = amf_associative_array_next(node);
            }
            s += sizeof(uint16) + sizeof(uint8);
            break;
        case AMF_TYPE_ARRAY:
            s += sizeof(uint32);
            node = amf_array_first(data);
            while (node != NULL) {
                s += (size_t)amf_data_size(amf_array_get(node));
                node = amf_array_next(node);
            }
            break;
        case AMF_TYPE_DATE:
            s += sizeof(number64) + sizeof(sint16);
            break;
        /*case AMF_TYPE_SIMPLEOBJECT:*/
        case AMF_TYPE_XML:
        case AMF_TYPE_CLASS:
        case AMF_TYPE_END:
            break; /* end of composite object */
        default:
            break;
        }
    }
    return s;
}
Пример #2
0
/* write an object */
static size_t amf_object_write(const amf_data * data, amf_write_proc write_proc, void * user_data) {
    amf_node * node;
    size_t w = 0;
    uint16_be filler = swap_uint16(0);
    uint8 terminator = AMF_TYPE_END;

    node = amf_object_first(data);
    while (node != NULL) {
        w += amf_string_write(amf_object_get_name(node), write_proc, user_data);
        w += amf_data_write(amf_object_get_data(node), write_proc, user_data);
        node = amf_object_next(node);
    }

    /* empty string is the last element */
    w += write_proc(&filler, sizeof(uint16_be), user_data);
    /* an object ends with 0x09 */
    w += write_proc(&terminator, sizeof(uint8), user_data);

    return w;
}
Пример #3
0
/* JSON metadata dumping */
static void json_amf_data_dump(const amf_data * data, json_emitter * je) {
    if (data != NULL) {
        amf_node * node;
        char str[128];

        switch (data->type) {
            case AMF_TYPE_NUMBER:
                json_emit_number(je, data->number_data);
                break;
            case AMF_TYPE_BOOLEAN:
                json_emit_boolean(je, data->boolean_data);
                break;
            case AMF_TYPE_STRING:
                json_emit_string(je, (char *)amf_string_get_bytes(data), amf_string_get_size(data));
                break;
            case AMF_TYPE_OBJECT:
                json_emit_object_start(je);
                node = amf_object_first(data);
                while (node != NULL) {
                    json_emit_object_key(je,
                        (char *)amf_string_get_bytes(amf_object_get_name(node)),
                        amf_string_get_size(amf_object_get_name(node))
                    );
                    json_amf_data_dump(amf_object_get_data(node), je);
                    node = amf_object_next(node);
                }
                json_emit_object_end(je);
                break;
            case AMF_TYPE_NULL:
            case AMF_TYPE_UNDEFINED:
                json_emit_null(je);
                break;
            case AMF_TYPE_ASSOCIATIVE_ARRAY:
                json_emit_object_start(je);
                node = amf_associative_array_first(data);
                while (node != NULL) {
                    json_emit_object_key(je,
                        (char *)amf_string_get_bytes(amf_associative_array_get_name(node)),
                        amf_string_get_size(amf_associative_array_get_name(node))
                    );
                    json_amf_data_dump(amf_object_get_data(node), je);
                    node = amf_associative_array_next(node);
                }
                json_emit_object_end(je);
                break;
            case AMF_TYPE_ARRAY:
                json_emit_array_start(je);
                node = amf_array_first(data);
                while (node != NULL) {
                    json_amf_data_dump(amf_array_get(node), je);
                    node = amf_array_next(node);
                }
                json_emit_array_end(je);
                break;
            case AMF_TYPE_DATE:
                amf_date_to_iso8601(data, str, sizeof(str));
                json_emit_string(je, str, strlen(str));
                break;
            case AMF_TYPE_XML: break;
            case AMF_TYPE_CLASS: break;
            default: break;
        }
    }
}
Пример #4
0
/* dump AMF data into a stream as text */
void amf_data_dump(FILE * stream, const amf_data * data, int indent_level) {
    if (data != NULL) {
        amf_node * node;
        time_t time;
        struct tm * t;
        char datestr[128];
        switch (data->type) {
        case AMF_TYPE_NUMBER:
            fprintf(stream, "%.12g", data->number_data);
            break;
        case AMF_TYPE_BOOLEAN:
            fprintf(stream, "%s", (data->boolean_data) ? "true" : "false");
            break;
        case AMF_TYPE_STRING:
            fprintf(stream, "\'%.*s\'", data->string_data.size, data->string_data.mbstr);
            break;
        case AMF_TYPE_OBJECT:
            node = amf_object_first(data);
            fprintf(stream, "{\n");
            while (node != NULL) {
                fprintf(stream, "%*s", (indent_level+1)*4, "");
                amf_data_dump(stream, amf_object_get_name(node), indent_level+1);
                fprintf(stream, ": ");
                amf_data_dump(stream, amf_object_get_data(node), indent_level+1);
                node = amf_object_next(node);
                fprintf(stream, "\n");
            }
            fprintf(stream, "%*s", indent_level*4 + 1, "}");
            break;
        case AMF_TYPE_NULL:
            fprintf(stream, "null");
            break;
        case AMF_TYPE_UNDEFINED:
            fprintf(stream, "undefined");
            break;
        /*case AMF_TYPE_REFERENCE:*/
        case AMF_TYPE_ASSOCIATIVE_ARRAY:
            node = amf_associative_array_first(data);
            fprintf(stream, "{\n");
            while (node != NULL) {
                fprintf(stream, "%*s", (indent_level+1)*4, "");
                amf_data_dump(stream, amf_associative_array_get_name(node), indent_level+1);
                fprintf(stream, " => ");
                amf_data_dump(stream, amf_associative_array_get_data(node), indent_level+1);
                node = amf_associative_array_next(node);
                fprintf(stream, "\n");
            }
            fprintf(stream, "%*s", indent_level*4 + 1, "}");
            break;
        case AMF_TYPE_ARRAY:
            node = amf_array_first(data);
            fprintf(stream, "[\n");
            while (node != NULL) {
                fprintf(stream, "%*s", (indent_level+1)*4, "");
                amf_data_dump(stream, node->data, indent_level+1);
                node = amf_array_next(node);
                fprintf(stream, "\n");
            }
            fprintf(stream, "%*s", indent_level*4 + 1, "]");
            break;
        case AMF_TYPE_DATE:
            time = amf_date_to_time_t(data);
            tzset();
            t = localtime(&time);
            strftime(datestr, sizeof(datestr), "%a, %d %b %Y %H:%M:%S %z", t);
            fprintf(stream, "%s", datestr);
            break;
        /*case AMF_TYPE_SIMPLEOBJECT:*/
        case AMF_TYPE_XML:
            break;
        case AMF_TYPE_CLASS:
            break;
        default:
            break;
        }
    }
}
Пример #5
0
/* XML metadata dumping */
static void xml_amf_data_dump(const amf_data * data, int qualified, int indent_level) {
    if (data != NULL) {
        amf_node * node;
        time_t time;
        struct tm * t;
        char datestr[128];
        int markers;
        char * ns;
        char ns_decl[50];

        /* namespace to use whether we're using qualified mode */
        ns = (qualified == 1) ? "amf:" : "";

        /* if indent_level is zero, that means we're at the root of the xml document
           therefore we need to insert the namespace definition */
        if (indent_level == 0) {
            sprintf(ns_decl, " xmlns%s=\"http://schemas.flvmeta.org/AMF0/1.0/\"", ns);
        }
        else {
            strcpy(ns_decl, "");
        }

        /* print indentation spaces */
        printf("%*s", indent_level * 2, "");

        switch (data->type) {
            case AMF_TYPE_NUMBER:
                printf("<%snumber%s value=\"%.12g\"/>\n", ns, ns_decl, data->number_data);
                break;
            case AMF_TYPE_BOOLEAN:
                printf("<%sboolean%s value=\"%s\"/>\n", ns, ns_decl, (data->boolean_data) ? "true" : "false");
                break;
            case AMF_TYPE_STRING:
                if (amf_string_get_size(data) > 0) {
                    printf("<%sstring%s>", ns, ns_decl);
                    /* check whether the string contains xml characters, if so, CDATA it */
                    markers = has_xml_markers((char*)amf_string_get_bytes(data), amf_string_get_size(data));
                    if (markers) {
                        printf("<![CDATA[");
                    }
                    /* do not print more than the actual length of string */
                    printf("%.*s", (int)amf_string_get_size(data), amf_string_get_bytes(data));
                    if (markers) {
                        printf("]]>");
                    }
                    printf("</%sstring>\n", ns);
                }
                else {
                    /* simplify empty xml element into a more compact form */
                    printf("<%sstring%s/>\n", ns, ns_decl);
                }
                break;
            case AMF_TYPE_OBJECT:
                if (amf_object_size(data) > 0) {
                    printf("<%sobject%s>\n", ns, ns_decl);
                    node = amf_object_first(data);
                    while (node != NULL) {
                        printf("%*s<%sentry name=\"%s\">\n", (indent_level + 1) * 2, "", ns, amf_string_get_bytes(amf_object_get_name(node)));
                        xml_amf_data_dump(amf_object_get_data(node), qualified, indent_level + 2);
                        node = amf_object_next(node);
                        printf("%*s</%sentry>\n", (indent_level + 1) * 2, "", ns);
                    }
                    printf("%*s</%sobject>\n", indent_level * 2, "", ns);
                }
                else {
                    /* simplify empty xml element into a more compact form */
                    printf("<%sobject%s/>\n", ns, ns_decl);
                }
                break;
            case AMF_TYPE_NULL:
                printf("<%snull%s/>\n", ns, ns_decl);
                break;
            case AMF_TYPE_UNDEFINED:
                printf("<%sundefined%s/>\n", ns, ns_decl);
                break;
            case AMF_TYPE_ASSOCIATIVE_ARRAY:
                if (amf_associative_array_size(data) > 0) {
                    printf("<%sassociativeArray%s>\n", ns, ns_decl);
                    node = amf_associative_array_first(data);
                    while (node != NULL) {
                        printf("%*s<%sentry name=\"%s\">\n", (indent_level + 1) * 2, "", ns, amf_string_get_bytes(amf_associative_array_get_name(node)));
                        xml_amf_data_dump(amf_associative_array_get_data(node), qualified, indent_level + 2);
                        node = amf_associative_array_next(node);
                        printf("%*s</%sentry>\n", (indent_level + 1) * 2, "", ns);
                    }
                    printf("%*s</%sassociativeArray>\n", indent_level * 2, "", ns);
                }
                else {
                    /* simplify empty xml element into a more compact form */
                    printf("<%sassociativeArray%s/>\n", ns, ns_decl);
                }
                break;
            case AMF_TYPE_ARRAY:
                if (amf_array_size(data) > 0) {
                    printf("<%sarray%s>\n", ns, ns_decl);
                    node = amf_array_first(data);
                    while (node != NULL) {
                        xml_amf_data_dump(amf_array_get(node), qualified, indent_level + 1);
                        node = amf_array_next(node);
                    }
                    printf("%*s</%sarray>\n", indent_level * 2, "", ns);
                }
                else {
                    /* simplify empty xml element into a more compact form */
                    printf("<%sarray%s/>\n", ns, ns_decl);
                }
                break;
            case AMF_TYPE_DATE:
                time = amf_date_to_time_t(data);
                tzset();
                t = localtime(&time);
                strftime(datestr, sizeof(datestr), "%Y-%m-%dT%H:%M:%S", t);
                printf("<%sdate%s value=\"%s\"/>\n", ns, ns_decl, datestr);
                break;
            case AMF_TYPE_XML: break;
            case AMF_TYPE_CLASS: break;
            default: break;
        }
    }
}
Пример #6
0
/* JSON metadata dumping */
static void amf_to_json(const amf_data * data, json_t ** object) {
    if (data != NULL) {
        json_t * value;
        amf_node * node;
        time_t time;
        struct tm * t;
        char str[128];
        char * escaped_str;

        switch (data->type) {
            case AMF_TYPE_NUMBER:
                sprintf(str, "%.12g", data->number_data);
                *object = json_new_number(str);
                break;
            case AMF_TYPE_BOOLEAN:
                *object = (data->boolean_data) ? json_new_true() : json_new_false();
                break;
            case AMF_TYPE_STRING:
                escaped_str = json_escape((char *)amf_string_get_bytes(data));
                *object = json_new_string(escaped_str);
                free(escaped_str);
                break;
            case AMF_TYPE_OBJECT:
                *object = json_new_object();
                node = amf_object_first(data);
                while (node != NULL) {
                    amf_to_json(amf_object_get_data(node), &value);
                    escaped_str = json_escape((char *)amf_string_get_bytes(amf_object_get_name(node)));
                    json_insert_pair_into_object(*object, escaped_str, value);
                    free(escaped_str);
                    node = amf_object_next(node);
                }
                break;
            case AMF_TYPE_NULL:
            case AMF_TYPE_UNDEFINED:
                *object = json_new_null();
                break;
            case AMF_TYPE_ASSOCIATIVE_ARRAY:
                *object = json_new_object();
                node = amf_associative_array_first(data);
                while (node != NULL) {
                    amf_to_json(amf_associative_array_get_data(node), &value);
                    json_insert_pair_into_object(*object, (const char *)amf_string_get_bytes(amf_associative_array_get_name(node)), value);
                    node = amf_associative_array_next(node);
                }
                break;
            case AMF_TYPE_ARRAY:
                *object = json_new_array();
                node = amf_array_first(data);
                while (node != NULL) {
                    amf_to_json(amf_array_get(node), &value);
                    json_insert_child(*object, value);
                    node = amf_array_next(node);
                }
                break;
            case AMF_TYPE_DATE:
                time = amf_date_to_time_t(data);
                tzset();
                t = localtime(&time);
                strftime(str, sizeof(str), "%Y-%m-%dT%H:%M:%S", t);
                *object = json_new_string(str);
                break;
            case AMF_TYPE_XML: break;
            case AMF_TYPE_CLASS: break;
            default: break;
        }
    }
}