bool SystemFactory::isVersionNewer(const QString& new_version, const QString& base_version) { QStringList base_version_tkn = base_version.split(QL1C('.')); QStringList new_version_tkn = new_version.split(QL1C('.')); while (!base_version_tkn.isEmpty() && !new_version_tkn.isEmpty()) { const int base_number = base_version_tkn.takeFirst().toInt(); const int new_number = new_version_tkn.takeFirst().toInt(); if (new_number > base_number) { // New version is indeed higher thatn current version. return true; } else if (new_number < base_number) { return false; } } // Versions are either the same or they have unequal sizes. if (base_version_tkn.isEmpty() && new_version_tkn.isEmpty()) { // Versions are the same. return false; } else { if (new_version_tkn.isEmpty()) { return false; } else { return new_version_tkn.join(QString()).toInt() > 0; } } }
AdBlockRuleFallbackImpl::AdBlockRuleFallbackImpl(const QString &filter) : AdBlockRuleImpl(filter) { m_regExp.setCaseSensitivity(Qt::CaseInsensitive); m_regExp.setPatternSyntax(QRegExp::RegExp2); QString parsedLine = filter; const int optionsNumber = parsedLine.lastIndexOf(QL1C('$')); if (optionsNumber >= 0 && !isRegExpFilter(parsedLine)) { const QStringList options(parsedLine.mid(optionsNumber + 1).split(QL1C(','))); parsedLine = parsedLine.left(optionsNumber); if (options.contains(QL1S("match-case"))) m_regExp.setCaseSensitivity(Qt::CaseSensitive); foreach (const QString &option, options) { // Domain restricted filter const QString domainKeyword(QL1S("domain=")); if (option.startsWith(domainKeyword)) { QStringList domainList = option.mid(domainKeyword.length()).split(QL1C('|')); foreach (const QString &domain, domainList) { if (domain.startsWith(QL1C('~'))) m_whiteDomains.insert(domain.toLower()); else m_blackDomains.insert(domain.toLower()); } } } }
void HistoryManager::updateHistoryEntry(const KUrl &url, const QString &title) { QString urlString = url.url(); urlString.remove(QL1S("www.")); if(urlString.startsWith(QL1S("http")) && urlString.endsWith(QL1C('/'))) urlString.remove(urlString.length()-1,1); for (int i = 0; i < m_history.count(); ++i) { QString itemUrl = m_history.at(i).url; itemUrl.remove(QL1S("www.")); if(itemUrl.startsWith(QL1S("http")) && itemUrl.endsWith(QL1C('/'))) itemUrl.remove(itemUrl.length()-1,1); if (urlString == itemUrl) { m_history[i].title = title; m_history[i].url = url.url(); m_saveTimer->changeOccurred(); if (m_lastSavedUrl.isEmpty()) m_lastSavedUrl = m_history.at(i).url; emit entryUpdated(i); break; } } }
bool LocalDomainUriFilter::filterUri(KUriFilterData& data) const { const QUrl url = data.uri(); const QString protocol = url.scheme(); // When checking for local domain just validate it is indeed a local domain, // but do not modify the hostname! See bug# if ((protocol.isEmpty() || !KProtocolInfo::isKnownProtocol(protocol)) && m_hostPortPattern.exactMatch(data.typedString())) { QString host (data.typedString().left(data.typedString().indexOf(QL1C('/')))); const int pos = host.indexOf(QL1C(':')); if (pos > -1) host.truncate(pos); // Remove port number if (exists(host)) { QString scheme (data.defaultUrlScheme()); if (scheme.isEmpty()) scheme = QL1S("http://"); setFilteredUri(data, QUrl(scheme + data.typedString())); setUriType(data, KUriFilterData::NetProtocol); return true; } } return false; }
// NOTE // These 2 functions have been copied from the KWebPage class to implement a local version of the downloadResponse method. // In this way, we can easily provide the extra functionality we need: // 1. KGet Integration // 2. Save downloads history static void extractSuggestedFileName(const QNetworkReply* reply, QString& fileName) { fileName.clear(); const KIO::MetaData& metaData = reply->attribute(static_cast<QNetworkRequest::Attribute>(KIO::AccessManager::MetaData)).toMap(); if (metaData.value(QL1S("content-disposition-type")).compare(QL1S("attachment"), Qt::CaseInsensitive) == 0) fileName = metaData.value(QL1S("content-disposition-filename")); if (!fileName.isEmpty()) return; if (!reply->hasRawHeader("Content-Disposition")) return; const QString value(QL1S(reply->rawHeader("Content-Disposition").simplified().constData())); if (value.startsWith(QL1S("attachment"), Qt::CaseInsensitive) || value.startsWith(QL1S("inline"), Qt::CaseInsensitive)) { const int length = value.size(); int pos = value.indexOf(QL1S("filename"), 0, Qt::CaseInsensitive); if (pos > -1) { pos += 9; while (pos < length && (value.at(pos) == QL1C(' ') || value.at(pos) == QL1C('=') || value.at(pos) == QL1C('"'))) pos++; int endPos = pos; while (endPos < length && value.at(endPos) != QL1C('"') && value.at(endPos) != QL1C(';')) endPos++; if (endPos > pos) fileName = value.mid(pos, (endPos - pos)).trimmed(); } } }
bool SystemFactory::setAutoStartStatus(AutoStartStatus new_status) { const SystemFactory::AutoStartStatus current_status = SystemFactory::autoStartStatus(); // Auto-start feature is not even available, exit. if (current_status == AutoStartStatus::Unavailable) { return false; } #if defined(Q_OS_WIN) QSettings registry_key(QSL("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"), QSettings::NativeFormat); switch (new_status) { case AutoStartStatus::Enabled: registry_key.setValue(APP_LOW_NAME, Application::applicationFilePath().replace(QL1C('/'), QL1C('\\'))); return true; case AutoStartStatus::Disabled: registry_key.remove(APP_LOW_NAME); return true; default: return false; } #elif defined(Q_OS_LINUX) // Note that we expect here that no other program uses // "rssguard.desktop" desktop file. const QString destination_file = autostartDesktopFileLocation(); const QString destination_folder = QFileInfo(destination_file).absolutePath(); switch (new_status) { case AutoStartStatus::Enabled: { if (QFile::exists(destination_file)) { if (!QFile::remove(destination_file)) { return false; } } if (!QDir().mkpath(destination_folder)) { return false; } const QString source_autostart_desktop_file = QString(APP_DESKTOP_ENTRY_PATH) + QDir::separator() + APP_DESKTOP_SOURCE_ENTRY_FILE; return QFile::copy(source_autostart_desktop_file, destination_file); } case AutoStartStatus::Disabled: return QFile::remove(destination_file); default: return false; } #else return false; #endif }
QString IOFactory::filterBadCharsFromFilename(const QString& name) { QString value = name; value.replace(QL1C('/'), QL1C('-')); value.remove(QL1C('\\')); value.remove(QL1C(':')); value.remove(QL1C('*')); value.remove(QL1C('?')); value.remove(QL1C('"')); value.remove(QL1C('<')); value.remove(QL1C('>')); value.remove(QL1C('|')); return value; }
void WebView::load(const LoadRequest &request) { const QUrl reqUrl = request.url(); if (reqUrl.scheme() == QL1S("javascript")) { const QString scriptSource = reqUrl.toString().mid(11); // Is the javascript source percent encoded or not? // Looking for % character in source should work in most cases if (scriptSource.contains(QL1C('%'))) page()->mainFrame()->evaluateJavaScript(QUrl::fromPercentEncoding(scriptSource.toUtf8())); else page()->mainFrame()->evaluateJavaScript(scriptSource); return; } if (reqUrl.isEmpty() || isUrlValid(reqUrl)) { request.load(this); m_aboutToLoadUrl = reqUrl; return; } const LoadRequest searchRequest = mApp->searchEnginesManager()->searchResult(reqUrl.toString()); m_aboutToLoadUrl = searchRequest.url(); searchRequest.load(this); }
QStringList NetworkFactory::extractFeedLinksFromHtmlPage(const QUrl &url, const QString &html) { QStringList feeds; const QRegExp rx(FEED_REGEX_MATCHER, Qt::CaseInsensitive); const QRegExp rx_href(FEED_HREF_REGEX_MATCHER, Qt::CaseInsensitive); for (int pos = 0; (pos = rx.indexIn(html, pos)) != -1; pos += rx.matchedLength()) { QString link_element = html.mid(pos, rx.matchedLength()); if (rx_href.indexIn(link_element) != -1) { QString href_attribute = rx_href.capturedTexts().at(0); QString feed_link = href_attribute.mid(6, href_attribute.size() - 7); if (feed_link.startsWith(QL1S("//"))) { feed_link = QString(URI_SCHEME_HTTP) + feed_link.mid(2); } else if (feed_link.startsWith(QL1C('/'))) { feed_link = url.toString(QUrl::RemovePath | QUrl::RemoveQuery | QUrl::StripTrailingSlash) + feed_link; } feeds.append(feed_link); } } return feeds; }
QString QzTools::ensureUniqueFilename(const QString &name, const QString &appendFormat) { Q_ASSERT(appendFormat.contains(QL1S("%1"))); QFileInfo info(name); if (!info.exists()) return name; const QDir dir = info.absoluteDir(); const QString fileName = info.fileName(); int i = 1; while (info.exists()) { QString file = fileName; int index = file.lastIndexOf(QL1C('.')); const QString appendString = appendFormat.arg(i); if (index == -1) file.append(appendString); else file = file.left(index) + appendString + file.mid(index); info.setFile(dir, file); i++; } return info.absoluteFilePath(); }
void WebPage::javaScriptAlert(const QUrl &securityOrigin, const QString &msg) { QStringList parts = msg.split(QL1C('-')); if (parts.size() == 2) { int message_id = parts.at(0).toInt(); QString action = parts.at(1); if (action == QSL("read")) { emit messageStatusChangeRequested(message_id, MarkRead); } else if (action == QSL("unread")) { emit messageStatusChangeRequested(message_id, MarkUnread); } else if (action == QSL("starred")) { emit messageStatusChangeRequested(message_id, MarkStarred); } else if (action == QSL("unstarred")) { emit messageStatusChangeRequested(message_id, MarkUnstarred); } else { QWebEnginePage::javaScriptAlert(securityOrigin, msg); } } else { QWebEnginePage::javaScriptAlert(securityOrigin, msg); } }
void DownloadManager::download(QWebEngineDownloadItem *downloadItem) { QString downloadPath; bool openFile = false; QString fileName = QFileInfo(downloadItem->path()).fileName(); fileName = QUrl::fromPercentEncoding(fileName.toUtf8()); if (m_downloadPath.isEmpty()) { // Ask what to do DownloadOptionsDialog optionsDialog(fileName, downloadItem->url(), mApp->activeWindow()); optionsDialog.showExternalManagerOption(m_useExternalManager); optionsDialog.setLastDownloadOption(m_lastDownloadOption); switch (optionsDialog.exec()) { case 1: // Open openFile = true; downloadPath = QzTools::ensureUniqueFilename(DataPaths::path(DataPaths::Temp) + QLatin1Char('/') + fileName); m_lastDownloadOption = OpenFile; break; case 2: // Save downloadPath = QFileDialog::getSaveFileName(mApp->activeWindow(), tr("Save file as..."), m_lastDownloadPath + fileName); m_lastDownloadOption = SaveFile; break; case 3: // External manager startExternalManager(downloadItem->url()); // fallthrough default: downloadItem->cancel(); return; } } else { downloadPath = QzTools::ensureUniqueFilename(m_downloadPath + QL1C('/') + fileName); } if (downloadPath.isEmpty()) { downloadItem->cancel(); return; } // Set download path and accept downloadItem->setPath(downloadPath); downloadItem->accept(); // Create download item QListWidgetItem* listItem = new QListWidgetItem(ui->list); DownloadItem* downItem = new DownloadItem(listItem, downloadItem, QFileInfo(downloadPath).absolutePath(), QFileInfo(downloadPath).fileName(), openFile, this); connect(downItem, SIGNAL(deleteItem(DownloadItem*)), this, SLOT(deleteItem(DownloadItem*))); connect(downItem, SIGNAL(downloadFinished(bool)), this, SLOT(downloadFinished(bool))); ui->list->setItemWidget(listItem, downItem); listItem->setSizeHint(downItem->sizeHint()); downItem->show(); show(); raise(); activateWindow(); }
void WebView::load(const LoadRequest &request) { const QUrl reqUrl = request.url(); if (reqUrl.isEmpty()) return; if (reqUrl.scheme() == QL1S("javascript")) { const QString scriptSource = reqUrl.toString().mid(11); // Is the javascript source percent encoded or not? // Looking for % character in source should work in most cases if (scriptSource.contains(QL1C('%'))) page()->runJavaScript(QUrl::fromPercentEncoding(scriptSource.toUtf8())); else page()->runJavaScript(scriptSource); return; } if (isUrlValid(reqUrl)) { loadRequest(request); return; } // Make sure to correctly load hosts like localhost (eg. without the dot) if (!reqUrl.isEmpty() && reqUrl.scheme().isEmpty() && !QzTools::containsSpace(reqUrl.path()) && // See #1622 !reqUrl.path().contains(QL1C('.')) ) { QUrl u(QSL("http://") + reqUrl.path()); if (u.isValid()) { // This is blocking... QHostInfo info = QHostInfo::fromName(u.path()); if (info.error() == QHostInfo::NoError) { LoadRequest req = request; req.setUrl(u); loadRequest(req); return; } } } if (qzSettings->searchFromAddressBar) { const LoadRequest searchRequest = mApp->searchEnginesManager()->searchResult(request.urlString()); loadRequest(searchRequest); } }
SystemFactory::AutoStartStatus SystemFactory::autoStartStatus() const { // User registry way to auto-start the application on Windows. #if defined(Q_OS_WIN) QSettings registry_key(QSL("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"), QSettings::NativeFormat); const bool autostart_enabled = registry_key.value(QSL(APP_LOW_NAME), QString()).toString().replace(QL1C('\\'), QL1C('/')) == Application::applicationFilePath(); if (autostart_enabled) { return AutoStartStatus::Enabled; } else { return AutoStartStatus::Disabled; } #elif defined(Q_OS_LINUX) // Use proper freedesktop.org way to auto-start the application on Linux. // INFO: http://standards.freedesktop.org/autostart-spec/latest/ const QString desktop_file_location = autostartDesktopFileLocation(); // No correct path was found. if (desktop_file_location.isEmpty()) { qWarning("Searching for auto-start function status failed. HOME variable not found."); return AutoStartStatus::Unavailable; } // We found correct path, now check if file exists and return correct status. if (QFile::exists(desktop_file_location)) { // File exists, we must read it and check if "Hidden" attribute is defined and what is its value. QSettings desktop_settings(desktop_file_location, QSettings::IniFormat); bool hidden_value = desktop_settings.value(QSL("Desktop Entry/Hidden"), false).toBool(); return hidden_value ? AutoStartStatus::Disabled : AutoStartStatus::Enabled; } else { return AutoStartStatus::Disabled; } #else // Disable auto-start functionality on unsupported platforms. return AutoStartStatus::Unavailable; #endif }
pEnvironmentVariablesModel::Variables pEnvironmentVariablesModel::stringListToVariables( const QStringList& variables ) { pEnvironmentVariablesModel::Variables items; foreach ( const QString& variable, variables ) { const QString name = variable.section( QL1C( '=' ), 0, 0 ); const QString value = variable.section( QL1C( '=' ), 1 ); pEnvironmentVariablesModel::Variable var; var.name = name; var.value = value; var.enabled = true; items[ name ] = var; } return items; }
// Returns true if the scheme and domain of the two urls match... static bool domainSchemeMatch(const QUrl& u1, const QUrl& u2) { if (u1.scheme() != u2.scheme()) return false; QStringList u1List = u1.host().split(QL1C('.'), QString::SkipEmptyParts); QStringList u2List = u2.host().split(QL1C('.'), QString::SkipEmptyParts); if (qMin(u1List.count(), u2List.count()) < 2) return false; // better safe than sorry... while (u1List.count() > 2) u1List.removeFirst(); while (u2List.count() > 2) u2List.removeFirst(); return (u1List == u2List); }
LoadRequest LocationBar::createLoadRequest() const { LoadRequest req; const QString &t = text().trimmed(); // Check for Search Engine shortcut int firstSpacePos = t.indexOf(QLatin1Char(' ')); if (firstSpacePos != -1) { const QString shortcut = t.left(firstSpacePos); const QString searchedString = t.mid(firstSpacePos).trimmed(); SearchEngine en = mApp->searchEnginesManager()->engineForShortcut(shortcut); if (!en.name.isEmpty()) { req = mApp->searchEnginesManager()->searchResult(en, searchedString); } } // Check for Bookmark keyword QList<BookmarkItem*> items = mApp->bookmarks()->searchKeyword(t); if (!items.isEmpty()) { BookmarkItem* item = items.at(0); item->updateVisitCount(); req.setUrl(item->url()); } if (req.isEmpty()) { // One word needs special handling, because QUrl::fromUserInput // would convert it to QUrl("http://WORD") if (!t.contains(QL1C(' ')) && !t.contains(QL1C('.'))) { req.setUrl(QUrl(t)); } else { const QUrl &guessed = QUrl::fromUserInput(t); if (!guessed.isEmpty()) req.setUrl(guessed); else req.setUrl(QUrl::fromEncoded(t.toUtf8())); } } return req; }
static QString toJavaScriptList(const QStringList &patterns) { QString out; foreach (const QString &pattern, patterns) { QString p; if (pattern.startsWith(QL1C('/')) && pattern.endsWith(QL1C('/')) && pattern.size() > 1) { p = pattern.mid(1, pattern.size() - 2); } else { p = pattern; p.replace(QL1S("."), QL1S("\\.")); p.replace(QL1S("*"), QL1S(".*")); } p = QSL("'%1'").arg(p); if (out.isEmpty()) { out.append(p); } else { out.append(QL1C(',') + p); } }
int TextFactory::stringWidth(const QString &string, const QFontMetrics &metrics) { const QStringList lines = string.split(QL1C('\n')); int width = 0; foreach (const QString &line, lines) { int line_width = metrics.width(line); if (line_width > width) { width = line_width; } }
// Version for Qt < 4.8 has one issue, it will wrongly // count .co.uk (and others) as second-level domain static QString toSecondLevelDomain(const QUrl &url) { const QString topLevelDomain = url.topLevelDomain(); const QString urlHost = url.host(); if (topLevelDomain.isEmpty() || urlHost.isEmpty()) { return QString(); } QString domain = urlHost.left(urlHost.size() - topLevelDomain.size()); if (domain.count(QL1C('.')) == 0) { return urlHost; } while (domain.count(QL1C('.')) != 0) { domain = domain.mid(domain.indexOf(QL1C('.')) + 1); } return domain + topLevelDomain; }
SvgParser::EndTagType SvgParser::isEndTag(bool skipTag) { static const QString elemEndStr = QL1S("/>"); if (*str == QL1C('>')) { if (skipTag) str++; return EndType1; } else if (stringEqual(str, elemEndStr.data(), 2)) { if (skipTag) str += 2; return EndType2; } return NotEnd; }
QTreeWidgetItem* pTranslationDialog::newItem( const QLocale& locale ) { const QString language = QLocale::languageToString( locale.language() ); const QString country = QLocale::countryToString( locale.country() ); const QString countryCode = locale.name().section( QL1C( '_' ), 1 ); QTreeWidgetItem* item = new QTreeWidgetItem; item->setIcon( 0, pIconManager::icon( QSL( "%1.png" ).arg( countryCode.toLower() ), QSL( ":/fresh/country-flags" ) ) ); item->setText( 0, QSL( "%1 (%2)" ).arg( language ).arg( country ) ); item->setToolTip( 0, locale.name() ); item->setData( 0, Qt::UserRole, locale.name() ); return item; }
QString OpenSearchEngine::parseTemplate(const QString &searchTerm, const QString &searchTemplate) { QString language = QLocale().name(); // Simple conversion to RFC 3066. language = language.replace(QL1C('_'), QL1C('-')); QString country = language; country = (country.remove(0, country.indexOf(QL1C('-')) + 1)).toLower(); const int firstDashPosition = country.indexOf(QL1C('-')); if (firstDashPosition >= 0) country = country.mid(firstDashPosition + 1); QString result = searchTemplate; result.replace(QL1S("{count}"), QL1S("20")); result.replace(QL1S("{startIndex}"), QL1S("0")); result.replace(QL1S("{startPage}"), QL1S("0")); result.replace(QL1S("{language}"), language); result.replace(QL1S("{country}"), country.toLower()); result.replace(QL1S("{inputEncoding}"), QL1S("UTF-8")); result.replace(QL1S("{outputEncoding}"), QL1S("UTF-8")); result.replace(QL1S("{searchTerms}"), searchTerm); return result; }
void pColorButton::setDefaultColor( const QColor& color ) { mColor = color; mColor = this->color(); // remove alpha if needed const QStringList texts = QStringList() << QSL( "RGBA #%1%2%3%4" ).arg( mColor.red(), 2, 16, QL1C( '0' ) ).arg( mColor.green(), 2, 16, QL1C( '0' ) ).arg( mColor.blue(), 2, 16, QL1C( '0' ) ).arg( mColor.alpha(), 2, 16, QL1C( '0' ) ) << QSL( "RGBA %1, %2, %3, %4" ).arg( mColor.red() ).arg( mColor.green() ).arg( mColor.blue() ).arg( mColor.alpha() ) ; setText( texts.first() ); setToolTip( texts.join( QL1S( "\n" ) ) ); setIcon( QIcon( pGuiUtils::filledPixmap( mColor, iconSize() ) ) ); }
SpeedDial::Page SpeedDial::pageForUrl(const QUrl &url) { ENSURE_LOADED; QString urlString = url.toString(); if (urlString.endsWith(QL1C('/'))) urlString = urlString.left(urlString.size() - 1); foreach (const Page &page, m_pages) { if (page.url == urlString) { return page; } } return Page(); }
static uint pluginId(const QUrl& url, const QStringList& argumentNames, const QStringList& argumentValues) { static const char* properties[] = {"src","data","width","height","type","id","name",0}; QString signature = url.toString(); for (int i = 0; properties[i]; ++i) { const int index = argumentNames.indexOf(properties[i]); if (index > -1) { signature += argumentNames.at(index); signature += QL1C('='); signature += argumentValues.at(index); } } return qHash(signature); }
static void extractMimeType(const QNetworkReply* reply, QString& mimeType) { mimeType.clear(); const KIO::MetaData& metaData = reply->attribute(static_cast<QNetworkRequest::Attribute>(KIO::AccessManager::MetaData)).toMap(); if (metaData.contains(QL1S("content-type"))) mimeType = metaData.value(QL1S("content-type")); if (!mimeType.isEmpty()) return; if (!reply->hasRawHeader("Content-Type")) return; const QString value (QL1S(reply->rawHeader("Content-Type").simplified().constData())); const int index = value.indexOf(QL1C(';')); mimeType = ((index == -1) ? value : value.left(index)); }
bool GmailServiceRoot::downloadAttachmentOnMyOwn(const QUrl& url) const { QString str_url = url.toString(); QString attachment_id = str_url.mid(str_url.indexOf(QL1C('?')) + 1); QStringList parts = attachment_id.split(QL1S(GMAIL_ATTACHMENT_SEP)); QString file = QFileDialog::getSaveFileName(qApp->mainFormWidget(), tr("Select attachment destination file"), qApp->homeFolder() + QDir::separator() + parts.at(0)); if (!file.isEmpty() && parts.size() == 3) { Downloader* down = network()->downloadAttachment(parts.at(1), parts.at(2)); FormDownloadAttachment form(file, down, qApp->mainFormWidget()); form.exec(); return true; } else { return false; } }
QString PIM_Handler::matchingJsTable() const { QString values; QHashIterator<PI_Type, QStringList> i(m_infoMatches); while (i.hasNext()) { i.next(); foreach (const QString &value, i.value()) { QString key = m_allInfo.value(i.key()); key.replace(QL1C('"'), QL1S("\\\"")); values.append(QSL("\"%1\":\"%2\",").arg(value, key)); } } if (!values.isEmpty()) values = values.left(values.size() - 1); return QSL("{ %1 }").arg(values); }
bool pActionsModel::addAction( const QString& _path, QAction* action ) { Q_ASSERT( action ); if ( !action || !path( action ).isEmpty() || this->action( _path ) ) { return false; } const QString path = cleanPath( _path ); const QString subPath = path.section( QL1C( '/' ), 0, -2 ); QAction* parentAction = createCompletePathNode( subPath ); if ( !parentAction ) { return false; } const int row = children( parentAction ).count(); insertAction( path, action, parentAction, row ); return true; }