2004-06-03 20:38:14 +02:00
|
|
|
#include "precompiled.h"
|
|
|
|
|
2005-02-21 18:13:31 +01:00
|
|
|
#include "XML.h"
|
2004-06-03 15:00:19 +02:00
|
|
|
#include "CStr.h"
|
2004-06-03 19:34:49 +02:00
|
|
|
#include "CLogger.h"
|
2004-06-08 14:00:39 +02:00
|
|
|
#include "posix.h" // ptrdiff_t
|
2004-06-03 15:00:19 +02:00
|
|
|
|
2005-08-12 19:06:53 +02:00
|
|
|
#include "lib/res/file/vfs.h"
|
|
|
|
#include "lib/res/mem.h"
|
2004-06-03 15:00:19 +02:00
|
|
|
|
2004-08-15 22:57:31 +02:00
|
|
|
#define LOG_CATEGORY "xml"
|
|
|
|
|
2004-06-19 16:41:54 +02:00
|
|
|
/*
|
|
|
|
// but static Xerces => tons of warnings due to missing debug info,
|
|
|
|
// and warnings about invalid pointers (conflicting CRT heaps?) in parser => allow for now
|
|
|
|
#ifndef XERCES_STATIC_LIB
|
|
|
|
#error "need to define XERCES_STATIC_LIB in project options (so that Xerces uses the same CRT as the other libs)"
|
|
|
|
#endif
|
|
|
|
*/
|
|
|
|
|
2005-08-09 17:55:44 +02:00
|
|
|
#if MSC_VERSION
|
2004-06-11 04:14:18 +02:00
|
|
|
# ifdef XERCES_STATIC_LIB
|
|
|
|
# ifndef NDEBUG
|
2004-06-13 18:03:12 +02:00
|
|
|
# pragma comment(lib, "xerces-c_2D-static.lib")
|
2004-06-11 04:14:18 +02:00
|
|
|
# else
|
2004-07-04 17:45:49 +02:00
|
|
|
# pragma comment(lib, "xerces-c_2D-static.lib")
|
2004-06-11 04:14:18 +02:00
|
|
|
# endif // NDEBUG
|
2004-06-19 16:41:54 +02:00
|
|
|
# else // XERCES_STATIC_LIB
|
2004-06-11 04:14:18 +02:00
|
|
|
# ifndef NDEBUG
|
2004-06-13 18:03:12 +02:00
|
|
|
# pragma comment(lib, "xerces-c_2D.lib")
|
2004-06-11 04:14:18 +02:00
|
|
|
# else
|
|
|
|
# pragma comment(lib, "xerces-c_2.lib")
|
|
|
|
# endif // NDEBUG
|
2004-06-19 16:41:54 +02:00
|
|
|
# endif // XERCES_STATIC_LIB
|
2005-08-09 17:55:44 +02:00
|
|
|
#endif // MSC_VERSION
|
2004-06-03 20:38:14 +02:00
|
|
|
|
2004-06-03 15:00:19 +02:00
|
|
|
XERCES_CPP_NAMESPACE_USE
|
|
|
|
|
|
|
|
CStr XMLTranscode(const XMLCh* xmltext)
|
|
|
|
{
|
|
|
|
char* str=XMLString::transcode((const XMLCh *)xmltext);
|
|
|
|
CStr result(str);
|
|
|
|
XMLString::release(&str);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2004-06-09 15:41:11 +02:00
|
|
|
XMLCh *XMLTranscode(const char *str)
|
2004-06-03 15:00:19 +02:00
|
|
|
{
|
2004-06-09 15:41:11 +02:00
|
|
|
return XMLString::transcode(str);
|
2004-06-03 15:00:19 +02:00
|
|
|
}
|
|
|
|
|
2006-02-04 23:31:25 +01:00
|
|
|
int CVFSInputSource::OpenFile(const char *path, uint flags = 0)
|
2004-06-03 15:00:19 +02:00
|
|
|
{
|
2006-02-04 23:31:25 +01:00
|
|
|
LibError ret = vfs_load(path, m_pBuffer, m_BufferSize, flags);
|
2006-01-24 09:16:29 +01:00
|
|
|
if(ret != ERR_OK)
|
2004-06-03 19:34:49 +02:00
|
|
|
{
|
2006-01-24 09:16:29 +01:00
|
|
|
LOG(ERROR, LOG_CATEGORY, "CVFSInputSource: file %s couldn't be loaded (vfs_load: %d)", path, ret);
|
2004-06-03 19:34:49 +02:00
|
|
|
return -1;
|
|
|
|
}
|
2004-08-24 19:26:35 +02:00
|
|
|
|
2004-06-03 15:00:19 +02:00
|
|
|
XMLCh *sysId=XMLString::transcode(path);
|
|
|
|
setSystemId(sysId);
|
|
|
|
XMLString::release(&sysId);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
CVFSInputSource::~CVFSInputSource()
|
|
|
|
{
|
2004-08-24 19:26:35 +02:00
|
|
|
// our buffer was vfs_load-ed; free it now
|
2006-01-24 09:16:29 +01:00
|
|
|
(void)file_buf_free(m_pBuffer);
|
2006-02-04 23:31:25 +01:00
|
|
|
m_pBuffer = 0;
|
2004-06-03 15:00:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
BinInputStream *CVFSInputSource::makeStream() const
|
|
|
|
{
|
2006-02-02 05:11:07 +01:00
|
|
|
if (m_pBuffer != 0)
|
2004-06-03 15:00:19 +02:00
|
|
|
{
|
2005-08-12 19:06:53 +02:00
|
|
|
#include "nommgr.h"
|
2004-06-08 14:00:39 +02:00
|
|
|
return new BinMemInputStream((XMLByte *)m_pBuffer, (unsigned int)m_BufferSize,
|
2004-06-03 15:00:19 +02:00
|
|
|
BinMemInputStream::BufOpt_Reference);
|
2005-08-12 19:06:53 +02:00
|
|
|
#include "mmgr.h"
|
2004-06-03 15:00:19 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2004-06-09 15:41:11 +02:00
|
|
|
#define IS_PATH_SEP(_chr) (_chr == '/' || _chr == '\\')
|
|
|
|
|
|
|
|
// Return a pointer to the last path separator preceding *end, while not
|
|
|
|
// going further back than *beginning
|
|
|
|
const char *prevpathcomp(const char *end, const char *beginning)
|
|
|
|
{
|
|
|
|
do
|
|
|
|
end--;
|
|
|
|
while (end > beginning && !IS_PATH_SEP(*end));
|
|
|
|
return end;
|
|
|
|
}
|
|
|
|
|
2005-08-09 17:55:44 +02:00
|
|
|
InputSource *CVFSEntityResolver::resolveEntity(const XMLCh *const UNUSED(publicId),
|
2004-06-03 15:00:19 +02:00
|
|
|
const XMLCh *const systemId)
|
|
|
|
{
|
2005-08-12 19:06:53 +02:00
|
|
|
#include "nommgr.h"
|
2004-06-03 15:00:19 +02:00
|
|
|
CVFSInputSource *ret=new CVFSInputSource();
|
2005-08-12 19:06:53 +02:00
|
|
|
#include "mmgr.h"
|
2004-06-03 15:00:19 +02:00
|
|
|
char *path=XMLString::transcode(systemId);
|
|
|
|
char *orgpath=path;
|
|
|
|
|
2006-04-22 18:26:16 +02:00
|
|
|
char abspath[PATH_MAX];
|
2004-06-09 15:41:11 +02:00
|
|
|
const char *end=strchr(m_DocName, '\0');
|
2004-06-03 15:00:19 +02:00
|
|
|
|
2004-07-07 03:44:54 +02:00
|
|
|
if (IS_PATH_SEP(*path))
|
|
|
|
path++;
|
|
|
|
else
|
2004-06-09 15:41:11 +02:00
|
|
|
{
|
2004-07-07 03:44:54 +02:00
|
|
|
// We know that we have a relative path here:
|
|
|
|
// - Remove the file name
|
|
|
|
// - If we have a ../ components - remove them and remove one component
|
2005-03-01 21:13:00 +01:00
|
|
|
// off the end of the document path for each ../ component
|
2004-07-07 03:44:54 +02:00
|
|
|
// - prefix of document path + suffix of input path => the VFS path
|
|
|
|
|
|
|
|
// Remove the file name
|
|
|
|
end=prevpathcomp(end, m_DocName);
|
|
|
|
|
|
|
|
// Remove one path component for each opening ../ (or ..\)
|
|
|
|
// Note that this loop will stop when all path components from the
|
|
|
|
// document name have been stripped - the resulting path will be invalid, but
|
|
|
|
// so was the input path.
|
|
|
|
// Also note that this will not handle ../ path components in the middle of
|
|
|
|
// the input path.
|
|
|
|
while (strncmp(path, "..", 2) == 0 && IS_PATH_SEP(path[2]) && end > m_DocName)
|
|
|
|
{
|
2004-06-09 15:41:11 +02:00
|
|
|
end=prevpathcomp(end, m_DocName);
|
2004-07-07 03:44:54 +02:00
|
|
|
path += 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
// include one slash from prefix
|
|
|
|
end++;
|
2004-06-03 15:00:19 +02:00
|
|
|
|
2004-06-09 15:41:11 +02:00
|
|
|
const ptrdiff_t prefixlen=end-m_DocName;
|
|
|
|
|
2005-10-30 17:19:20 +01:00
|
|
|
memcpy2(abspath, m_DocName, prefixlen);
|
2006-04-22 18:26:16 +02:00
|
|
|
strncpy(abspath+prefixlen, path, PATH_MAX-prefixlen);
|
2004-06-09 15:41:11 +02:00
|
|
|
// strncpy might not have terminated, if path was too long
|
2006-04-22 18:26:16 +02:00
|
|
|
abspath[PATH_MAX-1]=0;
|
2004-06-03 19:34:49 +02:00
|
|
|
|
2004-06-09 15:41:11 +02:00
|
|
|
path=abspath;
|
2004-06-03 15:00:19 +02:00
|
|
|
}
|
2004-07-07 03:44:54 +02:00
|
|
|
|
2005-08-12 19:06:53 +02:00
|
|
|
// janwas: removed for less spew
|
2004-11-16 19:22:54 +01:00
|
|
|
// LOG(NORMAL, LOG_CATEGORY, "EntityResolver: path \"%s\" translated to \"%s\"", orgpath, path);
|
2005-08-12 19:06:53 +02:00
|
|
|
|
2004-07-07 03:44:54 +02:00
|
|
|
|
|
|
|
char *pos=path;
|
|
|
|
if ((pos=strchr(pos, '\\')) != NULL)
|
|
|
|
{
|
2004-08-15 22:57:31 +02:00
|
|
|
LOG(WARNING, LOG_CATEGORY, "While resolving XML entities for %s: path %s [%s] contains non-portable path separator \\", m_DocName, orgpath, path);
|
2004-07-07 03:44:54 +02:00
|
|
|
do
|
|
|
|
*pos='/';
|
|
|
|
while ((pos=strchr(pos+1, '\\')) != NULL);
|
|
|
|
}
|
|
|
|
|
2004-06-09 15:41:11 +02:00
|
|
|
if (ret->OpenFile(path)!=0)
|
2004-06-03 15:00:19 +02:00
|
|
|
{
|
|
|
|
delete ret;
|
|
|
|
ret=NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
XMLString::release(&orgpath);
|
|
|
|
return ret;
|
|
|
|
}
|