XData Util::parseXData(const XmlElement& el) { xmpp_stanza_t* elPtr {el.getStanzaPtr()}; xmpp_stanza_t* field {xmpp_stanza_get_children(elPtr)}; std::string type {makeString(xmpp_stanza_get_type(elPtr))}; XData ret {type}; while(field) { if(makeString(xmpp_stanza_get_name(field)) == "field") { std::string fieldType {makeString(xmpp_stanza_get_type(field))}; std::string var {makeString(xmpp_stanza_get_attribute(field, "var"))}; std::vector<std::string> values; xmpp_stanza_t* value {xmpp_stanza_get_children(field)}; while(value) { if(makeString(xmpp_stanza_get_name(value)) == "value") { char* text {xmpp_stanza_get_text(value)}; values.emplace_back(makeString(text)); xmpp_free(value->ctx, text); } value = xmpp_stanza_get_next(value); } XData::Field newField {fieldType, var, values}; if(not newField.isValid()) { throw std::runtime_error {""}; } ret.addField(newField); } field = xmpp_stanza_get_next(field); } return ret; }
void HttpFileUpload::start() { if (d->state != State::None) // Attempt to start twice? return; setState(State::GettingSlot); d->result.statusCode = HttpFileUpload::ErrorCode::NoError; static QList<QSet<QString>> featureOptions; if (featureOptions.isEmpty()) { featureOptions << (QSet<QString>() << xmlns_v0_2_5) << (QSet<QString>() << xmlns_v0_3_1); } d->client->serverInfoManager()->queryServiceInfo( QLatin1String("store"), QLatin1String("file"), featureOptions, QRegExp("^(upload|http|stor|file|dis|drive).*"), ServerInfoManager::SQ_CheckAllOnNoMatch, [this](const QList<DiscoItem> &items) { d->httpHosts.clear(); for (const auto &item: items) { const QStringList &l = item.features().list(); XEP0363::version ver = XEP0363::vUnknown; QString xmlns; quint64 sizeLimit = 0; if (l.contains(xmlns_v0_3_1)) { ver = XEP0363::v0_3_1; xmlns = xmlns_v0_3_1; } else if (l.contains(xmlns_v0_2_5)) { ver = XEP0363::v0_2_5; xmlns = xmlns_v0_2_5; } if (ver != XEP0363::vUnknown) { QList<std::pair<HttpHost,int>> hosts; const XData::Field field = item.registeredExtension(xmlns).getField(QLatin1String("max-file-size")); if (field.isValid() && field.type() == XData::Field::Field_TextSingle) sizeLimit = field.value().at(0).toULongLong(); HttpHost host; host.ver = ver; host.jid = item.jid(); host.sizeLimit = sizeLimit; QVariant metaProps(d->client->serverInfoManager()->serviceMeta(host.jid, "httpprops")); if (metaProps.isValid()) { host.props = HostProps(metaProps.value<int>()); } else { host.props = SecureGet | SecurePut; if (ver == XEP0363::v0_3_1) host.props |= NewestVer; } int value = 0; if (host.props & SecureGet) value += 5; if (host.props & SecurePut) value += 5; if (host.props & NewestVer) value += 3; if (host.props & Failure) value -= 15; if (!sizeLimit || d->fileSize < sizeLimit) hosts.append({host,value}); // no sorting in preference order. most preferred go first std::sort(hosts.begin(), hosts.end(), [](const auto &a, const auto &b){ return a.second > b.second; }); for (auto &hp: hosts) { d->httpHosts.append(hp.first); } } } //d->currentHost = d->httpHosts.begin(); if (d->httpHosts.isEmpty()) { // if empty as the last resort check all services d->result.statusCode = HttpFileUpload::ErrorCode::NoUploadService; d->result.statusString = "No suitable http upload services were found"; done(State::Error); } else { tryNextServer(); } }); }