diff --git a/emhttp/plugins/dynamix/Credits.page b/emhttp/plugins/dynamix/Credits.page
index bb7005e17..a56d6732d 100644
--- a/emhttp/plugins/dynamix/Credits.page
+++ b/emhttp/plugins/dynamix/Credits.page
@@ -19,6 +19,8 @@ Tag="trophy"
**Community Applications** Copyright © 2015-2023, Andrew Zawadzki
+**GUI Search** Copyright © 2021-2023, Andrew Zawadzki
+
The Software comprising the Unraid webGui, which is all files within this repository **except** for
files listed below, is licensed under GPL version 2.
diff --git a/emhttp/plugins/dynamix/javascript/dynamix.js b/emhttp/plugins/dynamix/javascript/dynamix.js
index e30f48e1d..e315d668c 100644
--- a/emhttp/plugins/dynamix/javascript/dynamix.js
+++ b/emhttp/plugins/dynamix/javascript/dynamix.js
@@ -58,3 +58,11 @@ shortcut={all_shortcuts:{},add:function(l,p,i){var e={type:"keydown",propagate:!
/* readmore.js - v2.0.0, copyright Jed Foster NOT UPDATED */
(function(c){function g(b,a){this.element=b;this.options=c.extend({},h,a);c(this.element).data("max-height",this.options.maxHeight);c(this.element).data("height-margin",this.options.heightMargin);delete this.options.maxHeight;if(this.options.embedCSS&&!k){var d=".readmore-js-toggle, .readmore-js-section { "+this.options.sectionCSS+" } .readmore-js-section { overflow: hidden; }",e=document.createElement("style");e.type="text/css";e.styleSheet?e.styleSheet.cssText=d:e.appendChild(document.createTextNode(d));document.getElementsByTagName("head")[0].appendChild(e);k=!0}this._defaults=h;this._name=f;this.init()}var f="readmore",h={speed:100,maxHeight:200,heightMargin:16,moreLink:'Read More',lessLink:'Close',embedCSS:!0,sectionCSS:"display: block; width: 100%;",startOpen:!1,expandedClass:"readmore-js-expanded",collapsedClass:"readmore-js-collapsed",beforeToggle:function(){},afterToggle:function(){}},k=!1;g.prototype={init:function(){var b=this;c(this.element).each(function(){var a=c(this),d=a.css("max-height").replace(/[^-\d\.]/g,"")>a.data("max-height")?a.css("max-height").replace(/[^-\d\.]/g,""):a.data("max-height"),e=a.data("height-margin");"none"!=a.css("max-height")&&a.css("max-height","none");b.setBoxHeight(a);if(a.outerHeight(!0)<=d+e)return!0;a.addClass("readmore-js-section "+b.options.collapsedClass).data("collapsedHeight",d);a.after(c(b.options.startOpen?b.options.lessLink:b.options.moreLink).on("click",function(c){b.toggleSlider(this,a,c)}).addClass("readmore-js-toggle"));b.options.startOpen||a.css({height:d})});c(window).on("resize",function(a){b.resizeBoxes()})},toggleSlider:function(b,a,d){d.preventDefault();var e=this;d=newLink=sectionClass="";var f=!1;d=c(a).data("collapsedHeight");c(a).height()<=d?(d=c(a).data("expandedHeight")+"px",newLink="lessLink",f=!0,sectionClass=e.options.expandedClass):(newLink="moreLink",sectionClass=e.options.collapsedClass);e.options.beforeToggle(b,a,f);c(a).animate({height:d},{duration:e.options.speed,complete:function(){e.options.afterToggle(b,a,f);c(b).replaceWith(c(e.options[newLink]).on("click",function(b){e.toggleSlider(this,a,b)}).addClass("readmore-js-toggle"));c(this).removeClass(e.options.collapsedClass+" "+e.options.expandedClass).addClass(sectionClass)}})},setBoxHeight:function(b){var a=b.clone().css({height:"auto",width:b.width(),overflow:"hidden"}).insertAfter(b),c=a.outerHeight(!0);a.remove();b.data("expandedHeight",c)},resizeBoxes:function(){var b=this;c(".readmore-js-section").each(function(){var a=c(this);b.setBoxHeight(a);(a.height()>a.data("expandedHeight")||a.hasClass(b.options.expandedClass)&&a.height()-1)this._list=t.split(/\s*,\s*/);else if((t=i(t))&&t.children){var e=[];o.apply(t.children).forEach(function(t){if(!t.disabled){var i=t.textContent.trim(),n=t.value||i,s=t.label||i;""!==n&&e.push({label:s,value:n})}}),this._list=e}document.activeElement===this.input&&this.evaluate()},get selected(){return this.index>-1},get opened(){return this.isOpened},close:function(t){this.opened&&(this.input.setAttribute("aria-expanded","false"),this.ul.setAttribute("hidden",""),this.isOpened=!1,this.index=-1,this.status.setAttribute("hidden",""),i.fire(this.input,"awesomplete-close",t||{}))},open:function(){this.input.setAttribute("aria-expanded","true"),this.ul.removeAttribute("hidden"),this.isOpened=!0,this.status.removeAttribute("hidden"),this.autoFirst&&-1===this.index&&this.goto(0),i.fire(this.input,"awesomplete-open")},destroy:function(){if(i.unbind(this.input,this._events.input),i.unbind(this.input.form,this._events.form),!this.options.container){var t=this.container.parentNode;t.insertBefore(this.input,this.container),t.removeChild(this.container)}this.input.removeAttribute("autocomplete"),this.input.removeAttribute("aria-autocomplete");var e=r.all.indexOf(this);-1!==e&&r.all.splice(e,1)},next:function(){var t=this.ul.children.length;this.goto(this.index-1&&e.length>0&&(e[t].setAttribute("aria-selected","true"),this.status.textContent=e[t].textContent+", list item "+(t+1)+" of "+e.length,this.input.setAttribute("aria-activedescendant",this.ul.id+"_item_"+this.index),this.ul.scrollTop=e[t].offsetTop-this.ul.clientHeight+e[t].clientHeight,i.fire(this.input,"awesomplete-highlight",{text:this.suggestions[this.index]}))},select:function(t,e,n){if(t?this.index=i.siblingIndex(t):t=this.ul.children[this.index],t){var s=this.suggestions[this.index];i.fire(this.input,"awesomplete-select",{text:s,origin:e||t,originalEvent:n})&&(this.replace(s),this.close({reason:"select"}),i.fire(this.input,"awesomplete-selectcomplete",{text:s,originalEvent:n}))}},evaluate:function(){var e=this,i=this.input.value;i.length>=this.minChars&&this._list&&this._list.length>0?(this.index=-1,this.ul.innerHTML="",this.suggestions=this._list.map(function(n){return new t(e.data(n,i))}).filter(function(t){return e.filter(t,i)}),!1!==this.sort&&(this.suggestions=this.suggestions.sort(this.sort)),this.suggestions=this.suggestions.slice(0,this.maxItems),this.suggestions.forEach(function(t,n){e.ul.appendChild(e.item(t,i,n))}),0===this.ul.children.length?(this.status.textContent="No results found",this.close({reason:"nomatches"})):(this.open(),this.status.textContent=this.ul.children.length+" results found")):(this.close({reason:"nomatches"}),this.status.textContent="No results found")}},r.all=[],r.FILTER_CONTAINS=function(t,e){return RegExp(i.regExpEscape(e.trim()),"i").test(t)},r.FILTER_STARTSWITH=function(t,e){return RegExp("^"+i.regExpEscape(e.trim()),"i").test(t)},r.SORT_BYLENGTH=function(t,e){return t.length!==e.length?t.length-e.length:t$&"),role:"option","aria-selected":"false",id:"awesomplete_list_"+this.count+"_item_"+n})},r.REPLACE=function(t){this.input.value=t.value},r.DATA=function(t){return t},Object.defineProperty(t.prototype=Object.create(String.prototype),"length",{get:function(){return this.label.length}}),t.prototype.toString=t.prototype.valueOf=function(){return""+this.label};var o=Array.prototype.slice;i.create=function(t,e){var n=document.createElement(t);for(var s in e){var r=e[s];if("inside"===s)i(r).appendChild(n);else if("around"===s){var o=i(r);o.parentNode.insertBefore(n,o),n.appendChild(o),null!=o.getAttribute("autofocus")&&o.focus()}else s in n?n[s]=r:n.setAttribute(s,r)}return n},i.bind=function(t,e){if(t)for(var i in e){var n=e[i];i.split(/\s+/).forEach(function(e){t.addEventListener(e,n)})}},i.unbind=function(t,e){if(t)for(var i in e){var n=e[i];i.split(/\s+/).forEach(function(e){t.removeEventListener(e,n)})}},i.fire=function(t,e,i){var n=document.createEvent("HTMLEvents");n.initEvent(e,!0,!0);for(var s in i)n[s]=i[s];return t.dispatchEvent(n)},i.regExpEscape=function(t){return t.replace(/[-\\^$*+?.()|[\]{}]/g,"\\$&")},i.siblingIndex=function(t){for(var e=0;t=t.previousElementSibling;e++);return e},"undefined"!=typeof self&&(self.Awesomplete=r),"undefined"!=typeof Document&&("loading"!==document.readyState?s():document.addEventListener("DOMContentLoaded",s)),r.$=i,r.$$=n,"object"==typeof module&&module.exports&&(module.exports=r)}();
+
diff --git a/emhttp/plugins/dynamix/styles/dynamix-azure.css b/emhttp/plugins/dynamix/styles/dynamix-azure.css
index 4647bfab3..95a6ad462 100644
--- a/emhttp/plugins/dynamix/styles/dynamix-azure.css
+++ b/emhttp/plugins/dynamix/styles/dynamix-azure.css
@@ -266,3 +266,24 @@ div.icon-zip{background:url('../images/file-types.png') -32px -80px;width:16px;h
.tooltipster-sidetip.tooltipster-left .tooltipster-box{border-right:3px solid #ff8c2f}
.tooltipster-sidetip.tooltipster-right .tooltipster-box{border-left:3px solid #ff8c2f}
.fileTree{background-color:#f2f2f2}
+#guiSearchBox:placeholder-shown {caret-color:transparent;}
+#guiSearchBox {position:fixed;top:55px;left:250px;}
+.guiSearchBoxResults {position:fixed !important;top:90px !important; left:250px !important;}
+.awesomplete [hidden] {display: none;}
+.awesomplete .visually-hidden {position: absolute;clip: rect(0, 0, 0, 0);}
+.awesomplete {display: inline-block;position: relative;color: red;}
+.awesomplete > input {display: block;}
+.awesomplete > ul {position: absolute;left: 0;z-index: 1;min-width: 100%;box-sizing: border-box;list-style: none;padding: 0;margin: 0;background: #fff;}
+.awesomplete > ul:empty {display: none;}
+.awesomplete > ul {border-radius: .3em;margin: .2em 0 0;background: hsla(0,0%,100%,.9);background: linear-gradient(to bottom right, white, hsla(0,0%,100%,.8));border: 1px solid rgba(0,0,0,.3);box-shadow: .05em .2em .6em rgba(0,0,0,.2);text-shadow: none;}
+@supports (transform: scale(0)) {.awesomplete > ul {transition: .3s cubic-bezier(.4,.2,.5,1.4);transform-origin: 1.43em -.43em;}
+ .awesomplete > ul[hidden],.awesomplete > ul:empty {opacity: 0;transform: scale(0);display: block;transition-timing-function: ease;}
+}
+/* Pointer */
+.awesomplete > ul:before {content: "";position: absolute;top: -.43em;left: 1em;width: 0; height: 0;padding: .4em;background: white;border: inherit;border-right: 0;border-bottom: 0;-webkit-transform: rotate(45deg);transform: rotate(45deg);}
+.awesomplete > ul > li {position: relative;padding: .2em .5em;cursor: pointer;}
+.awesomplete > ul > li:hover {background: hsl(200, 40%, 80%);color: black;}
+.awesomplete > ul > li[aria-selected="true"] {background: hsl(205, 40%, 40%);color: white;}
+.awesomplete mark {background: hsl(65, 100%, 50%);}
+.awesomplete li:hover mark {background: hsl(68, 100%, 41%);}
+.awesomplete li[aria-selected="true"] mark {background: hsl(86, 100%, 21%);color: inherit;}
\ No newline at end of file
diff --git a/emhttp/plugins/dynamix/styles/dynamix-black.css b/emhttp/plugins/dynamix/styles/dynamix-black.css
index f20542757..d30366e6f 100644
--- a/emhttp/plugins/dynamix/styles/dynamix-black.css
+++ b/emhttp/plugins/dynamix/styles/dynamix-black.css
@@ -266,3 +266,23 @@ div.icon-zip{background:url('../images/file-types.png') -32px -80px;width:16px;h
.tooltipster-sidetip.tooltipster-left .tooltipster-box{border-right:3px solid #ff8c2f}
.tooltipster-sidetip.tooltipster-right .tooltipster-box{border-left:3px solid #ff8c2f}
.fileTree{background-color:#f2f2f2}
+#guiSearchBox:placeholder-shown {caret-color:transparent;}
+.guiSearchBoxResults {width:450px;}
+.awesomplete [hidden] {display: none;}
+.awesomplete .visually-hidden {position: absolute;clip: rect(0, 0, 0, 0);}
+.awesomplete {display: inline-block;position: relative;color: red;}
+.awesomplete > input {display: block;}
+.awesomplete > ul {position: absolute;left: 0;z-index: 1;min-width: 100%;box-sizing: border-box;list-style: none;padding: 0;margin: 0;background: #fff;}
+.awesomplete > ul:empty {display: none;}
+.awesomplete > ul {border-radius: .3em;margin: .2em 0 0;background: hsla(0,0%,100%,.9);background: linear-gradient(to bottom right, white, hsla(0,0%,100%,.8));border: 1px solid rgba(0,0,0,.3);box-shadow: .05em .2em .6em rgba(0,0,0,.2);text-shadow: none;}
+@supports (transform: scale(0)) {.awesomplete > ul {transition: .3s cubic-bezier(.4,.2,.5,1.4);transform-origin: 1.43em -.43em;}
+ .awesomplete > ul[hidden],.awesomplete > ul:empty {opacity: 0;transform: scale(0);display: block;transition-timing-function: ease;}
+}
+/* Pointer */
+.awesomplete > ul:before {content: "";position: absolute;top: -.43em;left: 1em;width: 0; height: 0;padding: .4em;background: white;border: inherit;border-right: 0;border-bottom: 0;-webkit-transform: rotate(45deg);transform: rotate(45deg);}
+.awesomplete > ul > li {position: relative;padding: .2em .5em;cursor: pointer;}
+.awesomplete > ul > li:hover {background: hsl(200, 40%, 80%);color: black;}
+.awesomplete > ul > li[aria-selected="true"] {background: hsl(205, 40%, 40%);color: white;}
+.awesomplete mark {background: hsl(65, 100%, 50%);}
+.awesomplete li:hover mark {background: hsl(68, 100%, 41%);}
+.awesomplete li[aria-selected="true"] mark {background: hsl(86, 100%, 21%);color: inherit;}
\ No newline at end of file
diff --git a/emhttp/plugins/dynamix/styles/dynamix-gray.css b/emhttp/plugins/dynamix/styles/dynamix-gray.css
index 4ee534c5a..080fc84db 100644
--- a/emhttp/plugins/dynamix/styles/dynamix-gray.css
+++ b/emhttp/plugins/dynamix/styles/dynamix-gray.css
@@ -266,3 +266,24 @@ div.icon-zip{background:url('../images/file-types.png') -32px -80px;width:16px;h
.tooltipster-sidetip.tooltipster-left .tooltipster-box{border-right:3px solid #ff8c2f}
.tooltipster-sidetip.tooltipster-right .tooltipster-box{border-left:3px solid #ff8c2f}
.fileTree{background-color:#f2f2f2}
+#guiSearchBox:placeholder-shown {caret-color:transparent;}
+#guiSearchBox {position:fixed;top:55px;left:250px;}
+.guiSearchBoxResults {position:fixed !important;top:90px !important; left:250px !important;}
+.awesomplete [hidden] {display: none;}
+.awesomplete .visually-hidden {position: absolute;clip: rect(0, 0, 0, 0);}
+.awesomplete {display: inline-block;position: relative;color: red;}
+.awesomplete > input {display: block;}
+.awesomplete > ul {position: absolute;left: 0;z-index: 1;min-width: 100%;box-sizing: border-box;list-style: none;padding: 0;margin: 0;background: #fff;}
+.awesomplete > ul:empty {display: none;}
+.awesomplete > ul {border-radius: .3em;margin: .2em 0 0;background: hsla(0,0%,100%,.9);background: linear-gradient(to bottom right, white, hsla(0,0%,100%,.8));border: 1px solid rgba(0,0,0,.3);box-shadow: .05em .2em .6em rgba(0,0,0,.2);text-shadow: none;}
+@supports (transform: scale(0)) {.awesomplete > ul {transition: .3s cubic-bezier(.4,.2,.5,1.4);transform-origin: 1.43em -.43em;}
+ .awesomplete > ul[hidden],.awesomplete > ul:empty {opacity: 0;transform: scale(0);display: block;transition-timing-function: ease;}
+}
+/* Pointer */
+.awesomplete > ul:before {content: "";position: absolute;top: -.43em;left: 1em;width: 0; height: 0;padding: .4em;background: white;border: inherit;border-right: 0;border-bottom: 0;-webkit-transform: rotate(45deg);transform: rotate(45deg);}
+.awesomplete > ul > li {position: relative;padding: .2em .5em;cursor: pointer;}
+.awesomplete > ul > li:hover {background: hsl(200, 40%, 80%);color: black;}
+.awesomplete > ul > li[aria-selected="true"] {background: hsl(205, 40%, 40%);color: white;}
+.awesomplete mark {background: hsl(65, 100%, 50%);}
+.awesomplete li:hover mark {background: hsl(68, 100%, 41%);}
+.awesomplete li[aria-selected="true"] mark {background: hsl(86, 100%, 21%);color: inherit;}
\ No newline at end of file
diff --git a/emhttp/plugins/dynamix/styles/dynamix-white.css b/emhttp/plugins/dynamix/styles/dynamix-white.css
index 830f1295e..8db7a567c 100644
--- a/emhttp/plugins/dynamix/styles/dynamix-white.css
+++ b/emhttp/plugins/dynamix/styles/dynamix-white.css
@@ -266,3 +266,23 @@ div.icon-zip{background:url('../images/file-types.png') -32px -80px;width:16px;h
.tooltipster-sidetip.tooltipster-left .tooltipster-box{border-right:3px solid #ff8c2f}
.tooltipster-sidetip.tooltipster-right .tooltipster-box{border-left:3px solid #ff8c2f}
.fileTree{background-color:#f2f2f2}
+#guiSearchBox:placeholder-shown {caret-color:transparent;}
+.guiSearchBoxResults {width:450px;}
+.awesomplete [hidden] {display: none;}
+.awesomplete .visually-hidden {position: absolute;clip: rect(0, 0, 0, 0);}
+.awesomplete {display: inline-block;position: relative;color: red;}
+.awesomplete > input {display: block;}
+.awesomplete > ul {position: absolute;left: 0;z-index: 1;min-width: 100%;box-sizing: border-box;list-style: none;padding: 0;margin: 0;background: #fff;}
+.awesomplete > ul:empty {display: none;}
+.awesomplete > ul {border-radius: .3em;margin: .2em 0 0;background: hsla(0,0%,100%,.9);background: linear-gradient(to bottom right, white, hsla(0,0%,100%,.8));border: 1px solid rgba(0,0,0,.3);box-shadow: .05em .2em .6em rgba(0,0,0,.2);text-shadow: none;}
+@supports (transform: scale(0)) {.awesomplete > ul {transition: .3s cubic-bezier(.4,.2,.5,1.4);transform-origin: 1.43em -.43em;}
+ .awesomplete > ul[hidden],.awesomplete > ul:empty {opacity: 0;transform: scale(0);display: block;transition-timing-function: ease;}
+}
+/* Pointer */
+.awesomplete > ul:before {content: "";position: absolute;top: -.43em;left: 1em;width: 0; height: 0;padding: .4em;background: white;border: inherit;border-right: 0;border-bottom: 0;-webkit-transform: rotate(45deg);transform: rotate(45deg);}
+.awesomplete > ul > li {position: relative;padding: .2em .5em;cursor: pointer;}
+.awesomplete > ul > li:hover {background: hsl(200, 40%, 80%);color: black;}
+.awesomplete > ul > li[aria-selected="true"] {background: hsl(205, 40%, 40%);color: white;}
+.awesomplete mark {background: hsl(65, 100%, 50%);}
+.awesomplete li:hover mark {background: hsl(68, 100%, 41%);}
+.awesomplete li[aria-selected="true"] mark {background: hsl(86, 100%, 21%);color: inherit;}
\ No newline at end of file
diff --git a/emhttp/plugins/gui.search/exec.php b/emhttp/plugins/gui.search/exec.php
new file mode 100755
index 000000000..588f66fb6
--- /dev/null
+++ b/emhttp/plugins/gui.search/exec.php
@@ -0,0 +1,147 @@
+
+###################################################
+# #
+# GUI Search copyright 2021-2023, Andrew Zawadzki #
+# Licenced under GPLv2 #
+# #
+###################################################
+@mkdir("/tmp/gui.search");
+
+extract(@parse_ini_file("/boot/config/plugins/dynamix/dynamix.cfg") ?: []);
+$locale = $locale ?? "";
+if ( $locale == "en_US")
+ $locale = "";
+
+if ( $locale != @file_get_contents("/tmp/gui.search/locale") ) {
+ @unlink("/tmp/gui.search/searchResults.json");
+}
+
+file_put_contents("/tmp/gui.search/locale",$locale);
+
+$uri = "";
+if ( $locale ) {
+ if ( is_dir("/usr/local/emhttp/languages/$locale") ) {
+ $dotFiles = glob("/usr/local/emhttp/languages/$locale/*.txt");
+ foreach ($dotFiles as $dot) {
+ $uri .= basename($dot,".txt")."/";
+ }
+ $uri = rtrim($uri,"/");
+ }
+}
+
+$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: "/usr/local/emhttp";
+
+$_SERVER['REQUEST_URI'] = $uri;
+$_SESSION['locale'] = $locale;
+require_once "$docroot/plugins/dynamix/include/Translations.php";
+
+$searchPages = array();
+$pageFiles = glob("/usr/local/emhttp/plugins/*/*.page");
+if ( is_file("/tmp/gui.search/searchResults.json") ) {
+ $searchPages = unserialize(file_get_contents("/tmp/gui.search/searchResults.json"));
+}
+if ( ! $searchPages ) {
+ $MainPages = array("About","WebGui","UNRAID-OS","SystemInformation","OtherSettings","Settings","NetworkServices","Utilities","DiskUtilities","UserPreferences","WGX");
+ // pass 1 - get all the "main" pages
+ foreach ($pageFiles as $page) {
+ if ( $page == "/usr/local/emhttp/plugins/dynamix/WGX.page") continue;
+ $file = explode("---",file_get_contents($page));
+ $pageInfo = parse_ini_string($file[0],true);
+
+ if ( isset($pageInfo['Menu']) && $pageInfo['Menu'] && in_array(explode(":",$pageInfo['Menu'])[0],$MainPages) && ! in_array(basename($page,".page"),$MainPages) ) {
+ $newPage[basename($page,".page")] = array(sanitizeQuote(_($pageInfo['Title'])),basename($page));
+ if ( $locale )
+ $newPage[basename($page,".page")] = array(sanitizeQuote($pageInfo['Title']),basename($page));
+ }
+ }
+
+ //pass 2 - link back any sub-pages
+ foreach ($pageFiles as $page) {
+ $file = explode("---",file_get_contents($page));
+ if ( ! isset($file[1]) ) continue;
+ $pageInfo = parse_ini_string($file[0],true);
+
+ if (isset($pageInfo['Menu']) && $pageInfo['Menu']) {
+ $pageLinked = explode(":",$pageInfo['Menu'])[0];
+ if (isset($newPage[$pageLinked]) && ! in_array($pageLinked,$MainPages) ) {
+ $newPage[] = array(sanitizeQuote(_($pageInfo['Title']))." ("._($newPage[$pageLinked][0]).")",$pageLinked);
+ if ( $locale )
+ $newPage[] = array(sanitizeQuote(($pageInfo['Title']))." (".($newPage[$pageLinked][0]).")",$pageLinked);
+
+ }
+ getSettings();
+ }
+ }
+ //pass 3 - cleanup
+ foreach ($newPage as $page) {
+ if ( ! in_array(array("label"=>sanitizeQuote(_($page[0])),"value"=>basename($page[1],".page")),$searchPages) )
+ $searchPages[] = array("label"=>sanitizeQuote(_($page[0])),"value"=>basename($page[1],".page"));
+ }
+ file_put_contents("/tmp/gui.search/searchResults.json",serialize($searchPages));
+}
+echo json_encode($searchPages);
+
+function getSettings() {
+ global $searchPages, $pageInfo, $page,$file,$locale;
+
+ $bannedPages = array("ShareEdit","UserEdit","Device","community.applications","Selftest","DeviceInfo","EthX","CA_Notices","SecuritySMB","SecurityNFS");
+ if (in_array(basename($page,".page"),$bannedPages) ) return;
+ foreach (explode("\n",$file[1]) as $line) {
+ $line = trim($line);
+ if ( startsWith($line,"_(") && (endsWith($line,")_:") || endsWith($line,")_):") ) ) {
+ preg_match("//i",$line,$extra,PREG_OFFSET_CAPTURE);
+ $string = str_replace(["_(",")_:",")_?",")_"],["","","",""],$line);
+
+ $extraEng = "";
+ $extraTra = "";
+ if ( $extra ) {
+ $extrasearch = trim(str_replace([""],["",""],$extra[0][0]));
+ $string = str_replace($extra[0][0],"",$string);
+ foreach ( explode("|",$extrasearch) as $term ) {
+ $extraEng .= $term."|";
+ $extraTra .= _($term)."|";
+ }
+ $extraEng = " [".rtrim($extraEng,"|")."]";
+ $extraTra = " [".rtrim($extraTra,"|")."]";
+ }
+ $string = sanitizeQuote($string);
+
+ $linkPage = basename($page,".page");
+ if (strpos($linkPage,"WG") === 0) {
+ $linkPage = "VPNmanager";
+ }
+ if ( stripos(str_replace(" ","",$line),"") )
+ continue;
+ if ( ! in_array(array("label"=>"$string $extraTra (".sanitizeQuote($pageInfo['Title']).")","value"=>"$linkPage**"._($string)),$searchPages) ) {
+ $searchPages[] = array("label"=>_($string)." $extraTra (".sanitizeQuote(_($pageInfo['Title'])).")","value"=>"$linkPage**"._($string));
+ if ( $locale ) {
+ if ( _($string) !== $string )
+ $searchPages[] = array("label"=>($string)." $extraEng (".sanitizeQuote($pageInfo['Title']).")","value"=>"$linkPage**"._($string));
+ }
+ }
+ }
+ }
+}
+
+function sanitizeQuote($string) {
+ return str_replace("'","",str_replace('"',"",$string));
+}
+
+##############################################
+# Determine if $haystack begins with $needle #
+##############################################
+function startsWith($haystack, $needle) {
+ if ( !is_string($haystack) || ! is_string($needle) ) return false;
+ return $needle === "" || strripos($haystack, $needle, -strlen($haystack)) !== FALSE;
+}
+#############################################
+# Determine if $string ends with $endstring #
+#############################################
+function endsWith($string, $endString) {
+ $len = strlen($endString);
+ if ($len == 0) {
+ return true;
+ }
+ return (substr($string, -$len) === $endString);
+}
+?>
diff --git a/emhttp/plugins/gui.search/gui_search.page b/emhttp/plugins/gui.search/gui_search.page
new file mode 100755
index 000000000..5f19685d7
--- /dev/null
+++ b/emhttp/plugins/gui.search/gui_search.page
@@ -0,0 +1,180 @@
+Menu='Buttons'
+Icon='search'
+Title='Search'
+Code='f002'
+---
+
+###################################################
+# #
+# GUI Search copyright 2021-2023, Andrew Zawadzki #
+# Licenced under GPLv2 #
+# #
+###################################################
+
+$currentUnraidPage = str_replace("Browse","Main",basename(explode("?",$_SERVER['REQUEST_URI'])[0]));
+
+$altGUI = ($theme == "azure" || $theme == "gray");
+?>
+
\ No newline at end of file
diff --git a/emhttp/plugins/gui.search/gui_search_post_hook.sh b/emhttp/plugins/gui.search/gui_search_post_hook.sh
new file mode 100755
index 000000000..813e7b48e
--- /dev/null
+++ b/emhttp/plugins/gui.search/gui_search_post_hook.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+rm -rf /tmp/gui.search
diff --git a/etc/rc.d/rc.local b/etc/rc.d/rc.local
index 86f620e2a..8b52eeac5 100755
--- a/etc/rc.d/rc.local
+++ b/etc/rc.d/rc.local
@@ -67,7 +67,7 @@ rm -f /boot/plugins/unRAIDServer.plg
rm -f $CONFIG/plugins/unRAIDServer.plg
# These plugins are now integrated in the OS or obsolete and may interfere
-Obsolete="vfio.pci dynamix.wireguard dynamix.ssd.trim"
+Obsolete="vfio.pci dynamix.wireguard dynamix.ssd.trim gui.search"
for Plugin in $Obsolete ; do
if [[ -e $CONFIG/plugins/$Plugin.plg ]]; then
logger "moving obsolete plugin $Plugin.plg to $CONFIG/plugins-error"