Пример #1
0
inline bool checkArray(QuickArray<qstring>& a, const char* chks[], int32_t sz)
{
	int32_t i;

	if ((int32_t)a.size() < sz)
		return false;

	for (i = 0; i < sz; i ++)
		if (!qstrcmp(a[i].c_str(), chks[i]))
			return false;

	return true;
}
Пример #2
0
inline result_t GetArray(v8::Local<v8::Value> v, QuickArray<T> &n)
{
	if (v.IsEmpty() || !v->IsArray())
		return CALL_E_INVALIDARG;

	v8::Local<v8::Array> a = v8::Local<v8::Array>::Cast(v);
	result_t hr;

	for (int32_t i = 0; i < (int32_t)a->Length(); i ++)
	{
		T vr;
		hr = GetArgumentValue(a->Get(i), vr, true);
		if (hr < 0)
			return hr;

		n.append(vr);
	}

	return 0;
}
Пример #3
0
result_t HeapSnapshot::save(const char* fname, AsyncEvent* ac)
{
	if (!ac)
		return CHECK_ERROR(CALL_E_NOSYNC);

	class buf_file
	{
	public:
		buf_file() : file(new File())
		{
		}

		~buf_file()
		{
			flush();
		}

	public:
		result_t open(const char* fname)
		{
			return file->open(fname, "w");
		}

		result_t append(qstring& s)
		{
			bufs.append(s);
			if (bufs.size() > BUF_SIZE)
				return flush();
			return 0;
		}

		result_t append(const char* s, int32_t l = -1)
		{
			bufs.append(s, l);
			if (bufs.size() > BUF_SIZE)
				return flush();
			return 0;
		}

		result_t append(char ch)
		{
			bufs.append(ch);
			if (bufs.size() > BUF_SIZE)
				return flush();
			return 0;
		}

		result_t flush()
		{
			qstring str = bufs.str();
			return file->Write(str.c_str(), (int32_t)str.length());
		}

	public:
		StringBuffer bufs;
		obj_ptr<File> file;
	};

	class name_ids
	{
	public:
		name_ids()
		{
			id("<dummy>");
		}

	public:
		int32_t id(qstring _name)
		{
			std::map<qstring, int32_t>::iterator it;
			int32_t _name_id;

			it = mapNames.find(_name);
			if (it == mapNames.end())
			{
				_name_id = (int32_t)names.size();
				mapNames.insert(std::pair<qstring, int32_t>(_name, _name_id));
				names.append(_name);
			} else
				_name_id = it->second;

			return _name_id;
		}

	public:
		std::map<qstring, int32_t> mapNames;
		QuickArray<qstring> names;
	};

	static char meta[] = "{\"snapshot\":{\"meta\":{\"node_fields\":"
	                     "[\"type\",\"name\",\"id\",\"self_size\","
	                     "\"edge_count\",\"trace_node_id\"],"
	                     "\"node_types\":[[\"hidden\",\"array\","
	                     "\"string\",\"object\",\"code\",\"closure\","
	                     "\"regexp\",\"number\",\"native\",\"synthetic\","
	                     "\"concatenated string\",\"sliced string\"],"
	                     "\"string\",\"number\",\"number\",\"number\","
	                     "\"number\",\"number\"],\"edge_fields\":"
	                     "[\"type\",\"name_or_index\",\"to_node\"],"
	                     "\"edge_types\":[[\"context\",\"element\","
	                     "\"property\",\"internal\",\"hidden\","
	                     "\"shortcut\",\"weak\"],\"string_or_number\","
	                     "\"node\"],\"trace_function_info_fields\":"
	                     "[\"function_id\",\"name\",\"script_name\","
	                     "\"script_id\",\"line\",\"column\"],"
	                     "\"trace_node_fields\":[\"id\",\"function_info_index\","
	                     "\"count\",\"size\",\"children\"],\"sample_fields\":"
	                     "[\"timestamp_us\",\"last_assigned_id\"]},";

	name_ids _ids;
	QuickArray<HeapGraphNode_base*> nodes;
	obj_ptr<List_base> childs;
	buf_file bufs;
	int32_t count, child_count = 0;
	int32_t n;
	int32_t i;
	result_t hr;

	hr = bufs.open(fname);
	if (hr < 0)
		return hr;

	hr = bufs.file->Write(meta, sizeof(meta) - 1);
	if (hr < 0)
		return hr;

	m_nodes->get_length(count);
	for (i = 0; i < count; i ++)
	{
		Variant v;
		HeapGraphNode* cur;

		m_nodes->_indexed_getter(i, v);
		cur = (HeapGraphNode*)v.object();

		nodes.append(cur);

		cur->get_childs(childs);

		childs->get_length(n);
		child_count += n;
	}

	qstring str;
	char buf[128];

	n = sprintf(buf, "\"node_count\":%d,\"edge_count\":%d,"
	            "\"trace_function_count\":0},\n\"nodes\":[", count, child_count);
	hr = bufs.append(buf, n);
	if (hr < 0)
		return hr;

	for (i = 0; i < count; i ++)
	{
		int32_t _id, _type, _name_id, _size, _child;
		qstring _name;
		HeapGraphNode_base* cur = nodes[i];

		cur->get_id(_id);
		cur->get_type(_type);
		cur->get_shallowSize(_size);
		cur->get_name(_name);
		_name_id = _ids.id(_name);

		cur->get_childs(childs);
		childs->get_length(_child);

		if (i == 0)
			n = sprintf(buf, "%d,%d,%d,%d,%d,0\n", _type, _name_id, _id, _size, _child);
		else
			n = sprintf(buf, ",%d,%d,%d,%d,%d,0\n", _type, _name_id, _id, _size, _child);
		hr = bufs.append(buf, n);
		if (hr < 0)
			return hr;
	}

	hr = bufs.append("],\n\"edges\":[");
	if (hr < 0)
		return hr;

	for (i = 0; i < count; i ++)
	{
		int32_t _type, _name_id, _child, _toid, _toindex;
		qstring _name;
		HeapGraphNode_base* cur = nodes[i];

		cur->get_childs(childs);
		childs->get_length(_child);

		for (int32_t j = 0; j < _child; j ++)
		{
			Variant v;
			HeapGraphEdge* edge;

			childs->_indexed_getter(j, v);
			edge = (HeapGraphEdge*)v.object();

			edge->get_type(_type);
			edge->get_name(_name);

			if (is_num_type(_type))
				_name_id = atoi(_name.c_str());
			else
				_name_id = _ids.id(_name);

			_toid = edge->toid();
			_toindex = _nodes.find(_toid)->second * 6;

			if (i == 0 && j == 0)
				n = sprintf(buf, "%d,%d,%d\n", _type, _name_id, _toindex);
			else
				n = sprintf(buf, ",%d,%d,%d\n", _type, _name_id, _toindex);
			hr = bufs.append(buf, n);
			if (hr < 0)
				return hr;
		}
	}

	hr = bufs.append("],\n\"trace_function_infos\":[],\n\"trace_tree\":[],\n"
	                 "\"samples\":[],\n\"strings\":[");
	if (hr < 0)
		return hr;

	count = (int32_t)_ids.names.size();
	for (i = 0; i < count; i ++)
	{
		if (i == 0)
			hr = bufs.append('\"');
		else
			hr = bufs.append("\",\n\"", 4);
		if (hr < 0)
			return hr;

		str.resize(0);
		encoding_base::jsstr(_ids.names[i].c_str(), true, str);
		hr = bufs.append(str);
		if (hr < 0)
			return hr;
	}

	hr = bufs.append("\"]}", 3);
	if (hr < 0)
		return hr;
	return 0;
}
Пример #4
0
result_t HeapSnapshot::load(const char* fname)
{
	Isolate* isolate = holder();
	result_t hr;
	v8::Local<v8::Value> v;
	v8::Local<v8::Object> o;

	QuickArray<int32_t> nodes;
	QuickArray<int32_t> edges;
	QuickArray<qstring> names;
	QuickArray<qstring> node_fields;
	QuickArray<qstring> node_types;
	QuickArray<qstring> edge_fields;
	QuickArray<qstring> edge_types;
	int32_t node_count, edge_count;
	static const char* node_fields_chk[] = {"type", "name", "id", "self_size", "edge_count"};
	static const char* node_types_chk[] = {"hidden", "array", "string", "object",
	                                       "code", "closure", "regexp", "number",
	                                       "native", "synthetic", "concatenated string",
	                                       "sliced string"
	                                      };
	static const char* edge_fields_chk[] = {"type", "name_or_index", "to_node"};
	static const char* edge_types_chk[] = {"context", "element", "property",
	                                       "internal", "hidden", "shortcut", "weak"
	                                      };

	qstring data;
	hr = fs_base::ac_readFile(fname, data);
	if (hr < 0)
		return hr;

	hr = json_base::decode(data.c_str(), v);
	if (hr < 0)
		return hr;
	data.resize(0);

	if (!v->IsObject())
		return CHECK_ERROR(CALL_E_INVALID_DATA);

	o = v8::Local<v8::Object>::Cast(v);
	hr = GetArray(o->Get(isolate->NewFromUtf8("nodes")),
	              nodes);
	if (hr < 0)
		return CHECK_ERROR(CALL_E_INVALID_DATA);

	hr = GetArray(o->Get(isolate->NewFromUtf8("edges")),
	              edges);
	if (hr < 0)
		return CHECK_ERROR(CALL_E_INVALID_DATA);

	hr = GetArray(o->Get(isolate->NewFromUtf8("strings")),
	              names);
	if (hr < 0)
		return CHECK_ERROR(CALL_E_INVALID_DATA);

	v = o->Get(isolate->NewFromUtf8("snapshot"));
	if (v.IsEmpty() || !v->IsObject())
		return CHECK_ERROR(CALL_E_INVALID_DATA);

	o = v8::Local<v8::Object>::Cast(v);
	hr = GetConfigValue(isolate->m_isolate, o, "node_count", node_count);
	if (hr < 0)
		return CHECK_ERROR(CALL_E_INVALID_DATA);

	hr = GetConfigValue(isolate->m_isolate, o, "edge_count", edge_count);
	if (hr < 0)
		return CHECK_ERROR(CALL_E_INVALID_DATA);

	v = o->Get(isolate->NewFromUtf8("meta"));
	if (v.IsEmpty() || !v->IsObject())
		return CHECK_ERROR(CALL_E_INVALID_DATA);

	o = v8::Local<v8::Object>::Cast(v);
	hr = GetArray(o->Get(isolate->NewFromUtf8("node_fields")),
	              node_fields);
	if (hr < 0 || checkArray(node_fields, node_fields_chk, ARRAYSIZE(node_fields_chk)))
		return CHECK_ERROR(CALL_E_INVALID_DATA);

	hr = GetArray(o->Get(isolate->NewFromUtf8("edge_fields")),
	              edge_fields);
	if (hr < 0 || checkArray(edge_fields, edge_fields_chk, ARRAYSIZE(edge_fields_chk)))
		return CHECK_ERROR(CALL_E_INVALID_DATA);

	if (node_fields.size() * node_count != nodes.size())
		return CHECK_ERROR(CALL_E_INVALID_DATA);

	if (edge_fields.size() * edge_count != edges.size())
		return CHECK_ERROR(CALL_E_INVALID_DATA);

	v = o->Get(isolate->NewFromUtf8("node_types"));
	if (v.IsEmpty() || !v->IsArray())
		return CHECK_ERROR(CALL_E_INVALID_DATA);

	hr = GetArray(v8::Local<v8::Array>::Cast(v)->Get(0), node_types);
	if (hr < 0 || checkArray(node_types, node_types_chk, ARRAYSIZE(node_types_chk)))
		return CHECK_ERROR(CALL_E_INVALID_DATA);

	v = o->Get(isolate->NewFromUtf8("edge_types"));
	if (v.IsEmpty() || !v->IsArray())
		return CHECK_ERROR(CALL_E_INVALID_DATA);

	hr = GetArray(v8::Local<v8::Array>::Cast(v)->Get(0), edge_types);
	if (hr < 0 || checkArray(edge_types, edge_types_chk, ARRAYSIZE(edge_types_chk)))
		return CHECK_ERROR(CALL_E_INVALID_DATA);

	int32_t node_pos = 0, edge_pos = 0;

	m_nodes = new List();
	while (node_pos < node_count)
	{
		int32_t _base = node_pos * (int32_t)node_fields.size();
		int32_t _node_type = nodes[_base];
		int32_t _node_name_id = nodes[_base + 1];
		if (_node_name_id < 0 || _node_name_id >= (int32_t)names.size())
			return CHECK_ERROR(CALL_E_INVALID_DATA);
		qstring _node_name = names[_node_name_id];
		int32_t _node_id = nodes[_base + 2];
		int32_t _node_size = nodes[_base + 3];
		int32_t _node_edge = nodes[_base + 4];
		obj_ptr<List> _edges = new List();

		if (edge_pos + _node_edge > edge_count)
			return CHECK_ERROR(CALL_E_INVALID_DATA);

		while (_node_edge --)
		{
			int32_t _base = edge_pos * (int32_t)edge_fields.size();
			int32_t _edge_type = edges[_base];
			int32_t _edge_name_id = edges[_base + 1];
			int32_t _edge_toid = edges[_base + 2];
			qstring _edge_name;

			if (is_num_type(_edge_type))
			{
				char buf[64];

				sprintf(buf, "%d", _edge_name_id);
				_edge_name = buf;
			}
			else
				_edge_name = names[_edge_name_id];

			if (_edge_toid % node_fields.size() != 0 ||
			        _edge_toid >= (int32_t)edges.size())
				return CHECK_ERROR(CALL_E_INVALID_DATA);
			_edge_toid = nodes[_edge_toid + 2];

			obj_ptr<HeapGraphEdge> _edge = new HeapGraphEdge(this, _edge_type,
			        _edge_name, _node_id, _edge_toid);
			_edges->append(_edge);

			edge_pos ++;
		}

		_edges->freeze();

		obj_ptr<HeapGraphNode> _node = new HeapGraphNode(_node_type,
		        _node_name, _node_id, _node_size, _edges);

		_nodes.insert(std::pair<int32_t, int32_t>(_node_id, node_pos));
		m_nodes->append(_node);

		node_pos ++;
	}

	m_nodes->freeze();

	return 0;
}
Пример #5
0
std::string json_format(v8::Local<v8::Value> obj)
{
    StringBuffer strBuffer;

    Isolate* isolate = Isolate::current();
    QuickArray<_item> stk;
    QuickArray<v8::Local<v8::Object>> vals;
    v8::Local<v8::Value> v = obj;
    v8::Local<v8::String> mark_name = isolate->NewFromUtf8("_util_format_mark");
    int32_t padding = 0;
    const int32_t tab_size = 2;
    _item *it = NULL;

    while (true)
    {
        if (v.IsEmpty())
            strBuffer.append("undefined");
        else if (v->IsUndefined() || v->IsNull() || v->IsDate() ||
                 v->IsBoolean() || v->IsBooleanObject())
            strBuffer.append(*v8::String::Utf8Value(v));
        else if (v->IsNumber() || v->IsNumberObject())
            strBuffer.append(*v8::String::Utf8Value(v->ToNumber()));
        else if (v->IsString() || v->IsStringObject())
            string_format(strBuffer, v);
        else if (v->IsRegExp())
        {
            v8::Local<v8::RegExp> re = v8::Local<v8::RegExp>::Cast(v);
            v8::Local<v8::String> src = re->GetSource();
            v8::RegExp::Flags flgs = re->GetFlags();

            strBuffer.append('/');
            strBuffer.append(*v8::String::Utf8Value(src));
            strBuffer.append('/');

            if (flgs & v8::RegExp::kIgnoreCase)
                strBuffer.append('i');
            if (flgs & v8::RegExp::kGlobal)
                strBuffer.append('g');
            if (flgs & v8::RegExp::kMultiline)
                strBuffer.append('m');
        }
        else if (v->IsObject())
        {
            do
            {
                v8::Local<v8::Object> obj = v->ToObject();
                v8::Local<v8::Array> keys = obj->GetPropertyNames();

                if (v->IsFunction() && keys->Length() == 0)
                {
                    strBuffer.append("[Function]");
                    break;
                }

                obj_ptr<Buffer_base> buf = Buffer_base::getInstance(v);
                if (buf)
                {
                    static char hexs[] = "0123456789abcdef";
                    std::string data;
                    std::string s;
                    int32_t len, i;

                    buf->toString(data);
                    len = (int32_t)data.length();

                    s.resize(len * 3 + 8);
                    memcpy(&s[0], "<Buffer", 7);

                    for (i = 0; i < len; i ++)
                    {
                        int32_t ch = (unsigned char)data[i];

                        s[i * 3 + 7] = ' ';
                        s[i * 3 + 8] = hexs[ch >> 4];
                        s[i * 3 + 9] = hexs[ch & 0xf];
                    }

                    s[i * 3 + 7] = '>';

                    strBuffer.append(s);
                    break;
                }

                obj_ptr<Int64_base> int64Val = Int64_base::getInstance(v);
                if (int64Val)
                {
                    std::string s;
                    int64Val->toString(10, s);
                    strBuffer.append(s);
                    break;
                }

                v8::Local<v8::Value> mk = obj->GetHiddenValue(mark_name);
                if (!mk.IsEmpty())
                {
                    strBuffer.append("[Circular]");
                    break;
                }

                vals.append(obj);
                obj->SetHiddenValue(mark_name, obj);

                v8::Local<v8::Value> toArray = obj->Get(isolate->NewFromUtf8("toArray"));
                if (!IsEmpty(toArray) && toArray->IsFunction())
                {
                    v = v8::Local<v8::Function>::Cast(toArray)->Call(obj, 0, NULL);
                    obj = v->ToObject();
                }

                int32_t sz = (int32_t)stk.size();

                if (v->IsArray())
                {
                    v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(v);
                    int32_t len = array->Length();

                    if (len == 0)
                        strBuffer.append("[]");
                    else
                    {
                        if (len == 1 && v->StrictEquals(array->Get(0)))
                            strBuffer.append("[Circular]");
                        else
                        {
                            stk.resize(sz + 1);
                            it = &stk[sz];

                            it->val = v;

                            it->keys = array;
                            it->len = len;

                            strBuffer.append('[');
                            padding += tab_size;
                        }
                    }
                    break;
                }

                int32_t len = keys->Length();

                if (len == 0)
                    strBuffer.append("{}");
                else
                {
                    if (len == 1 && v->StrictEquals(obj->Get(keys->Get(0))))
                        strBuffer.append("[Circular]");
                    else
                    {
                        stk.resize(sz + 1);
                        it = &stk[sz];

                        it->val = v;

                        it->obj = obj;
                        it->keys = keys;
                        it->len = len;

                        strBuffer.append('{');
                        padding += tab_size;
                    }
                }
            }
            while (false);
        }

        if (it)
        {
            while (it && it->pos == it->len)
            {
                padding -= tab_size;
                newline(strBuffer, padding);
                strBuffer.append(it->obj.IsEmpty() ? ']' : '}');

                int32_t sz = (int32_t)stk.size();

                stk.resize(sz - 1);
                if (sz > 1)
                    it = &stk[sz - 2];
                else
                    it = NULL;
            }

            if (!it)
                break;

            if (it->pos)
                strBuffer.append(',');
            newline(strBuffer, padding);

            v = it->keys->Get(it->pos ++);

            if (!it->obj.IsEmpty())
            {
                TryCatch try_catch;

                string_format(strBuffer, v);
                strBuffer.append(": ");
                v = it->obj->Get(v);
            }
        }
        else
            break;
    }

    int32_t sz1 = (int32_t)vals.size();
    int32_t i;

    for (i = 0; i < sz1; i ++)
        vals[i]->DeleteHiddenValue(mark_name);

    return strBuffer.str();
}
Пример #6
0
result_t util_base::intersection(const v8::FunctionCallbackInfo<v8::Value> &args,
                                 v8::Local<v8::Array> &retVal)
{
    v8::Local<v8::Array> arr = v8::Array::New(Isolate::current()->m_isolate);
    int32_t argc = args.Length();
    int32_t i, j, k, n = 0;

    if (argc > 0)
    {
        if (args[0]->IsUndefined() || args[0]->IsNull())
        {
            retVal = arr;
            return 0;
        }

        for (j = 0; j < argc; j ++)
            if (!args[j]->IsArray())
                return CHECK_ERROR(CALL_E_TYPEMISMATCH);

        v8::Local<v8::Array> base = v8::Local<v8::Array>::Cast(args[0]);
        int32_t len = base->Length();
        int32_t left = len;
        QuickArray<v8::Local<v8::Value> > erase;

        erase.resize(len);
        for (i = 0; i < len; i ++)
            erase[i] = base->Get(i);

        for (i = 1; left > 0 && i < argc; i ++)
        {
            v8::Local<v8::Array> other = v8::Local<v8::Array>::Cast(args[i]);
            int32_t len1 = other->Length();

            for (j = 0; left > 0 && j < len; j ++)
                if (!erase[j].IsEmpty())
                {
                    for (k = 0; k < len1; k ++)
                        if (erase[j]->Equals(other->Get(k)))
                            break;

                    if (k == len1)
                    {
                        erase[j] = v8::Local<v8::Value>();
                        left --;
                    }
                }
        }

        if (left)
            for (i = 0; i < len; i ++)
                if (!erase[i].IsEmpty())
                {
                    for (j = 0; j < i; j ++)
                        if (!erase[j].IsEmpty() && erase[i]->Equals(erase[j]))
                            break;

                    if (j == i)
                        arr->Set(n ++, erase[i]);
                }
    }

    retVal = arr;

    return 0;
}
Пример #7
0
    static result_t run(int32_t loglevel)
    {
        if (!s_root)
            return 0;

        if (s_now != s_root)
            return CHECK_ERROR(CALL_E_INVALID_CALL);

        s_now = NULL;

        QuickArray<obj_ptr<_case> > stack;
        QuickArray<std::string> names;
        QuickArray<std::string> msgs;
        int i, j;
        int32_t oldlevel = 0;
        int32_t cnt = 0, errcnt = 0;
        char buf[128];
        date_t da1, da2;

        console_base::get_loglevel(oldlevel);
        console_base::set_loglevel(loglevel);

        stack.append(s_root);

        da1.now();

        while (stack.size())
        {
            _case *p = stack[stack.size() - 1];
            _case *p1, *p2;

            if (p->m_pos == 0)
            {
                for (i = 0; i < (int) p->m_hooks[HOOK_BEFORE].size(); i++)
                    if (v8::Local<v8::Function>::New(isolate,
                                                     p->m_hooks[HOOK_BEFORE][i])->Call(v8::Undefined(isolate),
                                                             0, NULL).IsEmpty())
                    {
                        console_base::set_loglevel(oldlevel);
                        clear();
                        return 0;
                    }
            }

            if (p->m_pos < (int) p->m_subs.size())
            {
                std::string str(stack.size() * 2, ' ');

                p1 = p->m_subs[p->m_pos++];

                if (p1->m_block.IsEmpty())
                {
                    console_base::set_loglevel(oldlevel);
                    if (stack.size() == 1)
                        asyncLog(console_base::_INFO, "");

                    str.append(logger::highLight());
                    str.append(p1->m_name);
                    str.append(COLOR_RESET);

                    asyncLog(console_base::_INFO, str);
                    console_base::set_loglevel(loglevel);

                    stack.append(p1);
                    continue;
                }

                for (j = 0; j < (int) stack.size(); j++)
                {
                    p2 = stack[j];
                    for (i = 0; i < (int) p2->m_hooks[HOOK_BEFORECASE].size();
                            i++)
                        if (v8::Local<v8::Function>::New(isolate,
                                                         p2->m_hooks[HOOK_BEFORECASE][i])->Call(v8::Undefined(isolate),
                                                                 0, NULL).IsEmpty())
                        {
                            console_base::set_loglevel(oldlevel);
                            clear();
                            return 0;
                        }
                }

                cnt++;
                {
                    v8::TryCatch try_catch;
                    date_t d1, d2;

                    d1.now();
                    v8::Local<v8::Function>::New(isolate, p1->m_block)->Call(v8::Undefined(isolate),
                            0, NULL);
                    d2.now();

                    if (try_catch.HasCaught())
                    {
                        sprintf(buf, "%d) ", ++errcnt);

                        p1->m_error = true;
                        if (loglevel > console_base::_ERROR)
                            ReportException(try_catch, 0);
                        else if (loglevel == console_base::_ERROR)
                        {
                            std::string str1(buf);

                            for (i = 1; i < (int)stack.size(); i ++)
                            {
                                str1.append(stack[i]->m_name);
                                str1.append(" ", 1);
                            }
                            str1.append(p1->m_name);
                            names.append(logger::highLight() + str1 + COLOR_RESET);

                            msgs.append(GetException(try_catch, 0));
                        }

                        str.append(buf);
                        str.append(p1->m_name);
                    }
                    else
                    {
                        double n = d2.diff(d1);

                        str.append(logger::notice() + "\xe2\x88\x9a " COLOR_RESET);
                        str.append(p1->m_name);
                        if (n > s_slow / 2)
                        {
                            sprintf(buf, " (%dms) ", (int) n);

                            if (n > s_slow)
                                str.append(logger::error());
                            else
                                str.append(logger::warn());

                            str.append(buf);
                            str.append(COLOR_RESET);
                        }
                    }
                }

                console_base::set_loglevel(oldlevel);
                asyncLog(
                    p1->m_error ?
                    console_base::_ERROR :
                    console_base::_INFO, str);
                console_base::set_loglevel(loglevel);

                for (j = (int) stack.size() - 1; j >= 0; j--)
                {
                    p2 = stack[j];
                    for (i = (int) p2->m_hooks[HOOK_AFTERCASE].size() - 1;
                            i >= 0; i--)
                        if (v8::Local<v8::Function>::New(isolate,
                                                         p2->m_hooks[HOOK_AFTERCASE][i])->Call(v8::Undefined(isolate),
                                                                 0, NULL).IsEmpty())
                        {
                            console_base::set_loglevel(oldlevel);
                            clear();
                            return 0;
                        }
                }
            }

            if (p->m_pos == (int)p->m_subs.size())
            {
                for (i = (int) p->m_hooks[HOOK_AFTER].size() - 1; i >= 0; i--)
                    if (v8::Local<v8::Function>::New(isolate,
                                                     p->m_hooks[HOOK_AFTER][i])->Call(v8::Undefined(isolate),
                                                             0, NULL).IsEmpty())
                    {
                        console_base::set_loglevel(oldlevel);
                        clear();
                        return 0;
                    }
                stack.pop();
            }
        }

        console_base::set_loglevel(oldlevel);
        asyncLog(console_base::_INFO, "");

        if (errcnt == 0)
        {
            da2.now();

            sprintf(buf,
                    (logger::notice() + "  \xe2\x88\x9a %d tests completed" COLOR_RESET " (%dms)").c_str(),
                    cnt, (int) da2.diff(da1));
            asyncLog(console_base::_INFO, buf);
        }
        else
        {
            sprintf(buf, (logger::error() + "  × %d of %d tests failed" COLOR_RESET).c_str(),
                    errcnt, cnt);
            asyncLog(console_base::_ERROR, buf);
        }

        asyncLog(console_base::_INFO, "");

        for (i = 0; i < (int) msgs.size(); i++)
        {
            asyncLog(console_base::_INFO, names[i]);
            asyncLog(console_base::_ERROR, msgs[i]);
        }

        clear();
        return 0;
    }
