diff --git a/src/contents/ui/Navigation.qml b/src/contents/ui/Navigation.qml index 7012c28..296b633 100644 --- a/src/contents/ui/Navigation.qml +++ b/src/contents/ui/Navigation.qml @@ -1,154 +1,156 @@ /*************************************************************************** * * * Copyright 2014-2015 Sebastian Kügler * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * * * ***************************************************************************/ import QtQuick 2.3 import QtQuick.Layouts 1.0 import QtWebEngine 1.4 import QtQuick.Controls 2.0 as Controls import org.kde.kirigami 2.0 as Kirigami +import "regex-weburl.js" as RegexWebUrl + Item { id: errorHandler + property string searchUrl: "https://duckduckgo.com/?q=" + property string errorCode: "" property bool navigationShown: errorCode != "" || webBrowser.url === "" || true property int expandedHeight: Kirigami.Units.gridUnit * 2.5 property int buttonSize: Kirigami.Units.gridUnit * 2 Behavior on height { NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutQuad} } Rectangle { anchors.fill: parent; color: Kirigami.Theme.backgroundColor; } RowLayout { id: layout anchors.fill: parent anchors.leftMargin: Kirigami.Units.gridUnit / 2 anchors.rightMargin: Kirigami.Units.gridUnit / 2 visible: navigationShown spacing: Kirigami.Units.smallSpacing /* PlasmaComponents.ToolButton { id: backButton Layout.preferredWidth: buttonSize Layout.preferredHeight: buttonSize visible: currentWebView.canGoBack iconSource: "go-previous" onClicked: currentWebView.goBack() } PlasmaComponents.ToolButton { id: forwardButton Layout.preferredWidth: buttonSize Layout.preferredHeight: buttonSize visible: currentWebView.canGoForward iconSource: "go-next" onClicked: currentWebView.goForward() } PlasmaComponents.ToolButton { id: reloadButton Layout.preferredWidth: buttonSize Layout.preferredHeight: buttonSize iconSource: currentWebView.loading ? "process-stop" : "view-refresh" onClicked: currentWebView.loading ? currentWebView.stop() : currentWebView.reload() } */ Controls.TextField { id: urlInput Layout.fillWidth: true text: currentWebView.url selectByMouse: true focus: false - Keys.onReturnPressed: { - var urlRegExp = new RegExp("^(?:(?:http(?:s)?|ftp)://)(?:\\S+(?::(?:\\S)*)?@)?(?:(?:[a-z0-9\u00a1-\uffff](?:-)*)*(?:[a-z0-9\u00a1-\uffff])+)(?:\\.(?:[a-z0-9\u00a1-\uffff](?:-)*)*(?:[a-z0-9\u00a1-\uffff])+)*(?:\\.(?:[a-z0-9\u00a1-\uffff]){2,})(?::(?:\\d){2,5})?(?:/(?:\\S)*)?$") - - if (urlRegExp.test(text)) { + onAccepted: { + if (text.match(RegexWebUrl.re_weburl)) { load(browserManager.urlFromUserInput(text)) } else { - load(browserManager.urlFromUserInput("https://duckduckgo.com/" + text)) + load(browserManager.urlFromUserInput(searchUrl + text)) } } } Item { Layout.preferredWidth: buttonSize Layout.preferredHeight: buttonSize visible: currentWebView.loading Controls.BusyIndicator { width: buttonSize height: width anchors.centerIn: parent running: currentWebView.loading } } OptionButton { id: optionsButton property string targetState: "overview" Layout.fillWidth: false Layout.preferredWidth: buttonSize Layout.preferredHeight: buttonSize iconSource: "open-menu-symbolic" onClicked: options.state = (options.state != "hidden" ? "hidden" : targetState) } } states: [ State { name: "shown" when: navigationShown PropertyChanges { target: errorHandler; x: -expandedHeight} }, State { name: "hidden" when: !navigationShown PropertyChanges { target: errorHandler; x: 0} } ] } diff --git a/src/regex-weburl/regex-weburl.js b/src/regex-weburl/regex-weburl.js new file mode 100644 index 0000000..7f08404 --- /dev/null +++ b/src/regex-weburl/regex-weburl.js @@ -0,0 +1,108 @@ +// +// Regular Expression for URL validation +// +// Author: Diego Perini +// Created: 2010/12/05 +// Updated: 2018/09/12 +// License: MIT +// +// Copyright (c) 2010-2018 Diego Perini (http://www.iport.it) +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// the regular expression composed & commented +// could be easily tweaked for RFC compliance, +// it was expressly modified to fit & satisfy +// these test for an URL shortener: +// +// http://mathiasbynens.be/demo/url-regex +// +// Notes on possible differences from a standard/generic validation: +// +// - utf-8 char class take in consideration the full Unicode range +// - TLDs have been made mandatory so single names like "localhost" fails +// - protocols have been restricted to ftp, http and https only as requested +// +// Changes: +// +// - IP address dotted notation validation, range: 1.0.0.0 - 223.255.255.255 +// first and last IP address of each class is considered invalid +// (since they are broadcast/network addresses) +// +// - Added exclusion of private, reserved and/or local networks ranges +// - Made starting path slash optional (http://example.com?foo=bar) +// - Allow a dot (.) at the end of hostnames (http://example.com.) +// - Allow an underscore (_) character in host/domain names +// - Check dot delimited parts length and total length +// - Made protocol optional, allowed short syntax // +// +// Compressed one-line versions: +// +// Javascript regex version +// +// /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\u00a1-\uffff][a-z0-9\u00a1-\uffff_-]{0,62})?[a-z0-9\u00a1-\uffff]\.)+(?:[a-z\u00a1-\uffff]{2,}\.?))(?::\d{2,5})?(?:[/?#]\S*)?$/i +// +// PHP version (uses % symbol as delimiter) +// +// %^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\x{00a1}-\x{ffff}][a-z0-9\x{00a1}-\x{ffff}_-]{0,62})?[a-z0-9\x{00a1}-\x{ffff}]\.)+(?:[a-z\x{00a1}-\x{ffff}]{2,})\.?))(?::\d{2,5})?(?:[/?#]\S*)?$%iuS +// +var re_weburl = new RegExp( + "^" + + // protocol identifier (optional) + // short syntax // still required + "(?:(?:(?:https?|ftp):)?\\/\\/)" + + // user:pass BasicAuth (optional) + "(?:\\S+(?::\\S*)?@)?" + + "(?:" + + // IP address exclusion + // private & local networks + "(?!(?:10|127)(?:\\.\\d{1,3}){3})" + + "(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})" + + "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" + + // IP address dotted notation octets + // excludes loopback network 0.0.0.0 + // excludes reserved space >= 224.0.0.0 + // excludes network & broacast addresses + // (first & last IP address of each class) + "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" + + "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" + + "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" + + "|" + + // host & domain names, may end with dot + // can be replaced by a shortest alternative + // (?![-_])(?:[-\\w\\u00a1-\\uffff]{0,63}[^-_]\\.)+ + "(?:" + + "(?:" + + "[a-z0-9\\u00a1-\\uffff]" + + "[a-z0-9\\u00a1-\\uffff_-]{0,62}" + + ")?" + + "[a-z0-9\\u00a1-\\uffff]\\." + + ")+" + + // TLD identifier name, may end with dot + "(?:[a-z\\u00a1-\\uffff]{2,}\\.?)" + + ")" + + // port number (optional) + "(?::\\d{2,5})?" + + // resource path (optional) + "(?:[/?#]\\S*)?" + + "$", "i" +); diff --git a/src/resources.qrc b/src/resources.qrc index 2dd87ff..c85824d 100644 --- a/src/resources.qrc +++ b/src/resources.qrc @@ -1,19 +1,20 @@ contents/ui/Bookmarks.qml contents/ui/ContentView.qml contents/ui/ErrorHandler.qml contents/ui/History.qml contents/ui/ListWebView.qml contents/ui/Navigation.qml contents/ui/OptionButton.qml contents/ui/Options.qml contents/ui/OptionsOverview.qml contents/ui/Settings.qml contents/ui/Tabs.qml contents/ui/TabWebView.qml contents/ui/UrlDelegate.qml contents/ui/webbrowser.qml contents/ui/WebView.qml + regex-weburl/regex-weburl.js