mirror of
https://github.com/cookiengineer/audacity
synced 2025-10-19 09:01:15 +02:00
Locate and position the current Audacity source code, and clear a variety of old junk out of the way into junk-branches
This commit is contained in:
152
src/xml/XMLFileReader.cpp
Normal file
152
src/xml/XMLFileReader.cpp
Normal file
@@ -0,0 +1,152 @@
|
||||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
XMLFileReader.cpp
|
||||
|
||||
Dominic Mazzoni
|
||||
|
||||
*******************************************************************//**
|
||||
|
||||
\class XMLFileReader
|
||||
\brief Reads a file and passes the results through an XMLTagHandler.
|
||||
|
||||
*//*******************************************************************/
|
||||
|
||||
#include <wx/defs.h>
|
||||
#include <wx/ffile.h>
|
||||
#include <wx/intl.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "../Internat.h"
|
||||
#include "XMLFileReader.h"
|
||||
|
||||
XMLFileReader::XMLFileReader()
|
||||
{
|
||||
mParser = XML_ParserCreate(NULL);
|
||||
XML_SetUserData(mParser, (void *)this);
|
||||
XML_SetElementHandler(mParser, startElement, endElement);
|
||||
XML_SetCharacterDataHandler(mParser, charHandler);
|
||||
mBaseHandler = NULL;
|
||||
mMaxDepth = 128;
|
||||
mHandler = new XMLTagHandler*[mMaxDepth];
|
||||
mDepth = -1;
|
||||
mErrorStr = wxT("");
|
||||
}
|
||||
|
||||
XMLFileReader::~XMLFileReader()
|
||||
{
|
||||
delete[] mHandler;
|
||||
XML_ParserFree(mParser);
|
||||
}
|
||||
|
||||
bool XMLFileReader::Parse(XMLTagHandler *baseHandler,
|
||||
const wxString &fname)
|
||||
{
|
||||
wxFFile theXMLFile(fname, wxT("rb"));
|
||||
if (!theXMLFile.IsOpened()) {
|
||||
mErrorStr.Printf(_("Could not open file: \"%s\""), fname.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
mBaseHandler = baseHandler;
|
||||
mHandler[0] = NULL;
|
||||
|
||||
const size_t bufferSize = 16384;
|
||||
char buffer[16384];
|
||||
int done = 0;
|
||||
do {
|
||||
size_t len = fread(buffer, 1, bufferSize, theXMLFile.fp());
|
||||
done = (len < bufferSize);
|
||||
if (!XML_Parse(mParser, buffer, len, done)) {
|
||||
mErrorStr.Printf(_("Error: %hs at line %lu"),
|
||||
XML_ErrorString(XML_GetErrorCode(mParser)),
|
||||
(long unsigned int)XML_GetCurrentLineNumber(mParser));
|
||||
theXMLFile.Close();
|
||||
return false;
|
||||
}
|
||||
} while (!done);
|
||||
|
||||
theXMLFile.Close();
|
||||
|
||||
// Even though there were no parse errors, we only succeed if
|
||||
// the first-level handler actually got called, and didn't
|
||||
// return false.
|
||||
if (mHandler[0])
|
||||
return true;
|
||||
else {
|
||||
mErrorStr.Printf(_("Could not load file: \"%s\""), fname.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
wxString XMLFileReader::GetErrorStr()
|
||||
{
|
||||
return mErrorStr;
|
||||
}
|
||||
|
||||
// static
|
||||
void XMLFileReader::startElement(void *userData, const char *name,
|
||||
const char **atts)
|
||||
{
|
||||
XMLFileReader *This = (XMLFileReader *)userData;
|
||||
|
||||
This->mDepth++;
|
||||
|
||||
if (This->mDepth >= This->mMaxDepth) {
|
||||
XMLTagHandler **newHandler = new XMLTagHandler*[This->mMaxDepth*2];
|
||||
for(int i=0; i<This->mMaxDepth; i++)
|
||||
newHandler[i] = This->mHandler[i];
|
||||
delete[] This->mHandler;
|
||||
This->mHandler = newHandler;
|
||||
This->mMaxDepth *= 2;
|
||||
}
|
||||
|
||||
if (This->mDepth==0)
|
||||
This->mHandler[This->mDepth] = This->mBaseHandler;
|
||||
else {
|
||||
if (This->mHandler[This->mDepth-1])
|
||||
This->mHandler[This->mDepth] =
|
||||
This->mHandler[This->mDepth-1]->ReadXMLChild(name);
|
||||
else
|
||||
This->mHandler[This->mDepth] = NULL;
|
||||
}
|
||||
|
||||
if (This->mHandler[This->mDepth]) {
|
||||
if (!This->mHandler[This->mDepth]->ReadXMLTag(name, atts))
|
||||
This->mHandler[This->mDepth] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void XMLFileReader::endElement(void *userData, const char *name)
|
||||
{
|
||||
XMLFileReader *This = (XMLFileReader *)userData;
|
||||
|
||||
if (This->mHandler[This->mDepth])
|
||||
This->mHandler[This->mDepth]->ReadXMLEndTag(name);
|
||||
|
||||
This->mDepth--;
|
||||
}
|
||||
|
||||
// static
|
||||
void XMLFileReader::charHandler(void *userData, const char *s, int len)
|
||||
{
|
||||
XMLFileReader *This = (XMLFileReader *)userData;
|
||||
|
||||
if (This->mHandler[This->mDepth])
|
||||
This->mHandler[This->mDepth]->ReadXMLContent(s, len);
|
||||
}
|
||||
|
||||
// Indentation settings for Vim and Emacs and unique identifier for Arch, a
|
||||
// version control system. Please do not modify past this point.
|
||||
//
|
||||
// Local Variables:
|
||||
// c-basic-offset: 3
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
//
|
||||
// vim: et sts=3 sw=3
|
||||
// arch-tag: 0a51946d-5a9f-46c9-92d9-ee09698a9bc3
|
||||
|
57
src/xml/XMLFileReader.h
Normal file
57
src/xml/XMLFileReader.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
XMLFileReader.h
|
||||
|
||||
Dominic Mazzoni
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#include "../Audacity.h" // to pull in USE_SYSTEM_EXPAT define
|
||||
|
||||
#include "expat.h"
|
||||
|
||||
#include "XMLTagHandler.h"
|
||||
|
||||
class XMLFileReader {
|
||||
public:
|
||||
XMLFileReader();
|
||||
virtual ~XMLFileReader();
|
||||
|
||||
bool Parse(XMLTagHandler *baseHandler,
|
||||
const wxString &fname);
|
||||
|
||||
wxString GetErrorStr();
|
||||
|
||||
// Callback functions for expat
|
||||
|
||||
static void startElement(void *userData, const char *name,
|
||||
const char **atts);
|
||||
|
||||
static void endElement(void *userData, const char *name);
|
||||
|
||||
static void charHandler(void *userData, const char *s, int len);
|
||||
|
||||
private:
|
||||
XML_Parser mParser;
|
||||
int mMaxDepth;
|
||||
int mDepth;
|
||||
XMLTagHandler **mHandler;
|
||||
XMLTagHandler *mBaseHandler;
|
||||
wxString mErrorStr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Indentation settings for Vim and Emacs and unique identifier for Arch, a
|
||||
// version control system. Please do not modify past this point.
|
||||
//
|
||||
// Local Variables:
|
||||
// c-basic-offset: 3
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
//
|
||||
// vim: et sts=3 sw=3
|
||||
// arch-tag: 367db03e-6d57-4749-928b-f690b8af3f4f
|
||||
|
203
src/xml/XMLTagHandler.cpp
Normal file
203
src/xml/XMLTagHandler.cpp
Normal file
@@ -0,0 +1,203 @@
|
||||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
XMLTagHandler.cpp
|
||||
|
||||
Dominic Mazzoni
|
||||
Vaughan Johnson
|
||||
|
||||
|
||||
*//****************************************************************//**
|
||||
|
||||
\class XMLTagHandler
|
||||
\brief This class is an interface which should be implemented by
|
||||
classes which wish to be able to load and save themselves
|
||||
using XML files.
|
||||
|
||||
\class XMLValueChecker
|
||||
\brief XMLValueChecker implements static bool methods for checking
|
||||
input values from XML files.
|
||||
|
||||
*//*******************************************************************/
|
||||
|
||||
#include "XMLTagHandler.h"
|
||||
|
||||
#include "../Audacity.h"
|
||||
#include "../Internat.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <wx/defs.h>
|
||||
#include <wx/arrstr.h>
|
||||
#include <wx/filename.h>
|
||||
|
||||
#include "../SampleFormat.h"
|
||||
#include "../Track.h"
|
||||
|
||||
bool XMLValueChecker::IsGoodString(const wxString str)
|
||||
{
|
||||
size_t len = str.Length();
|
||||
int nullIndex = str.Find('\0', false);
|
||||
if ((len < 2048) && // Shouldn't be any reason for longer strings, except intentional file corruption.
|
||||
(nullIndex == -1)) // No null characters except terminator.
|
||||
return true;
|
||||
else
|
||||
return false; // good place for a breakpoint
|
||||
}
|
||||
|
||||
// "Good" means the name is well-formed and names an existing file or folder.
|
||||
bool XMLValueChecker::IsGoodFileName(const wxString strFileName, const wxString strDirName /* = "" */)
|
||||
{
|
||||
// Test strFileName.
|
||||
if (!IsGoodFileString(strFileName))
|
||||
return false;
|
||||
|
||||
#ifdef _WIN32
|
||||
if (strFileName.Length() + 1 + strDirName.Length() > MAX_PATH)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
// Test the corresponding wxFileName.
|
||||
wxFileName fileName(strDirName, strFileName);
|
||||
return (fileName.IsOk() && fileName.FileExists());
|
||||
}
|
||||
|
||||
bool XMLValueChecker::IsGoodSubdirName(const wxString strSubdirName, const wxString strDirName /* = "" */)
|
||||
{
|
||||
// Test strSubdirName.
|
||||
// Note this prevents path separators, and relative path to parents (strDirName),
|
||||
// so fixes vulnerability #3 in the NGS report for UmixIt,
|
||||
// where an attacker could craft an AUP file with relative pathnames to get to system files, for example.
|
||||
if (!IsGoodFileString(strSubdirName) || (strSubdirName == wxT(".")) || (strSubdirName == wxT("..")))
|
||||
return false;
|
||||
|
||||
#ifdef _WIN32
|
||||
if (strSubdirName.Length() + 1 + strDirName.Length() > MAX_PATH)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
// Test the corresponding wxFileName.
|
||||
wxFileName fileName(strDirName, strSubdirName);
|
||||
return (fileName.IsOk() && fileName.DirExists());
|
||||
}
|
||||
|
||||
bool XMLValueChecker::IsGoodPathName(const wxString strPathName)
|
||||
{
|
||||
// Test the corresponding wxFileName.
|
||||
wxFileName fileName(strPathName);
|
||||
return XMLValueChecker::IsGoodFileName(fileName.GetFullName(), fileName.GetPath(wxPATH_GET_VOLUME));
|
||||
}
|
||||
|
||||
bool XMLValueChecker::IsGoodFileString(wxString str)
|
||||
{
|
||||
return (IsGoodString(str) &&
|
||||
!str.IsEmpty() &&
|
||||
(str.Length() <= 260) && // FILENAME_MAX is 260 in MSVC, but inconsistent across platforms, sometimes huge.
|
||||
(str.Find(wxFileName::GetPathSeparator()) == -1)); // No path separator characters. //vvv (this won't work on CVS HEAD)
|
||||
}
|
||||
|
||||
bool XMLValueChecker::IsGoodInt(const wxString strInt)
|
||||
{
|
||||
if (!IsGoodString(strInt))
|
||||
return false;
|
||||
|
||||
// Check that the value won't overflow.
|
||||
// Signed long: -2,147,483,648 to +2,147,483,647, i.e., -2^31 to 2^31-1
|
||||
// We're strict about disallowing spaces and commas, and requiring minus sign to be first char for negative.
|
||||
const size_t lenMAXABS = strlen("2147483647");
|
||||
const size_t lenStrInt = strInt.Length();
|
||||
|
||||
if (lenStrInt > (lenMAXABS + 1))
|
||||
return false;
|
||||
else if ((lenStrInt == (lenMAXABS + 1)) && (strInt[0] == '-'))
|
||||
{
|
||||
const int digitsMAXABS[] = {2, 1, 4, 7, 4, 8, 3, 6, 4, 9};
|
||||
unsigned int i;
|
||||
for (i = 0; i < lenMAXABS; i++)
|
||||
if (strInt[i+1] < '0' || strInt[i+1] > '9')
|
||||
return false; // not a digit
|
||||
|
||||
for (i = 0; i < lenMAXABS; i++)
|
||||
if (strInt[i+1] - '0' < digitsMAXABS[i])
|
||||
return true; // number is small enough
|
||||
return false;
|
||||
}
|
||||
else if (lenStrInt == lenMAXABS)
|
||||
{
|
||||
const int digitsMAXABS[] = {2, 1, 4, 7, 4, 8, 3, 6, 4, 8};
|
||||
unsigned int i;
|
||||
for (i = 0; i < lenMAXABS; i++)
|
||||
if (strInt[i] < '0' || strInt[i+1] > '9')
|
||||
return false; // not a digit
|
||||
for (i = 0; i < lenMAXABS; i++)
|
||||
if (strInt[i] - '0' < digitsMAXABS[i])
|
||||
return true; // number is small enough
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool XMLValueChecker::IsValidChannel(const int nValue)
|
||||
{
|
||||
return (nValue >= Track::LeftChannel) && (nValue <= Track::MonoChannel);
|
||||
}
|
||||
|
||||
bool XMLValueChecker::IsValidSampleFormat(const int nValue)
|
||||
{
|
||||
return (nValue == int16Sample) || (nValue == int24Sample) || (nValue == floatSample);
|
||||
}
|
||||
|
||||
bool XMLTagHandler::ReadXMLTag(const char *tag, const char **attrs)
|
||||
{
|
||||
wxArrayString tmp_attrs;
|
||||
|
||||
while (*attrs) {
|
||||
const char *s = *attrs++;
|
||||
tmp_attrs.Add(UTF8CTOWX(s));
|
||||
}
|
||||
|
||||
// JKC: Previously the next line was:
|
||||
// const char **out_attrs = new char (const char *)[tmp_attrs.GetCount()+1];
|
||||
// however MSVC doesn't like the constness in this position, so this is now
|
||||
// added by a cast after creating the array of pointers-to-non-const chars.
|
||||
const wxChar **out_attrs = (const wxChar**)new wxChar *[tmp_attrs.GetCount()+1];
|
||||
for (size_t i=0; i<tmp_attrs.GetCount(); i++) {
|
||||
out_attrs[i] = tmp_attrs[i].c_str();
|
||||
}
|
||||
out_attrs[tmp_attrs.GetCount()] = 0;
|
||||
|
||||
bool result = HandleXMLTag(UTF8CTOWX(tag).c_str(), out_attrs);
|
||||
|
||||
delete[] out_attrs;
|
||||
return result;
|
||||
}
|
||||
|
||||
void XMLTagHandler::ReadXMLEndTag(const char *tag)
|
||||
{
|
||||
HandleXMLEndTag(UTF8CTOWX(tag).c_str());
|
||||
}
|
||||
|
||||
void XMLTagHandler::ReadXMLContent(const char *s, int len)
|
||||
{
|
||||
HandleXMLContent(wxString(s, wxConvUTF8, len));
|
||||
}
|
||||
|
||||
XMLTagHandler *XMLTagHandler::ReadXMLChild(const char *tag)
|
||||
{
|
||||
return HandleXMLChild(UTF8CTOWX(tag).c_str());
|
||||
}
|
||||
|
||||
// Indentation settings for Vim and Emacs and unique identifier for Arch, a
|
||||
// version control system. Please do not modify past this point.
|
||||
//
|
||||
// Local Variables:
|
||||
// c-basic-offset: 3
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
//
|
||||
// vim: et sts=3 sw=3
|
||||
// arch-tag: 6aabae58-19bd-4b3a-aa6c-08432a7e106e
|
||||
|
100
src/xml/XMLTagHandler.h
Normal file
100
src/xml/XMLTagHandler.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
XMLTagHandler.h
|
||||
|
||||
Dominic Mazzoni
|
||||
Vaughan Johnson
|
||||
|
||||
The XMLTagHandler class is an interface which should be implemented by
|
||||
classes which wish to be able to load and save themselves
|
||||
using XML files.
|
||||
|
||||
The XMLValueChecker class implements static bool methods for checking
|
||||
input values from XML files.
|
||||
|
||||
**********************************************************************/
|
||||
#ifndef __AUDACITY_XML_TAG_HANDLER__
|
||||
#define __AUDACITY_XML_TAG_HANDLER__
|
||||
|
||||
#include "../Audacity.h"
|
||||
#include <wx/string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "XMLWriter.h"
|
||||
class XMLValueChecker
|
||||
{
|
||||
public:
|
||||
// "Good" means well-formed and for the file-related functions, names an existing file or folder.
|
||||
// These are used in HandleXMLTag and BuildFomXML methods to check the input for
|
||||
// security vulnerabilites, per the NGS report for UmixIt.
|
||||
static bool IsGoodString(const wxString str);
|
||||
|
||||
static bool IsGoodFileName(const wxString strFileName, const wxString strDirName = wxEmptyString);
|
||||
static bool IsGoodSubdirName(const wxString strSubdirName, const wxString strDirName = wxEmptyString);
|
||||
static bool IsGoodPathName(const wxString strPathName);
|
||||
|
||||
// Note that because wxString::ToLong does additional testing, IsGoodInt doesn't duplicate
|
||||
// that testing, so use wxString::ToLong after IsGoodInt, not just atoi.
|
||||
static bool IsGoodInt(const wxString strInt);
|
||||
|
||||
static bool IsValidChannel(const int nValue);
|
||||
static bool IsValidSampleFormat(const int nValue); // true if nValue is one sampleFormat enum values
|
||||
|
||||
static bool IsGoodFileString(wxString str);
|
||||
};
|
||||
|
||||
|
||||
class AUDACITY_DLL_API XMLTagHandler {
|
||||
public:
|
||||
XMLTagHandler(){};
|
||||
virtual ~XMLTagHandler(){};
|
||||
//
|
||||
// Methods to override
|
||||
//
|
||||
|
||||
// This method will be called on your class if your class has
|
||||
// been registered to handle this particular tag. Parse the
|
||||
// tag and the attribute-value pairs (null-terminated), and
|
||||
// return true on success, and false on failure. If you return
|
||||
// false, you will not get any calls about children.
|
||||
virtual bool HandleXMLTag(const wxChar *tag, const wxChar **attrs) = 0;
|
||||
|
||||
// This method will be called when a closing tag is encountered.
|
||||
// It is optional to override this method.
|
||||
virtual void HandleXMLEndTag(const wxChar *tag) {}
|
||||
|
||||
// This method will be called when element content has been
|
||||
// encountered.
|
||||
// It is optional to override this method.
|
||||
virtual void HandleXMLContent(const wxString & content) {}
|
||||
|
||||
// If the XML document has children of your tag, this method
|
||||
// should be called. Typically you should construct a new
|
||||
// object for the child, insert it into your own local data
|
||||
// structures, and then return it. If you do not wish to
|
||||
// handle this child, return NULL and it will be ignored.
|
||||
virtual XMLTagHandler *HandleXMLChild(const wxChar *tag) = 0;
|
||||
|
||||
// These functions recieve data from expat. They do charset
|
||||
// conversion and then pass the data to the handlers above.
|
||||
bool ReadXMLTag(const char *tag, const char **attrs);
|
||||
void ReadXMLEndTag(const char *tag);
|
||||
void ReadXMLContent(const char *s, int len);
|
||||
XMLTagHandler *ReadXMLChild(const char *tag);
|
||||
};
|
||||
|
||||
#endif // define __AUDACITY_XML_TAG_HANDLER__
|
||||
|
||||
// Indentation settings for Vim and Emacs and unique identifier for Arch, a
|
||||
// version control system. Please do not modify past this point.
|
||||
//
|
||||
// Local Variables:
|
||||
// c-basic-offset: 3
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
//
|
||||
// vim: et sts=3 sw=3
|
||||
// arch-tag: 7c9a9baa-c546-42de-afaa-d87e5e13bf5a
|
||||
|
369
src/xml/XMLWriter.cpp
Normal file
369
src/xml/XMLWriter.cpp
Normal file
@@ -0,0 +1,369 @@
|
||||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
XMLWriter.cpp
|
||||
|
||||
Leland Lucius
|
||||
|
||||
*******************************************************************//**
|
||||
|
||||
\class XMLWriter
|
||||
\brief Base class for XMLFileWriter and XMLStringWriter that provides
|
||||
the general functionality for creating XML in UTF8 encoding.
|
||||
|
||||
*//****************************************************************//**
|
||||
|
||||
\class XMLFileWriter
|
||||
\brief Wrapper to output XML data to files.
|
||||
|
||||
*//****************************************************************//**
|
||||
|
||||
\class XMLStringWriter
|
||||
\brief Wrapper to output XML data to strings.
|
||||
|
||||
*//*******************************************************************/
|
||||
|
||||
#include <wx/defs.h>
|
||||
#include <wx/ffile.h>
|
||||
#include <wx/intl.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "../Internat.h"
|
||||
#include "XMLWriter.h"
|
||||
#include "XMLTagHandler.h"
|
||||
|
||||
///
|
||||
/// XMLWriter base class
|
||||
///
|
||||
XMLWriter::XMLWriter()
|
||||
{
|
||||
mDepth = 0;
|
||||
mInTag = false;
|
||||
mHasKids.Add(false);
|
||||
}
|
||||
|
||||
XMLWriter::~XMLWriter()
|
||||
{
|
||||
}
|
||||
|
||||
void XMLWriter::StartTag(const wxString &name)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (mInTag) {
|
||||
Write(wxT(">\n"));
|
||||
mInTag = false;
|
||||
}
|
||||
|
||||
for (i = 0; i < mDepth; i++) {
|
||||
Write(wxT("\t"));
|
||||
}
|
||||
|
||||
Write(wxString::Format(wxT("<%s"), name.c_str()));
|
||||
|
||||
mTagstack.Insert(name, 0);
|
||||
mHasKids[0] = true;
|
||||
mHasKids.Insert(false, 0);
|
||||
mDepth++;
|
||||
mInTag = true;
|
||||
}
|
||||
|
||||
void XMLWriter::EndTag(const wxString &name)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (mTagstack.GetCount() > 0) {
|
||||
if (mTagstack[0] == name) {
|
||||
if (mHasKids[1]) { // There will always be at least 2 at this point
|
||||
if (mInTag) {
|
||||
Write(wxT("/>\n"));
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < mDepth - 1; i++) {
|
||||
Write(wxT("\t"));
|
||||
}
|
||||
Write(wxString::Format(wxT("</%s>\n"), name.c_str()));
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write(wxT(">\n"));
|
||||
}
|
||||
mTagstack.RemoveAt(0);
|
||||
mHasKids.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
mDepth--;
|
||||
mInTag = false;
|
||||
}
|
||||
|
||||
void XMLWriter::WriteAttr(const wxString &name, const wxString &value)
|
||||
{
|
||||
Write(wxString::Format(wxT(" %s=\"%s\""),
|
||||
name.c_str(),
|
||||
XMLEsc(value).c_str()));
|
||||
}
|
||||
|
||||
void XMLWriter::WriteAttr(const wxChar *name, const wxChar *value)
|
||||
{
|
||||
WriteAttr(wxString(name), wxString(value));
|
||||
}
|
||||
|
||||
void XMLWriter::WriteAttr(const wxString &name, const wxChar *value)
|
||||
{
|
||||
WriteAttr(name, wxString(value));
|
||||
}
|
||||
|
||||
void XMLWriter::WriteAttr(const wxChar *name, const wxString &value)
|
||||
{
|
||||
WriteAttr(wxString(name), value);
|
||||
}
|
||||
|
||||
void XMLWriter::WriteAttr(const wxString &name, int value)
|
||||
{
|
||||
Write(wxString::Format(wxT(" %s=\"%d\""),
|
||||
name.c_str(),
|
||||
value));
|
||||
}
|
||||
|
||||
void XMLWriter::WriteAttr(const wxChar *name, int value)
|
||||
{
|
||||
WriteAttr(wxString(name), value);
|
||||
}
|
||||
|
||||
void XMLWriter::WriteAttr(const wxString &name, bool value)
|
||||
{
|
||||
Write(wxString::Format(wxT(" %s=\"%d\""),
|
||||
name.c_str(),
|
||||
value));
|
||||
}
|
||||
|
||||
void XMLWriter::WriteAttr(const wxChar *name, bool value)
|
||||
{
|
||||
WriteAttr(wxString(name), value);
|
||||
}
|
||||
|
||||
void XMLWriter::WriteAttr(const wxString &name, long value)
|
||||
{
|
||||
Write(wxString::Format(wxT(" %s=\"%ld\""),
|
||||
name.c_str(),
|
||||
value));
|
||||
}
|
||||
|
||||
void XMLWriter::WriteAttr(const wxChar *name, long value)
|
||||
{
|
||||
WriteAttr(wxString(name), value);
|
||||
}
|
||||
|
||||
void XMLWriter::WriteAttr(const wxString &name, long long value)
|
||||
{
|
||||
Write(wxString::Format(wxT(" %s=\"%lld\""),
|
||||
name.c_str(),
|
||||
value));
|
||||
}
|
||||
|
||||
void XMLWriter::WriteAttr(const wxChar *name, long long value)
|
||||
{
|
||||
WriteAttr(wxString(name), value);
|
||||
}
|
||||
|
||||
void XMLWriter::WriteAttr(const wxString &name, size_t value)
|
||||
{
|
||||
Write(wxString::Format(wxT(" %s=\"%ld\""),
|
||||
name.c_str(),
|
||||
value));
|
||||
}
|
||||
|
||||
void XMLWriter::WriteAttr(const wxChar *name, size_t value)
|
||||
{
|
||||
WriteAttr(wxString(name), value);
|
||||
}
|
||||
|
||||
void XMLWriter::WriteAttr(const wxString &name, float value, int digits)
|
||||
{
|
||||
Write(wxString::Format(wxT(" %s=\"%s\""),
|
||||
name.c_str(),
|
||||
Internat::ToString(value, digits).c_str()));
|
||||
}
|
||||
|
||||
void XMLWriter::WriteAttr(const wxChar *name, float value, int digits)
|
||||
{
|
||||
WriteAttr(wxString(name), value, digits);
|
||||
}
|
||||
|
||||
void XMLWriter::WriteAttr(const wxString &name, double value, int digits)
|
||||
{
|
||||
Write(wxString::Format(wxT(" %s=\"%s\""),
|
||||
name.c_str(),
|
||||
Internat::ToString(value, digits).c_str()));
|
||||
}
|
||||
|
||||
void XMLWriter::WriteAttr(const wxChar *name, double value, int digits)
|
||||
{
|
||||
WriteAttr(wxString(name), value, digits);
|
||||
}
|
||||
|
||||
void XMLWriter::WriteData(const wxString &value)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < mDepth; i++) {
|
||||
Write(wxT("\t"));
|
||||
}
|
||||
|
||||
Write(XMLEsc(value));
|
||||
}
|
||||
|
||||
void XMLWriter::WriteData(const wxChar *value)
|
||||
{
|
||||
WriteData(wxString(value));
|
||||
}
|
||||
|
||||
void XMLWriter::WriteSubTree(const wxString &value)
|
||||
{
|
||||
if (mInTag) {
|
||||
Write(wxT(">\n"));
|
||||
mInTag = false;
|
||||
mHasKids[0] = true;
|
||||
}
|
||||
|
||||
Write(value.c_str());
|
||||
}
|
||||
|
||||
void XMLWriter::WriteSubTree(const wxChar *value)
|
||||
{
|
||||
WriteSubTree(wxString(value));
|
||||
}
|
||||
|
||||
void XMLWriter::Write(const wxChar *value)
|
||||
{
|
||||
Write(wxString(value));
|
||||
}
|
||||
|
||||
// See http://www.w3.org/TR/REC-xml for reference
|
||||
wxString XMLWriter::XMLEsc(const wxString & s)
|
||||
{
|
||||
wxString result;
|
||||
int len = s.Length();
|
||||
|
||||
for(int i=0; i<len; i++) {
|
||||
wxUChar c = s.GetChar(i);
|
||||
|
||||
switch (c) {
|
||||
case wxT('\''):
|
||||
result += wxT("'");
|
||||
break;
|
||||
|
||||
case wxT('"'):
|
||||
result += wxT(""");
|
||||
break;
|
||||
|
||||
case wxT('&'):
|
||||
result += wxT("&");
|
||||
break;
|
||||
|
||||
case wxT('<'):
|
||||
result += wxT("<");
|
||||
break;
|
||||
|
||||
case wxT('>'):
|
||||
result += wxT(">");
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!wxIsprint(c)) {
|
||||
result += wxString::Format(wxT("&#x%04x;"), c);
|
||||
}
|
||||
else {
|
||||
result += c;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
///
|
||||
/// XMLFileWriter class
|
||||
///
|
||||
XMLFileWriter::XMLFileWriter()
|
||||
{
|
||||
}
|
||||
|
||||
XMLFileWriter::~XMLFileWriter()
|
||||
{
|
||||
if (IsOpened()) {
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
void XMLFileWriter::Open(const wxString &name, const wxString &mode)
|
||||
{
|
||||
if (!wxFFile::Open(name, mode))
|
||||
throw new XMLFileWriterException(_("Error opening file"));
|
||||
}
|
||||
|
||||
void XMLFileWriter::Close()
|
||||
{
|
||||
while (mTagstack.GetCount()) {
|
||||
EndTag(mTagstack[0]);
|
||||
}
|
||||
|
||||
CloseWithoutEndingTags();
|
||||
}
|
||||
|
||||
void XMLFileWriter::CloseWithoutEndingTags()
|
||||
{
|
||||
// Before closing, we first flush it, because if Flush() fails because of a
|
||||
// "disk full" condition, we can still at least try to close the file.
|
||||
if (!wxFFile::Flush())
|
||||
{
|
||||
wxFFile::Close();
|
||||
throw new XMLFileWriterException(_("Error flushing file"));
|
||||
}
|
||||
|
||||
// Note that this should never fail if flushing worked.
|
||||
if (!wxFFile::Close())
|
||||
throw new XMLFileWriterException(_("Error closing file"));
|
||||
}
|
||||
|
||||
void XMLFileWriter::Write(const wxString &data)
|
||||
{
|
||||
if (!wxFFile::Write(data, wxConvUTF8))
|
||||
{
|
||||
// When writing fails, we try to close the file before throwing the
|
||||
// exception, so it can at least be deleted.
|
||||
wxFFile::Close();
|
||||
throw new XMLFileWriterException(_("Error writing to file"));
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// XMLStringWriter class
|
||||
///
|
||||
XMLStringWriter::XMLStringWriter()
|
||||
{
|
||||
}
|
||||
|
||||
XMLStringWriter::~XMLStringWriter()
|
||||
{
|
||||
}
|
||||
|
||||
void XMLStringWriter::Write(const wxString &data)
|
||||
{
|
||||
Append(data);
|
||||
}
|
||||
|
||||
// Indentation settings for Vim and Emacs and unique identifier for Arch, a
|
||||
// version control system. Please do not modify past this point.
|
||||
//
|
||||
// Local Variables:
|
||||
// c-basic-offset: 3
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
//
|
||||
// vim: et sts=3 sw=3
|
||||
// arch-tag: 391b08e6-61f4-43ea-8431-c835c31ba86d
|
141
src/xml/XMLWriter.h
Normal file
141
src/xml/XMLWriter.h
Normal file
@@ -0,0 +1,141 @@
|
||||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
XMLWriter.h
|
||||
|
||||
Leland Lucius
|
||||
|
||||
**********************************************************************/
|
||||
#ifndef __AUDACITY_XML_XML_FILE_WRITER__
|
||||
#define __AUDACITY_XML_XML_FILE_WRITER__
|
||||
|
||||
#include <wx/ffile.h>
|
||||
#include <wx/dynarray.h>
|
||||
|
||||
///
|
||||
/// XMLWriter
|
||||
///
|
||||
class XMLWriter {
|
||||
|
||||
public:
|
||||
|
||||
XMLWriter();
|
||||
virtual ~XMLWriter();
|
||||
|
||||
void StartTag(const wxString &name);
|
||||
void EndTag(const wxString &name);
|
||||
|
||||
void WriteAttr(const wxString &name, const wxString &value);
|
||||
void WriteAttr(const wxChar *name, const wxChar *value);
|
||||
void WriteAttr(const wxString &name, const wxChar *value);
|
||||
void WriteAttr(const wxChar *name, const wxString &value);
|
||||
|
||||
void WriteAttr(const wxString &name, int value);
|
||||
void WriteAttr(const wxChar *name, int value);
|
||||
void WriteAttr(const wxString &name, bool value);
|
||||
void WriteAttr(const wxChar *name, bool value);
|
||||
void WriteAttr(const wxString &name, long value);
|
||||
void WriteAttr(const wxChar *name, long value);
|
||||
void WriteAttr(const wxString &name, long long value);
|
||||
void WriteAttr(const wxChar *name, long long value);
|
||||
void WriteAttr(const wxString &name, size_t value);
|
||||
void WriteAttr(const wxChar *name, size_t value);
|
||||
void WriteAttr(const wxString &name, float value, int digits = -1);
|
||||
void WriteAttr(const wxChar *name, float value, int digits = -1);
|
||||
void WriteAttr(const wxString &name, double value, int digits = -1);
|
||||
void WriteAttr(const wxChar *name, double value, int digits = -1);
|
||||
|
||||
void WriteData(const wxString &value);
|
||||
void WriteData(const wxChar *value);
|
||||
|
||||
void WriteSubTree(const wxString &value);
|
||||
void WriteSubTree(const wxChar *value);
|
||||
|
||||
void Write(const wxChar *data);
|
||||
|
||||
virtual void Write(const wxString &data) = 0;
|
||||
|
||||
// Escape a string, replacing certain characters with their
|
||||
// XML encoding, i.e. '<' becomes '<'
|
||||
wxString XMLEsc(const wxString & s);
|
||||
|
||||
protected:
|
||||
|
||||
bool mInTag;
|
||||
int mDepth;
|
||||
wxArrayString mTagstack;
|
||||
wxArrayInt mHasKids;
|
||||
|
||||
};
|
||||
|
||||
///
|
||||
/// XMLFileWriter
|
||||
///
|
||||
class XMLFileWriter:public wxFFile, public XMLWriter {
|
||||
|
||||
public:
|
||||
|
||||
XMLFileWriter();
|
||||
virtual ~XMLFileWriter();
|
||||
|
||||
/// Open the file. Might throw XMLFileWriterException.
|
||||
void Open(const wxString &name, const wxString &mode);
|
||||
|
||||
/// Close file. Might throw XMLFileWriterException.
|
||||
void Close();
|
||||
|
||||
/// Close file without automatically ending tags.
|
||||
/// Might throw XMLFileWriterException.
|
||||
void CloseWithoutEndingTags(); // for auto-save files
|
||||
|
||||
/// Write to file. Might throw XMLFileWriterException.
|
||||
void Write(const wxString &data);
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
///
|
||||
/// Exception thrown by various XMLFileWriter methods
|
||||
///
|
||||
class XMLFileWriterException
|
||||
{
|
||||
public:
|
||||
XMLFileWriterException(const wxString& message) { mMessage = message; }
|
||||
wxString GetMessage() const { return mMessage; }
|
||||
|
||||
protected:
|
||||
wxString mMessage;
|
||||
};
|
||||
|
||||
///
|
||||
/// XMLStringWriter
|
||||
///
|
||||
class XMLStringWriter:public wxString, public XMLWriter {
|
||||
|
||||
public:
|
||||
|
||||
XMLStringWriter();
|
||||
virtual ~XMLStringWriter();
|
||||
|
||||
void Write(const wxString &data);
|
||||
|
||||
wxString Get();
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// Indentation settings for Vim and Emacs and unique identifier for Arch, a
|
||||
// version control system. Please do not modify past this point.
|
||||
//
|
||||
// Local Variables:
|
||||
// c-basic-offset: 3
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
//
|
||||
// vim: et sts=3 sw=3
|
||||
// arch-tag: 391b08e6-61f4-43ea-8431-c835c31ba86d
|
92
src/xml/audacityproject.dtd
Normal file
92
src/xml/audacityproject.dtd
Normal file
@@ -0,0 +1,92 @@
|
||||
<!--DTD for Audacity Project files, as created by Audacity version 1.3.0 -->
|
||||
<!--For more information: http://audacity.sourceforge.net/xml/ -->
|
||||
|
||||
<!ELEMENT project (tags, (wavetrack | labeltrack | timetrack)*)>
|
||||
<!ATTLIST project projname CDATA #REQUIRED>
|
||||
<!ATTLIST project version CDATA #REQUIRED>
|
||||
<!ATTLIST project audacityversion CDATA #REQUIRED>
|
||||
<!ATTLIST project sel0 CDATA #REQUIRED>
|
||||
<!ATTLIST project sel1 CDATA #REQUIRED>
|
||||
<!ATTLIST project vpos CDATA #REQUIRED>
|
||||
<!ATTLIST project h CDATA #REQUIRED>
|
||||
<!ATTLIST project zoom CDATA #REQUIRED>
|
||||
<!ATTLIST project rate CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT tags EMPTY>
|
||||
<!ATTLIST tags title CDATA #REQUIRED>
|
||||
<!ATTLIST tags artist CDATA #REQUIRED>
|
||||
<!ATTLIST tags album CDATA #REQUIRED>
|
||||
<!ATTLIST tags track CDATA #REQUIRED>
|
||||
<!ATTLIST tags year CDATA #REQUIRED>
|
||||
<!ATTLIST tags genre CDATA #REQUIRED>
|
||||
<!ATTLIST tags comments CDATA #REQUIRED>
|
||||
<!ATTLIST tags id3v2 (0|1) #REQUIRED>
|
||||
|
||||
<!ELEMENT labeltrack (label*)>
|
||||
<!ATTLIST labeltrack name CDATA #REQUIRED>
|
||||
<!ATTLIST labeltrack numlabels CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT label EMPTY>
|
||||
<!ATTLIST label t CDATA #REQUIRED>
|
||||
<!ATTLIST label t1 CDATA #REQUIRED>
|
||||
<!ATTLIST label title CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT timetrack (envelope)>
|
||||
<!ATTLIST timetrack name CDATA #REQUIRED>
|
||||
<!ATTLIST timetrack channel CDATA #REQUIRED>
|
||||
<!ATTLIST timetrack offset CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT wavetrack (waveclip*)>
|
||||
<!ATTLIST wavetrack name CDATA #REQUIRED>
|
||||
<!ATTLIST wavetrack channel CDATA #REQUIRED>
|
||||
<!ATTLIST wavetrack linked CDATA #REQUIRED>
|
||||
<!ATTLIST wavetrack offset CDATA #REQUIRED>
|
||||
<!ATTLIST wavetrack rate CDATA #REQUIRED>
|
||||
<!ATTLIST wavetrack gain CDATA #REQUIRED>
|
||||
<!ATTLIST wavetrack pan CDATA #REQUIRED>
|
||||
<!ATTLIST wavetrack mute CDATA "0">
|
||||
<!ATTLIST wavetrack solo CDATA "0">
|
||||
|
||||
<!ELEMENT waveclip (sequence, envelope)>
|
||||
<!ATTLIST waveclip offset CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT sequence (waveblock*)>
|
||||
<!ATTLIST sequence maxsamples CDATA #REQUIRED>
|
||||
<!ATTLIST sequence sampleformat CDATA #REQUIRED>
|
||||
<!ATTLIST sequence numsamples CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT waveblock (simpleblockfile | silentblockfile | legacyblockfile | pcmaliasblockfile)>
|
||||
<!ATTLIST waveblock start CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT simpleblockfile EMPTY>
|
||||
<!ATTLIST simpleblockfile filename CDATA #REQUIRED>
|
||||
<!ATTLIST simpleblockfile len CDATA #REQUIRED>
|
||||
<!ATTLIST simpleblockfile min CDATA #REQUIRED>
|
||||
<!ATTLIST simpleblockfile max CDATA #REQUIRED>
|
||||
<!ATTLIST simpleblockfile rms CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT silentblockfile EMPTY>
|
||||
<!ATTLIST silentblockfile len CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT legacyblockfile EMPTY>
|
||||
<!ATTLIST legacyblockfile name CDATA #REQUIRED>
|
||||
<!ATTLIST legacyblockfile len CDATA #REQUIRED>
|
||||
<!ATTLIST legacyblockfile summarylen CDATA #REQUIRED>
|
||||
<!ATTLIST legacyblockfile norms CDATA "0">
|
||||
|
||||
<!ELEMENT pcmaliasblockfile EMPTY>
|
||||
<!ATTLIST pcmaliasblockfile summaryfile CDATA #REQUIRED>
|
||||
<!ATTLIST pcmaliasblockfile aliasfile CDATA #REQUIRED>
|
||||
<!ATTLIST pcmaliasblockfile aliasstart CDATA #REQUIRED>
|
||||
<!ATTLIST pcmaliasblockfile aliaslen CDATA #REQUIRED>
|
||||
<!ATTLIST pcmaliasblockfile aliaschannel CDATA #REQUIRED>
|
||||
<!ATTLIST pcmaliasblockfile min CDATA #REQUIRED>
|
||||
<!ATTLIST pcmaliasblockfile max CDATA #REQUIRED>
|
||||
<!ATTLIST pcmaliasblockfile rms CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT envelope (controlpoint*)>
|
||||
<!ATTLIST envelope numpoints CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT controlpoint EMPTY>
|
||||
<!ATTLIST controlpoint t CDATA #REQUIRED>
|
||||
<!ATTLIST controlpoint val CDATA #REQUIRED>
|
Reference in New Issue
Block a user