static inline int ln_addTags_Syslog(struct json_object *taglist, es_str_t **str) { int r = 0; struct json_object *tagObj; int needComma = 0; const char *tagCstr; int i; assert(json_object_is_type(taglist, json_type_array)); CHKR(es_addBuf(str, " event.tags=\"", 13)); for (i = json_object_array_length(taglist) - 1; i >= 0; i--) { if(needComma) es_addChar(str, ','); else needComma = 1; CHKN(tagObj = json_object_array_get_idx(taglist, i)); CHKN(tagCstr = json_object_get_string(tagObj)); CHKR(es_addBuf(str, (char*)tagCstr, strlen(tagCstr))); } es_addChar(str, '"'); done: return r; }
int ln_fmtEventToRFC5424(struct json_object *json, es_str_t **str) { int r = -1; struct json_object *tags; assert(json != NULL); assert(json_object_is_type(json, json_type_object)); if((*str = es_newStr(256)) == NULL) goto done; es_addBuf(str, "[cee@115", 8); if(json_object_object_get_ex(json, "event.tags", &tags)) { CHKR(ln_addTags_Syslog(tags, str)); } struct json_object_iterator it = json_object_iter_begin(json); struct json_object_iterator itEnd = json_object_iter_end(json); while (!json_object_iter_equal(&it, &itEnd)) { char *const name = (char*)json_object_iter_peek_name(&it); if (strcmp(name, "event.tags")) { es_addChar(str, ' '); ln_addField_Syslog(name, json_object_iter_peek_value(&it), str); } json_object_iter_next(&it); } es_addChar(str, ']'); done: return r; }
/* the following is a quick hack, which should be moved to the * string class. */ static inline void dotAddPtr(es_str_t **str, void *p) { char buf[64]; int i; i = snprintf(buf, sizeof(buf), "%p", p); es_addBuf(str, buf, i); }
static int ln_addField_Syslog(char *name, struct json_object *field, es_str_t **str) { int r; const char *value; int needComma = 0; struct json_object *obj; int i; assert(field != NULL); assert(str != NULL); assert(*str != NULL); CHKR(es_addBuf(str, name, strlen(name))); CHKR(es_addBuf(str, "=\"", 2)); switch(json_object_get_type(field)) { case json_type_array: for (i = json_object_array_length(field) - 1; i >= 0; i--) { if(needComma) es_addChar(str, ','); else needComma = 1; CHKN(obj = json_object_array_get_idx(field, i)); CHKN(value = json_object_get_string(obj)); CHKR(ln_addValue_Syslog(value, str)); } break; case json_type_string: case json_type_int: CHKN(value = json_object_get_string(field)); CHKR(ln_addValue_Syslog(value, str)); break; case json_type_null: case json_type_boolean: case json_type_double: case json_type_object: CHKR(es_addBuf(str, "***unsupported type***", sizeof("***unsupported type***")-1)); break; default: CHKR(es_addBuf(str, "***OBJECT***", sizeof("***OBJECT***")-1)); } CHKR(es_addChar(str, '\"')); r = 0; done: return r; }
int ee_addField_JSON(struct ee_field *field, es_str_t **str) { int r; struct ee_valnode *valnode; assert(field != NULL);assert(field->objID== ObjID_FIELD); assert(str != NULL); assert(*str != NULL); #ifdef NO_EMPTY_FIELDS if(field->nVals == 0) { r = 1; goto done; } else if(field->nVals == 1 && es_strlen(field->val->val.str) == 0) { r = 1; goto done; } #endif CHKR(es_addChar(str, '\"')); CHKR(es_addStr(str, field->name)); if(ee_ctxIsEncUltraCompact(field->ctx)) { CHKR(es_addBuf(str, "\":", 2)); } else { CHKR(es_addBuf(str, "\": ", 3)); } if(field->nVals == 0) { if(ee_ctxIsEncUltraCompact(field->ctx)) { CHKR(es_addChar(str, '\"')); } else { CHKR(es_addBuf(str, "\"\"", 2)); } } else if(field->nVals == 1) { CHKR(ee_addValue_JSON(field->val, str)); } else { /* we have multiple values --> array */ CHKR(es_addChar(str, '[')); CHKR(ee_addValue_JSON(field->val, str)); for(valnode = field->valroot ; valnode != NULL ; valnode = valnode->next) { CHKR(es_addChar(str, ',')); CHKR(ee_addValue_JSON(valnode->val, str)); } CHKR(es_addChar(str, ']')); } r = 0; done: return r; }
void ln_displayPTree(struct ln_ptree *tree, int level) { int i; int nChildLit; int nChildField; es_str_t *str; char *cstr; ln_fieldList_t *node; char indent[2048]; if(level > 1023) level = 1023; memset(indent, ' ', level * 2); indent[level * 2] = '\0'; nChildField = 0; for(node = tree->froot ; node != NULL ; node = node->next ) { ++nChildField; } nChildLit = 0; for(i = 0 ; i < 256 ; ++i) { if(tree->subtree[i] != NULL) { nChildLit++; } } str = es_newStr(sizeof(tree->prefix)); es_addBuf(&str, (char*) prefixBase(tree), tree->lenPrefix); cstr = es_str2cstr(str, NULL); es_deleteStr(str); ln_dbgprintf(tree->ctx, "%ssubtree%s %p (prefix: '%s', children: %d literals, %d fields)", indent, tree->flags.isTerminal ? " TERM" : "", tree, cstr, nChildLit, nChildField); free(cstr); /* display char subtrees */ for(i = 0 ; i < 256 ; ++i) { if(tree->subtree[i] != NULL) { ln_dbgprintf(tree->ctx, "%schar %2.2x(%c):", indent, i, i); ln_displayPTree(tree->subtree[i], level + 1); } } /* display field subtrees */ for(node = tree->froot ; node != NULL ; node = node->next ) { cstr = es_str2cstr(node->name, NULL); ln_dbgprintf(tree->ctx, "%sfield %s:", indent, cstr); free(cstr); ln_displayPTree(node->subtree, level + 1); } }
/** * recursive handler for DOT graph generator. */ static void ln_genDotPTreeGraphRec(struct ln_ptree *tree, es_str_t **str) { int i; ln_fieldList_t *node; dotAddPtr(str, tree); es_addBufConstcstr(str, " [label=\""); if(tree->lenPrefix > 0) { es_addChar(str, '\''); es_addBuf(str, (char*) prefixBase(tree), tree->lenPrefix); es_addChar(str, '\''); } es_addBufConstcstr(str, "\""); if(isLeaf(tree)) { es_addBufConstcstr(str, " style=\"bold\""); } es_addBufConstcstr(str, "]\n"); /* display char subtrees */ for(i = 0 ; i < 256 ; ++i) { if(tree->subtree[i] != NULL) { dotAddPtr(str, tree); es_addBufConstcstr(str, " -> "); dotAddPtr(str, tree->subtree[i]); es_addBufConstcstr(str, " [label=\""); es_addChar(str, (char) i); es_addBufConstcstr(str, "\"]\n"); ln_genDotPTreeGraphRec(tree->subtree[i], str); } } /* display field subtrees */ for(node = tree->froot ; node != NULL ; node = node->next ) { dotAddPtr(str, tree); es_addBufConstcstr(str, " -> "); dotAddPtr(str, node->subtree); es_addBufConstcstr(str, " [label=\""); es_addStr(str, node->name); es_addBufConstcstr(str, "\" style=\"dotted\"]\n"); ln_genDotPTreeGraphRec(node->subtree, str); } }
static inline int ee_addTags_JSON(struct ee_tagbucket *tags, es_str_t **str) { int r = 0; struct ee_tagbucket_listnode *tag; int needComma = 0; CHKR(es_addBuf(str, "\"event.tags\":[", 14)); for(tag = tags->root ; tag != NULL ; tag = tag->next) { if(needComma) es_addChar(str, ','); else needComma = 1; es_addChar(str, '"'); CHKR(es_addStr(str, tag->name)); es_addChar(str, '"'); } es_addChar(str, ']'); done: return r; }
int ee_fmtEventToJSON(struct ee_event *event, es_str_t **str) { int r = -1; struct ee_fieldbucket_listnode *node; int bNeedComma = 0; assert(event != NULL);assert(event->objID == ObjID_EVENT); if((*str = es_newStr(256)) == NULL) goto done; es_addChar(str, '{'); if( event->ctx->flags & EE_CTX_FLAG_INCLUDE_FLAT_TAGS && event->tags != NULL) { CHKR(ee_addTags_JSON(event->tags, str)); bNeedComma = 1; } if(event->fields != NULL) { for(node = event->fields->root ; node != NULL ; node = node->next) { assert(node->field->objID == ObjID_FIELD); if(bNeedComma) { CHKR(es_addBuf(str, ", ", 2)); } else { bNeedComma = 1; } #ifdef NO_EMPTY_FIELDS if(ee_addField_JSON(node->field, str) == 1) continue; #else ee_addField_JSON(node->field, str); #endif } } es_addChar(str, '}'); done: return r; }
/* TODO: JSON encoding for Unicode characters is as of RFC4627 not fully * supported. The algorithm is that we must build the wide character from * UTF-8 (if char > 127) and build the full 4-octet Unicode character out * of it. Then, this needs to be encoded. Currently, we work on a * byte-by-byte basis, which simply is incorrect. * rgerhards, 2010-11-09 */ int ee_addValue_JSON(struct ee_value *value, es_str_t **str) { int r; es_str_t *valstr; unsigned char *buf; unsigned char c; es_size_t i; char numbuf[4]; int j; assert(str != NULL); assert(*str != NULL); assert(value != NULL); assert(value->objID == ObjID_VALUE); // TODO: support other types! assert(value->valtype == ee_valtype_str); valstr = value->val.str; es_addChar(str, '\"'); buf = es_getBufAddr(valstr); for(i = 0 ; i < es_strlen(valstr) ; ++i) { c = buf[i]; if( (c >= 0x23 && c <= 0x5b) || (c >= 0x5d /* && c <= 0x10FFFF*/) || c == 0x20 || c == 0x21) { /* no need to escape */ es_addChar(str, c); } else { /* we must escape, try RFC4627-defined special sequences first */ switch(c) { case '\0': es_addBuf(str, "\\u0000", 6); break; case '\"': es_addBuf(str, "\\\"", 2); break; case '/': es_addBuf(str, "\\/", 2); break; case '\\': es_addBuf(str, "\\\\", 2); break; case '\010': es_addBuf(str, "\\b", 2); break; case '\014': es_addBuf(str, "\\f", 2); break; case '\n': es_addBuf(str, "\\n", 2); break; case '\r': es_addBuf(str, "\\r", 2); break; case '\t': es_addBuf(str, "\\t", 2); break; default: /* TODO : proper Unicode encoding (see header comment) */ for(j = 0 ; j < 4 ; ++j) { numbuf[3-j] = hexdigit[c % 16]; c = c / 16; } es_addBuf(str, "\\u", 2); es_addBuf(str, numbuf, 4); break; } } } es_addChar(str, '\"'); r = 0; return r; }