static rc_t XML_ValidateNode(FSNode* parent, const KXMLNode* n, SRAConfigFlags flags, char* errmsg) { rc_t rc = 0; const char* name = NULL; FSNode* fsn = NULL; bool children_allowed = false, should_have_children = false, ignore_children = false; if( (rc = KXMLNodeElementName(n, &name)) != 0 ) { return rc; } DEBUG_MSG(8, ("Node: %s\n", name)); if( name == NULL ) { return RC(rcExe, rcDoc, rcValidating, rcDirEntry, rcNull); } if( strcmp(name, "Directory") == 0 ) { rc = DirectoryNode_Make(n, &fsn, errmsg, g_start_dir, g_xml_mtime, g_xml_validate); children_allowed = true; } else if( strcmp(name, "File") == 0 ) { rc = FileNode_Make(n, &fsn, errmsg, g_start_dir, g_xml_validate); } else if( strcmp(name, "SRA") == 0 ) { if( (rc = SRAListNode_Make(n, parent, flags, errmsg, g_start_dir, g_xml_validate)) == 0 ) { fsn = parent; } } else if( strcmp(name, "TAR") == 0 ) { /* tar nodes do not validate on creation */ rc = TarNode_MakeXML(n, &fsn, errmsg, g_start_dir); children_allowed = true; ignore_children = true; } else if( strcmp(name, "SRAConfig") == 0 ) { if( (rc = SRAConfigParse(n, &flags, errmsg)) == 0 ) { fsn = parent; children_allowed = true; should_have_children = true; } } else { strcpy(errmsg, name); rc = RC(rcExe, rcDoc, rcValidating, rcTag, rcUnknown); } if( rc == 0 ) { strcpy(errmsg, name); if( fsn == parent || (rc = FSNode_AddChild(parent, fsn)) == 0 ) { uint32_t count = 0; if( (rc = KXMLNodeCountChildNodes(n, &count)) == 0 && count > 0 ) { if( !children_allowed ) { if( fsn != NULL ) { FSNode_GetName(fsn, &name); } rc = RC(rcExe, rcDoc, rcValidating, rcDirEntry, rcInvalid); strcpy(errmsg, name); } else if( !ignore_children ) { uint32_t i = 0; const KXMLNode* ch = NULL; while( rc == 0 && i < count ) { if( (rc = KXMLNodeGetNodeRead(n, &ch, i++)) == 0 ) { rc = XML_ValidateNode(fsn, ch, flags, errmsg); ReleaseComplain(KXMLNodeRelease, ch); } } } } else if( count == 0 && should_have_children ) { PLOGMSG(klogWarn, (klogWarn, "$(n) may have children", PLOG_S(n), name)); } } } return rc; }
static rc_t TarNode_MakeFileList(const KXMLNode* xml_node, const TarFileList** files, char* errmsg, const char* rel_path, const char* name) { rc_t rc = 0; time_t now = time(NULL); uint32_t count = 0; *files = NULL; if( (rc = KXMLNodeCountChildNodes(xml_node, &count)) == 0 ) { if( count == 0 ) { rc = RC(rcExe, rcDoc, rcValidating, rcData, rcEmpty); } else if( (rc = TarFileList_Make(files, count, name)) == 0 ) { uint32_t i = 0; while(rc == 0 && i < count) { const KXMLNode* n = NULL; const char* n_name; if( (rc = KXMLNodeGetNodeRead(xml_node, &n, i++)) == 0 && (rc = KXMLNodeElementName(n, &n_name)) == 0 ) { if( strcmp(n_name, "Item") != 0 ) { rc = RC(rcExe, rcDoc, rcValidating, rcNode, rcUnexpected); strcpy(errmsg, n_name); } else { size_t sz_read; char path[4096], name[4096]; KTime_t ts = now; uint64_t fsz = 0; bool exec = false; if( (rc = KXMLNodeReadAttrCString(n, "path", name, sizeof(name), &sz_read)) == 0 ) { if( name[0] == '\0' ) { rc = RC(rcExe, rcDoc, rcValidating, rcAttr, rcEmpty); } else if( name[0] == '/' ) { memmove(path, name, sz_read + 1); } else { KDirectory* dir = NULL; if( (rc = KDirectoryNativeDir(&dir)) == 0 && (rc = KDirectoryResolvePath(dir, true, path, sizeof(path), "%s/%s", rel_path, name)) == 0 ) { DEBUG_LINE(8, "%s/%s resolved to %s", rel_path, name, path); } KDirectoryRelease(dir); } if( rc != 0 ) { strcpy(errmsg, "TAR/Item/@path"); } } if( rc == 0 && (rc = XML_ParseTimestamp(n, "timestamp", &ts, true)) != 0 ) { strcpy(errmsg, "TAR/Item/@timestamp"); } if( rc == 0 && (rc = XML_ParseBool(n, "executable", &exec, true)) != 0 ) { strcpy(errmsg, "TAR/Item/@executable"); } if( rc == 0 && (rc = KXMLNodeReadAttrAsU64(n, "size", &fsz)) != 0 ) { strcpy(errmsg, "TAR/Item/@size"); } if( rc == 0 ) { name[0] = '\0'; rc = KXMLNodeReadAttrCString(n, "name", name, sizeof(name), &sz_read); if( (GetRCObject(rc) == (enum RCObject)rcAttr && GetRCState(rc) == rcNotFound) || name[0] == '\0' ) { char* x = strrchr(path, '/'); strcpy(name, x ? x + 1 : path); rc = 0; } else if( rc == 0 && name[0] == '/' ) { strcat(errmsg, "Item/@name cannot be absolute"); rc = RC(rcExe, rcDoc, rcValidating, rcName, rcInvalid); } else if( rc != 0 ) { strcpy(errmsg, "Item/@name"); } } if( rc == 0 ) { const KNamelist* attr = NULL; if( (rc = KXMLNodeListAttr(n, &attr)) == 0 ) { uint32_t j = 0, count = 0; if( (rc = KNamelistCount(attr, &count)) == 0 && count > 0 ) { while( rc == 0 && j < count ) { const char *attr_nm = NULL; if( (rc = KNamelistGet(attr, j++, &attr_nm)) != 0 ) { break; } if( strcmp("path", attr_nm) == 0 || strcmp("name", attr_nm) == 0 || strcmp("timestamp", attr_nm) == 0 || strcmp("size", attr_nm) == 0 || strcmp("executable", attr_nm) == 0 ) { continue; } rc = RC(rcExe, rcDoc, rcValidating, rcDirEntry, rcInvalid); strcpy(errmsg, "unknown attribute TAR/Item/@"); strcat(errmsg, attr_nm); } } ReleaseComplain(KNamelistRelease, attr); } } if( rc == 0 && (rc = TarFileList_Add(*files, path, name, fsz, ts, exec)) != 0 ) { strcpy(errmsg, "adding to TAR"); } } ReleaseComplain(KXMLNodeRelease, n); } } if( rc != 0 ) { TarFileList_Release(*files); *files = NULL; } } } return rc; }
static rc_t ProcessNode(const KXMLNode* node, const char* parentName, uint32_t idx, struct XTocEntry* xSelf, struct XTocEntry* xContainer) { rc_t rc = 0; uint32_t count = 0; uint32_t i = 0; struct XTocEntry* xEntry = NULL; bool isContainer = false; NodeData data; assert(node && parentName); if (rc == 0) { rc = NodeDataInit(&data, node, parentName, idx); } if (rc == 0) { DBGMSG(DBG_APP,DBG_COND_1, ("%s[%i] = %s\n", parentName, idx, data.nodeName)); rc = NodeDataAddToXToc(&data, xSelf, xContainer, &xEntry, &isContainer); if (isContainer) { xContainer = xEntry; } } if (rc == 0) { rc = KXMLNodeCountChildNodes(node, &count); if (rc != 0) { /* PLOGERR(klogErr, (klogErr, rc, "while calling KXMLNodeCountChildNodes($(parent)[$(i)])", "parent=%s,i=%d", parentName, idx));*/ } else { /* DBGMSG(DBG_APP,DBG_COND_1, ("KXMLNodeCountChildNodes(%s) = %i\n", data.nodeName, count));*/ } } for (i = 0; i < count && rc == 0; ++i) { const KXMLNode* child = NULL; rc = KXMLNodeGetNodeRead(node, &child, i); if (rc != 0) { /* PLOGERR(klogErr, (klogErr, rc, "while calling KXMLNodeCountChildNodes($(parent)[$(i)][$(j)]", "parent=%s,i=%d,j=%d", parentName, idx, i));*/ } else { /* DBGMSG(DBG_APP,DBG_COND_1, ("KXMLNodeGetNodeRead(%s[%i])\n", data.nodeName, idx, i));*/ ProcessNode(child, data.nodeName, i, xEntry, xContainer); } { rc_t rc2 = KXMLNodeRelease(child); if (rc == 0) { rc = rc2; } child = NULL; } } NodeDataDestroy(&data); return rc; }