Пример #8
0
result_t X509Cert::load(exlib::string txtCert)
{
    if (m_root)
        return CHECK_ERROR(CALL_E_INVALID_CALL);

    int32_t ret;

    if (qstrstr(txtCert.c_str(), "BEGIN CERTIFICATE"))
    {
        ret = mbedtls_x509_crt_parse(&m_crt, (const unsigned char *)txtCert.c_str(),
                                     txtCert.length() + 1);
        if (ret != 0)
            return CHECK_ERROR(_ssl::setError(ret));

        return 0;
    }

    _parser p(txtCert);
    QuickArray<std::pair<exlib::string, exlib::string> > values;
    std::map<exlib::string, bool> verifies;
    std::map<exlib::string, bool> certs;

    while (!p.end())
    {
        exlib::string cka_label;
        exlib::string cka_value;
        exlib::string cka_serial;
        exlib::string _value;
        bool in_multiline = false, in_obj = false;
        bool is_cert = false;
        bool is_trust = false;
        bool is_value = false;
        bool is_serial = false;
        bool is_ca = false;
        bool is_verify = false;

        while (!p.end())
        {
            exlib::string line;
            exlib::string cmd, type, value;

            p.getLine(line);
            _parser p1(line);

            p1.skipSpace();
            if (p1.get() == '#')
                continue;

            if (in_multiline)
            {
                if (p1.get() == '\\')
                {
                    while (p1.get() == '\\')
                    {
                        char ch1, ch2, ch3;

                        p1.skip();

                        ch1 = p1.getChar();
                        if (ch1 < '0' || ch1 > '7')
                            break;

                        ch2 = p1.getChar();
                        if (ch2 < '0' || ch2 > '7')
                            break;

                        ch3 = p1.getChar();
                        if (ch3 < '0' || ch3 > '7')
                            break;

                        ch1 = (ch1 - '0') * 64 + (ch2 - '0') * 8 + (ch3 - '0');
                        _value.append(&ch1, 1);
                    }
                    continue;
                }

                p1.getWord(cmd);
                if ((cmd == "END"))
                {
                    if (is_value)
                        cka_value = _value;
                    else if (is_serial)
                        cka_serial = _value;

                    in_multiline = false;
                }

                continue;
            }

            p1.getWord(cmd);

            p1.skipSpace();
            p1.getWord(type);
            if ((type == "MULTILINE_OCTAL"))
            {
                in_multiline = true;
                _value.resize(0);

                is_value = is_cert && (cmd == "CKA_VALUE");
                is_serial = (cmd == "CKA_SERIAL_NUMBER");
                continue;
            }

            p1.skipSpace();
            p1.getLeft(value);

            if (!in_obj)
            {
                if ((cmd == "CKA_CLASS"))
                {
                    in_obj = true;
                    is_cert = (value == "CKO_CERTIFICATE");
                    is_trust = (value == "CKO_NSS_TRUST");
                }
                continue;
            }

            if ((cmd == "CKA_LABEL"))
                cka_label = value;
            else if (is_trust && (cmd == "CKA_TRUST_SERVER_AUTH"))
            {
                is_ca = (value == "CKT_NSS_TRUSTED_DELEGATOR");
                is_verify = (value == "CKT_NSS_MUST_VERIFY_TRUST");
            }

            if (cmd.empty())
                break;
        }

        if (!cka_label.empty())
        {
            if (is_trust)
            {
                if (is_ca)
                    certs.insert(std::pair<exlib::string, bool>(cka_label + cka_serial, true));
                if (is_verify)
                    verifies.insert(std::pair<exlib::string, bool>(cka_label + cka_serial, true));
            }
            else if (is_cert && !cka_value.empty())
                values.append(std::pair<exlib::string, exlib::string>(cka_label + cka_serial, cka_value));
        }
    }

    bool is_loaded = false;
    int32_t i;

    for (i = 0; i < (int32_t)values.size(); i++)
    {
        std::pair<exlib::string, exlib::string> &c = values[i];
        std::map<exlib::string, bool>::iterator it_trust;

        it_trust = verifies.find(c.first);
        if (it_trust != verifies.end())
        {
            ret = mbedtls_x509_crt_parse_der(&m_crt,
                                             (const unsigned char *)c.second.c_str(),
                                             c.second.length());
            if (ret != 0)
                return CHECK_ERROR(_ssl::setError(ret));

            is_loaded = true;
        }
    }

    for (i = 0; i < (int32_t)values.size(); i++)
    {
        std::pair<exlib::string, exlib::string> &c = values[i];
        std::map<exlib::string, bool>::iterator it_trust;

        it_trust = certs.find(c.first);
        if (it_trust != certs.end())
        {
            ret = mbedtls_x509_crt_parse_der(&m_crt,
                                             (const unsigned char *)c.second.c_str(),
                                             c.second.length() );
            if (ret != 0)
                return CHECK_ERROR(_ssl::setError(ret));

            is_loaded = true;
        }
    }

    if (!is_loaded)
        return CHECK_ERROR(_ssl::setError(MBEDTLS_ERR_X509_INVALID_FORMAT));

    return 0;
}