/*! * jQuery JavaScript Library v1.10.0 * http://jquery.com/ * * Includes Sizzle.js * http://sizzlejs.com/ * * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors * Released under the MIT license * http://jquery.org/license * * Date: 2013-05-24T18:39Z */ (function( window, undefined ) { // Can't do this because several apps including ASP.NET trace // the stack via arguments.caller.callee and Firefox dies if // you try to trace through "use strict" call chains. (#13335) // Support: Firefox 18+ //"use strict"; var // The deferred used on DOM ready readyList, // A central reference to the root jQuery(document) rootjQuery, // Support: IE<10 // For `typeof xmlNode.method` instead of `xmlNode.method !== undefined` core_strundefined = typeof undefined, // Use the correct document accordingly with window argument (sandbox) location = window.location, document = window.document, docElem = document.documentElement, // Map over jQuery in case of overwrite _jQuery = window.jQuery, // Map over the $ in case of overwrite _$ = window.$, // [[Class]] -> type pairs class2type = {}, // List of deleted data cache ids, so we can reuse them core_deletedIds = [], core_version = "1.10.0", // Save a reference to some core methods core_concat = core_deletedIds.concat, core_push = core_deletedIds.push, core_slice = core_deletedIds.slice, core_indexOf = core_deletedIds.indexOf, core_toString = class2type.toString, core_hasOwn = class2type.hasOwnProperty, core_trim = core_version.trim, // Define a local copy of jQuery jQuery = function( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' return new jQuery.fn.init( selector, context, rootjQuery ); }, // Used for matching numbers core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, // Used for splitting on whitespace core_rnotwhite = /\S+/g, // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE) rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, // A simple way to check for HTML strings // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) // Strict HTML recognition (#11290: must start with <) rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, // Match a standalone tag rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, // JSON RegExp rvalidchars = /^[\],:{}\s]*$/, rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g, rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g, // Matches dashed string for camelizing rmsPrefix = /^-ms-/, rdashAlpha = /-([\da-z])/gi, // Used by jQuery.camelCase as callback to replace() fcamelCase = function( all, letter ) { return letter.toUpperCase(); }, // The ready event handler completed = function( event ) { // readyState === "complete" is good enough for us to call the dom ready in oldIE if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) { detach(); jQuery.ready(); } }, // Clean-up method for dom ready events detach = function() { if ( document.addEventListener ) { document.removeEventListener( "DOMContentLoaded", completed, false ); window.removeEventListener( "load", completed, false ); } else { document.detachEvent( "onreadystatechange", completed ); window.detachEvent( "onload", completed ); } }; jQuery.fn = jQuery.prototype = { // The current version of jQuery being used jquery: core_version, constructor: jQuery, init: function( selector, context, rootjQuery ) { var match, elem; // HANDLE: $(""), $(null), $(undefined), $(false) if ( !selector ) { return this; } // Handle HTML strings if ( typeof selector === "string" ) { if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { // Assume that strings that start and end with <> are HTML and skip the regex check match = [ null, selector, null ]; } else { match = rquickExpr.exec( selector ); } // Match html or make sure no context is specified for #id if ( match && (match[1] || !context) ) { // HANDLE: $(html) -> $(array) if ( match[1] ) { context = context instanceof jQuery ? context[0] : context; // scripts is true for back-compat jQuery.merge( this, jQuery.parseHTML( match[1], context && context.nodeType ? context.ownerDocument || context : document, true ) ); // HANDLE: $(html, props) if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { for ( match in context ) { // Properties of context are called as methods if possible if ( jQuery.isFunction( this[ match ] ) ) { this[ match ]( context[ match ] ); // ...and otherwise set as attributes } else { this.attr( match, context[ match ] ); } } } return this; // HANDLE: $(#id) } else { elem = document.getElementById( match[2] ); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 if ( elem && elem.parentNode ) { // Handle the case where IE and Opera return items // by name instead of ID if ( elem.id !== match[2] ) { return rootjQuery.find( selector ); } // Otherwise, we inject the element directly into the jQuery object this.length = 1; this[0] = elem; } this.context = document; this.selector = selector; return this; } // HANDLE: $(expr, $(...)) } else if ( !context || context.jquery ) { return ( context || rootjQuery ).find( selector ); // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { return this.constructor( context ).find( selector ); } // HANDLE: $(DOMElement) } else if ( selector.nodeType ) { this.context = this[0] = selector; this.length = 1; return this; // HANDLE: $(function) // Shortcut for document ready } else if ( jQuery.isFunction( selector ) ) { return rootjQuery.ready( selector ); } if ( selector.selector !== undefined ) { this.selector = selector.selector; this.context = selector.context<?php /** * @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net> * * @author Julius Härtl <jus@bitgrid.net> * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ namespace OC\Core\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCSController; use OCP\INavigationManager; use OCP\IRequest; use OCP\IURLGenerator; class NavigationController extends OCSController { private INavigationManager $navigationManager; private IURLGenerator $urlGenerator; public function __construct(string $appName, IRequest $request, INavigationManager $navigationManager, IURLGenerator $urlGenerator) { parent::__construct($appName, $request); $this->navigationManager = $navigationManager; $this->urlGenerator = $urlGenerator; } /** * @NoAdminRequired * @NoCSRFRequired */ public function getAppsNavigation(bool $absolute = false): DataResponse { $navigation = $this->navigationManager->getAll(); if ($absolute) { $navigation = $this->rewriteToAbsoluteUrls($navigation); } $navigation = array_values($navigation); $etag = $this->generateETag($navigation); if ($this->request->getHeader('If-None-Match') === $etag) { return new DataResponse([], Http::STATUS_NOT_MODIFIED); } $response = new DataResponse($navigation); $response->setETag($etag); return $response; } /** * @NoAdminRequired * @NoCSRFRequired */ public function getSettingsNavigation(bool $absolute = false): DataResponse { $navigation = $this->navigationManager->getAll('settings'); if ($absolute) { $navigation = $this->rewriteToAbsoluteUrls($navigation); } $navigation = array_values($navigation); $etag = $this->generateETag($navigation); if ($this->request->getHeader('If-None-Match') === $etag) { return new DataResponse([], Http::STATUS_NOT_MODIFIED); } $response = new DataResponse($navigation); $response->setETag($etag); return $response; } /** * Generate an ETag for a list of navigation entries */ private function generateETag(array $navigation): string { foreach ($navigation as &$nav) { if ($nav['id'] === 'logout') { $nav['href'] = 'logout'; } } return md5(json_encode($navigation)); } /** * Rewrite href attribute of navigation entries to an absolute URL */ private function rewriteToAbsoluteUrls(array $navigation): array { foreach ($navigation as &$entry) { if (0 !== strpos($entry['href'], $this->urlGenerator->getBaseUrl())) { $entry['href'] = $this->urlGenerator->getAbsoluteURL($entry['href']); } if (0 !== strpos($entry['icon'], $this->urlGenerator->getBaseUrl())) { $entry['icon'] = $this->urlGenerator->getAbsoluteURL($entry['icon']); } } return $navigation; } }
<?php /** * @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net> * * @author Julius Härtl <jus@bitgrid.net> * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ namespace OC\Core\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCSController; use OCP\INavigationManager; use OCP\IRequest; use OCP\IURLGenerator; class NavigationController extends OCSController { private INavigationManager $navigationManager; private IURLGenerator $urlGenerator; public function __construct(string $appName, IRequest $request, INavigationManager $navigationManager, IURLGenerator $urlGenerator) { parent::__construct($appName, $request); $this->navigationManager = $navigationManager; $this->urlGenerator = $urlGenerator; } /** * @NoAdminRequired * @NoCSRFRequired */ public function getAppsNavigation(bool $absolute = false): DataResponse { $navigation = $this->navigationManager->getAll(); if ($absolute) { $navigation = $this->rewriteToAbsoluteUrls($navigation); } $navigation = array_values($navigation); $etag = $this->generateETag($navigation); if ($this->request->getHeader('If-None-Match') === $etag) { return new DataResponse([], Http::STATUS_NOT_MODIFIED); } $response = new DataResponse($navigation); $response->setETag($etag); return $response; } /** * @NoAdminRequired * @NoCSRFRequired */ public function getSettingsNavigation(bool $absolute = false): DataResponse { $navigation = $this->navigationManager->getAll('settings'); if ($absolute) { $navigation = $this->rewriteToAbsoluteUrls($navigation); } $navigation = array_values($navigation); $etag = $this->generateETag($navigation); if ($this->request->getHeader('If-None-Match') === $etag) { return new DataResponse([], Http::STATUS_NOT_MODIFIED); } $response = new DataResponse($navigation); $response->setETag($etag); return $response; } /** * Generate an ETag for a list of navigation entries */ private function generateETag(array $navigation): string { foreach ($navigation as &$nav) { if ($nav['id'] === 'logout') { $nav['href'] = 'logout'; } } return md5(json_encode($navigation)); } /** * Rewrite href attribute of navigation entries to an absolute URL */ private function rewriteToAbsoluteUrls(array $navigation): array { foreach ($navigation as &$entry) { if (0 !== strpos($entry['href'], $this->urlGenerator->getBaseUrl())) { $entry['href'] = $this->urlGenerator->getAbsoluteURL($entry['href']); } if (0 !== strpos($entry['icon'], $this->urlGenerator->getBaseUrl())) { $entry['icon'] = $this->urlGenerator->getAbsoluteURL($entry['icon']); } } return $navigation; } }