Esempio n. 1
0
string::size_type SimpleXMLReader::loadAttribs(const string& name, const string& tmp, string::size_type start) throw(SimpleXMLException) {
	string::size_type i = start;
	string::size_type j;

	for(;;) {
		if((j = tmp.find('=', i)) == string::npos) {
			throw SimpleXMLException("Missing '=' in " + name);
		}

		if(tmp[j+1] != '"' && tmp[j+1] != '\'') {
			throw SimpleXMLException("Invalid character after '=' in " + name);
		}

		string::size_type x = j + 2;
		string::size_type y;
		if((y = tmp.find(tmp[j+1], x)) == string::npos) {
			throw SimpleXMLException("Missing '" + string(1, tmp[j+1]) + "' in " + name);
		}
		// Ok, we have an attribute...
		attribs.push_back(make_pair(tmp.substr(i, j-i), tmp.substr(x, y-x)));
		SimpleXML::escape(attribs.back().second, true, true, utf8);

		i = tmp.find_first_not_of(' ', y + 1);
		if(tmp[i] == '/' || tmp[i] == '>') {
			return i;
		}
	}
}
Esempio n. 2
0
void SimpleXML::addTag(const string& aName, const string& aData /* = "" */) {
    if(aName.empty()) {
        throw SimpleXMLException("Empty tag names not allowed");
    }

    if(current == &root && !current->children.empty()) {
        throw SimpleXMLException("Only one root tag allowed");
    } else {
        current->children.push_back(new Tag(aName, aData, current));
        currentChild = current->children.end() - 1;
    }
}
Esempio n. 3
0
void SimpleXML::fromXML(const string& aXML) {
    if(!root.children.empty()) {
        delete root.children[0];
        root.children.clear();
    }

    TagReader t(&root);
        SimpleXMLReader(&t).parse(aXML.c_str(), aXML.size(), false);

    if(root.children.size() != 1) {
        throw SimpleXMLException("Invalid XML file, missing or multiple root tags");
    }

    current = &root;
    resetCurrentChild();
}
void ListLoader::startTag(const string& name, StringPairList& attribs, bool simple) {
    if(inListing) {
        if(name == sFile) {
            const string& n = getAttrib(attribs, sName, 0);
            if(n.empty())
                return;
            const string& s = getAttrib(attribs, sSize, 1);
            if(s.empty())
                return;
            int64_t size = Util::toInt64(s);
            const string& h = getAttrib(attribs, sTTH, 2);
            if(h.empty())
                return;
             TTHValue tth(h); /// @todo verify validity?

            if(updating) {
                // just update the current file if it is already there.
                for(DirectoryListing::File::Iter i = cur->files.begin(), iend = cur->files.end(); i != iend; ++i) {
                    DirectoryListing::File& file = **i;
                    /// @todo comparisons should be case-insensitive but it takes too long - add a cache
                    if(file.getTTH() == tth || file.getName() == n) {
                        file.setName(n);
                        file.setSize(size);
                        file.setTTH(tth);
                        return;
                    }
                }
            }
            
            DirectoryListing::File* f = new DirectoryListing::File(cur, n, size, tth);
            
            string l_ts = "";
            
            if (!m_is_first_check_mediainfo_list){
                m_is_first_check_mediainfo_list = true;
                l_ts = getAttrib(attribs, sTS, 3);
                m_is_mediainfo_list = !l_ts.empty();
            }
            else if (m_is_mediainfo_list) {
                l_ts = getAttrib(attribs, sTS, 3);
            }
            
            if (!l_ts.empty()){
                f->mediaInfo.video_info = getAttrib(attribs, sMVideo, 3);
                f->mediaInfo.audio_info = getAttrib(attribs, sMAudio, 3);
                f->mediaInfo.resolution = getAttrib(attribs, sWH, 3);
                f->mediaInfo.bitrate    = atoi(getAttrib(attribs, sBR, 4).c_str());
            }
            
            cur->files.push_back(f);
        } else if(name == sDirectory) {
            const string& n = getAttrib(attribs, sName, 0);
            if(n.empty()) {
                throw SimpleXMLException(_("Directory missing name attribute"));
            }
            bool incomp = getAttrib(attribs, sIncomplete, 1) == "1";
            DirectoryListing::Directory* d = NULL;
            if(updating) {
                for(DirectoryListing::Directory::Iter i = cur->directories.begin(); i != cur->directories.end(); ++i) {
                    /// @todo comparisons should be case-insensitive but it takes too long - add a cache
                    if((*i)->getName() == n) {
                        d = *i;
                        if(!d->getComplete())
                            d->setComplete(!incomp);
                        break;
                    }
                }
            }
            if(d == NULL) {
                d = new DirectoryListing::Directory(cur, n, false, !incomp);
                cur->directories.push_back(d);
            }
            cur = d;

            if(simple) {
                // To handle <Directory Name="..." />
                endTag(name, Util::emptyString);
            }
        }
    } else if(name == sFileListing) {
        const string& b = getAttrib(attribs, sBase, 2);
        if(!b.empty() && b[0] == '/' && b[b.size()-1] == '/') {
            base = b;
        }
        StringList sl = StringTokenizer<string>(base.substr(1), '/').getTokens();
        for(StringIter i = sl.begin(); i != sl.end(); ++i) {
            DirectoryListing::Directory* d = NULL;
            for(DirectoryListing::Directory::Iter j = cur->directories.begin(); j != cur->directories.end(); ++j) {
                if((*j)->getName() == *i) {
                    d = *j;
                    break;
                }
            }
            if(d == NULL) {
                d = new DirectoryListing::Directory(cur, *i, false, false);
                cur->directories.push_back(d);
            }
            cur = d;
        }
        cur->setComplete(true);
        inListing = true;

        if(simple) {
            // To handle <Directory Name="..." />
            endTag(name, Util::emptyString);
        }
    }
}
Esempio n. 5
0
void SimpleXML::addAttrib(const string& aName, const string& aData) {
    if(current == &root)
        throw SimpleXMLException("No tag is currently selected");

    current->attribs.push_back(make_pair(aName, aData));
}
Esempio n. 6
0
string::size_type SimpleXMLReader::fromXML(const string& tmp, const string& n, string::size_type start, bool inTag) throw(SimpleXMLException) {
	string::size_type i = start;
	string::size_type j;

	bool hasChildren = false;

	for(;;) {
		if((j = tmp.find('<', i)) == string::npos) {
			if(inTag) {
				throw SimpleXMLException("Missing end tag in " + n);
			}
			return tmp.size();
		}

		// Check that we have at least 3 more characters as the shortest valid xml tag is <a/>...
		if((j + 3) > tmp.size()) {
			throw SimpleXMLException("Missing end tag in " + n);
		}

		i = j + 1;

		if(tmp[i] == '?') {
			// <? processing instruction ?>, check encoding...
			if((j = tmp.find("?>", i)) == string::npos) {
				throw SimpleXMLException("Missing '?>' in " + n);
			}

			string str = tmp.substr(i, j - i);
			if(str.find("encoding=\"utf-8\"") == string::npos) {
				// Ugly pass to convert from some other codepage to utf-8; note that we convert from the ACP, not the one specified in the xml...
				utf8 = false;
			}

			i = j + 2;
			continue;
		}

		if(tmp[i] == '!' && tmp[i+1] == '-' && tmp[i+2] == '-') {
			// <!-- comment -->, ignore...
			if((j = tmp.find("-->", i)) == string::npos) {
				throw SimpleXMLException("Missing '-->' in " + n);
			}
			i = j + 3;
			continue;
		}

		// Check if we reached the end tag
		if(tmp[i] == '/') {
			i++;
			
			if( (tmp.compare(i, n.length(), n) == 0) && 
				(tmp[i + n.length()] == '>') )
			{
				if(!hasChildren) {
					data = tmp.substr(start, i - start - 2);
					SimpleXML::escape(data, false, true, utf8);
				} else {
					data.clear();
				}
				return i + n.length() + 1;
			} else {
				throw SimpleXMLException("Missing end tag in " + n);
			}
		}

		// Alright, we have a real tag for sure...now get the name of it.
		if((j = tmp.find_first_of(" />", i)) == string::npos) {
			throw SimpleXMLException("Missing '>' in " + n);
		}

		string name = tmp.substr(i, j-i);
		hasChildren = true;
		if(tmp[j] == ' ') {
			if((j = tmp.find_first_not_of(' ', j+1)) == string::npos) {
				throw SimpleXMLException("Missing '>' in " + name);
			}
		}		

		attribs.clear();
		if(tmp[j] != '/' && tmp[j] != '>') {
			// We have attribs...
			j = loadAttribs(name, tmp, j);
		}

		if(tmp[j] == '>') {
			// This is a real tag with data etc...
			cb->startTag(name, attribs, false);
			j = fromXML(tmp, name, j+1, true);
			cb->endTag(name, data);
		} else {
			// A simple tag (<xxx/>
			cb->startTag(name, attribs, true);
			j++;
		}
		i = j;
	}	
}
void ListLoader::startTag(const string& name, StringPairList& attribs, bool simple) {
	if(list->getAbort()) {
		throw AbortException();
	}

	if(inListing) {
		if(name == sFile) {
			const string& n = getAttrib(attribs, sName, 0);
			if(n.empty())
				return;
			const string& s = getAttrib(attribs, sSize, 1);
			if(s.empty())
				return;
			const string& h = getAttrib(attribs, sTTH, 2);
			if(h.empty()) {
				return;
			}
			DirectoryListing::File* f = new DirectoryListing::File(cur, n, Util::toInt64(s), h);
			cur->files.push_back(f);
		} else if(name == sDirectory) {
			const string& n = getAttrib(attribs, sName, 0);
			if(n.empty()) {
				throw SimpleXMLException("Directory missing name attribute");
			}
			bool incomp = getAttrib(attribs, sIncomplete, 1) == "1";
			DirectoryListing::Directory* d = NULL;
			if(updating) {
				for(DirectoryListing::Directory::Iter i = cur->directories.begin(); i != cur->directories.end(); ++i) {
					if((*i)->getName() == n) {
						d = *i;
						if(!d->getComplete())
							d->setComplete(!incomp);
						break;
					}
				}
			}
			if(d == NULL) {
				d = new DirectoryListing::Directory(cur, n, false, !incomp);
				cur->directories.push_back(d);
			}
			cur = d;

			if(simple) {
				// To handle <Directory Name="..." />
				endTag(name, Util::emptyString);
			}
		}
	} else if(name == sFileListing) {
		const string& b = getAttrib(attribs, sBase, 2);
		if(b.size() >= 1 && b[0] == '/' && b[b.size()-1] == '/') {
			base = b;
		}
		StringList sl = StringTokenizer<string>(base.substr(1), '/').getTokens();
		for(StringIter i = sl.begin(); i != sl.end(); ++i) {
			DirectoryListing::Directory* d = NULL;
			for(DirectoryListing::Directory::Iter j = cur->directories.begin(); j != cur->directories.end(); ++j) {
				if((*j)->getName() == *i) {
					d = *j;
					break;
				}
			}
			if(d == NULL) {
				d = new DirectoryListing::Directory(cur, *i, false, false);
				cur->directories.push_back(d);
			}
			cur = d;
		}
		cur->setComplete(true);
		inListing = true;

		if(simple) {
			// To handle <Directory Name="..." />
			endTag(name, Util::emptyString);
		}
	}
}