/** * Disable console output unless DEBUG mode is enabled. * Add * define('DEBUG', true); * To the end of config/config.php to enable debug mode. * The undefined checks fix the broken ie8 console */ var oc_debug; var oc_webroot; var oc_current_user = document.getElementsByTagName('head')[0].getAttribute('data-user'); var oc_requesttoken = document.getElementsByTagName('head')[0].getAttribute('data-requesttoken'); window.oc_config = window.oc_config || {}; if (typeof oc_webroot === "undefined") { oc_webroot = location.pathname; var pos = oc_webroot.indexOf('/index.php/'); if (pos !== -1) { oc_webroot = oc_webroot.substr(0, pos); } else { oc_webroot = oc_webroot.substr(0, oc_webroot.lastIndexOf('/')); } } if ( oc_debug !== true || typeof console === "undefined" || typeof console.log === "undefined" ) { if (!window.console) { window.console = {}; } var noOp = function() { }; var methods = ['log', 'debug', 'warn', 'info', 'error', 'assert', 'time', 'timeEnd']; for (var i = 0; i < methods.length; i++) { console[methods[i]] = noOp; } } /** * Sanitizes a HTML string by replacing all potential dangerous characters with HTML entities * @param {string} s String to sanitize * @return {string} Sanitized string */ function escapeHTML(s) { return s.toString().split('&').join('&').split('<').join('<').split('>').join('>').split('"').join('"').split('\'').join('''); } /** * Get the path to download a file * @param {string} file The filename * @param {string} dir The directory the file is in - e.g. $('#dir').val() * @return {string} Path to download the file * @deprecated use Files.getDownloadURL() instead */ function fileDownloadPath(dir, file) { return OC.filePath('files', 'ajax', 'download.php')+'?files='+encodeURIComponent(file)+'&dir='+encodeURIComponent(dir); } /** @namespace */ var OC={ PERMISSION_CREATE:4, PERMISSION_READ:1, PERMISSION_UPDATE:2, PERMISSION_DELETE:8, PERMISSION_SHARE:16, PERMISSION_ALL:31, /* jshint camelcase: false */ webroot:oc_webroot, appswebroots:(typeof oc_appswebroots !== 'undefined') ? oc_appswebroots:false, currentUser:(typeof oc_current_user!=='undefined')?oc_current_user:false, config: window.oc_config, appConfig: window.oc_appconfig || {}, theme: window.oc_defaults || {}, coreApps:['', 'admin','log','search','settings','core','3rdparty'], menuSpeed: 100, /** * Get an absolute url to a file in an app * @param {string} app the id of the app the file belongs to * @param {string} file the file path relative to the app folder * @return {string} Absolute URL to a file */ linkTo:function(app,file){ return OC.filePath(app,'',file); }, /** * Creates a relative url for remote use * @param {string} service id * @return {string} the url */ linkToRemoteBase:function(service) { return OC.webroot + '/remote.php/' + service; }, /** * @brief Creates an absolute url for remote use * @param {string} service id * @return {string} the url */ linkToRemote:function(service) { return window.location.protocol + '//' + window.location.host + OC.linkToRemoteBase(service); }, /** * Gets the base path for the given OCS API service. * @param {string} service name * @return {string} OCS API base path */ linkToOCS: function(service) { return window.location.protocol + '//' + window.location.host + OC.webroot + '/ocs/v1.php/' + service + '/'; }, /** * Generates the absolute url for the given relative url, which can contain parameters. * @param {string} url * @param params * @return {string} Absolute URL for the given relative URL */ generateUrl: function(url, params) { var _build = function (text, vars) { var vars = vars || []; return text.replace(/{([^{}]*)}/g, function (a, b) { var r = vars[b]; return typeof r === 'string' || typeof r === 'number' ? r : a; } ); }; if (url.charAt(0) !== '/') { url = '/' + url; } // TODO save somewhere whether the webserver is able to skip the index.php to have shorter links (e.g. for sharing) return OC.webroot + '/index.php' + _build(url, params); }, /** * Get the absolute url for a file in an app * @param {string} app the id of the app * @param {string} type the type of the file to link to (e.g. css,img,ajax.template) * @param {string} file the filename * @return {string} Absolute URL for a file in an app * @deprecated use OC.generateUrl() instead */ filePath:function(app,type,file){ var isCore=OC.coreApps.indexOf(app)!==-1, link=OC.webroot; if(file.substring(file.length-3) === 'php' && !isCore){ link+='/index.php/apps/' + app; if (file != 'index.php') { link+='/'; if(type){ link+=encodeURI(type + '/'); } link+= file; } }else if(file.substring(file.length-3) !== 'php' && !isCore){ link=OC.appswebroots[app]; if(type){ link+= '/'+type+'/'; } if(link.substring(link.length-1) !== '/'){ link+='/'; } link+=file; }else{ if ((app == 'settings' || app == 'core' || app == 'search') && type == 'ajax') { link+='/index.php/'; } else { link+='/'; } if(!isCore){ link+='apps/'; } if (app !== '') { app+='/'; link+=app; } if(type){ link+=type+'/'; } link+=file; } return link; }, /** * Redirect to the target URL, can also be used for downloads. * @param {string} targetURL URL to redirect to */ redirect: function(targetURL) { window.location = targetURL; }, /** * get the absolute path to an image file * if no extension is given for the image, it will automatically decide * between .png and .svg based on what the browser supports * @param {string} app the app id to which the image belongs * @param {string} file the name of the image file * @return {string} */ imagePath:function(app,file){ if(file.indexOf('.')==-1){//if no extension is given, use png or svg depending on browser support file+=(OC.Util.hasSVGSupport())?'.svg':'.png'; } return OC.filePath(app,'img',file); }, /** * Load a script for the server and load it. If the script is already loaded, * the event handler will be called directly * @param {string} app the app id to which the script belongs * @param {string} script the filename of the script * @param ready event handler to be called when the script is loaded */ addScript:function(app,script,ready){ var deferred, path=OC.filePath(app,'js',script+'.js'); if(!OC.addScript.loaded[path]){ if(ready){ deferred=$.getScript(path,ready); }else{ deferred=$.getScript(path); } OC.addScript.loaded[path]=deferred; }else{ if(ready){ ready(); } } return OC.addScript.loaded[path]; }, /** * Loads a CSS file * @param {string} app the app id to which the css style belongs * @param {string} style the filename of the css file */ addStyle:function(app,style){ var path=OC.filePath(app,'css',style+'.css'); if(OC.addStyle.loaded.indexOf(path)===-1){ OC.addStyle.loaded.push(path); if (document.createStyleSheet) { document.createStyleSheet(path); } else { style=$(''); $('head').append(style); } } }, /** * Loads translations for the given app asynchronously. * * @param {String} app app name * @param {Function} callback callback to call after loading * @return {Promise} */ addTranslations: function(app, callback) { return OC.L10N.load(app, callback); }, /** * Returns the base name of the given path. * For example for "/abc/somefile.txt" it will return "somefile.txt" * * @param {String} path * @return {String} base name */ basename: function(path) { return path.replace(/\\/g,'/').replace( /.*\//, '' ); }, /** * Returns the dir name of the given path. * For example for "/abc/somefile.txt" it will return "/abc" * * @param {String} path * @return {String} dir name */ dirname: function(path) { return path.replace(/\\/g,'/').replace(/\/[^\/]*$/, ''); }, /** * Do a search query and display the results * @param {string} query the search query */ search: _.debounce(function(query){ if(query){ OC.addStyle('search','results'); $.getJSON(OC.filePath('search','ajax','search.php')+'?query='+encodeURIComponent(query), function(results){ OC.search.lastResults=results; OC.search.showResults(results); }); } }, 500), /** * Dialog helper for jquery dialogs. * * @namespace OC.dialogs */ dialogs:OCdialogs, /** * Parses a URL query string into a JS map * @param {string} queryString query string in the format param1=1234¶m2=abcde¶m3=xyz * @return {Object.} map containing key/values matching the URL parameters */ parseQueryString:function(queryString){ var parts, pos, components, result = {}, key, value; if (!queryString){ return null; } pos = queryString.indexOf('?'); if (pos >= 0){ queryString = queryString.substr(pos + 1); } parts = queryString.replace(/\+/g, '%20').split('&'); for (var i = 0; i < parts.length; i++){ // split on first equal sign var part = parts[i]; pos = part.indexOf('='); if (pos >= 0) { components = [ part.substr(0, pos), part.substr(pos + 1) ]; } else { // key only components = [part]; } if (!components.length){ continue; } key = decodeURIComponent(components[0]); if (!key){ continue; } // if equal sign was there, return string if (components.length > 1) { result[key] = decodeURIComponent(components[1]); } // no equal sign => null value else { result[key] = null; } } return result; }, /** * Builds a URL query from a JS map. * @param {Object.} params map containing key/values matching the URL parameters * @return {string} String containing a URL query (without question) mark */ buildQueryString: function(params) { if (!params) { return ''; } return $.map(params, function(value, key) { var s = encodeURIComponent(key); if (value !== null && typeof(value) !== 'undefined') { s += '=' + encodeURIComponent(value); } return s; }).join('&'); }, /** * Opens a popup with the setting for an app. * @param {string} appid The ID of the app e.g. 'calendar', 'contacts' or 'files'. * @param {boolean|string} loadJS If true 'js/settings.js' is loaded. If it's a string * it will attempt to load a script by that name in the 'js' directory. * @param {boolean} [cache] If true the javascript file won't be forced refreshed. Defaults to true. * @param {string} [scriptName] The name of the PHP file to load. Defaults to 'settings.php' in * the root of the app directory hierarchy. */ appSettings:function(args) { if(typeof args === 'undefined' || typeof args.appid === 'undefined') { throw { name: 'MissingParameter', message: 'The parameter appid is missing' }; } var props = {scriptName:'settings.php', cache:true}; $.extend(props, args); var settings = $('#appsettings'); if(settings.length === 0) { throw { name: 'MissingDOMElement', message: 'There has be be an element with id "appsettings" for the popup to show.' }; } var popup = $('#appsettings_popup'); if(popup.length === 0) { $('body').prepend(''); popup = $('#appsettings_popup'); popup.addClass(settings.hasClass('topright') ? 'topright' : 'bottomleft'); } if(popup.is(':visible')) { popup.hide().remove(); } else { var arrowclass = settings.hasClass('topright') ? 'up' : 'left'; var jqxhr = $.get(OC.filePath(props.appid, '', props.scriptName), function(data) { popup.html(data).ready(function() { popup.prepend('

'+t('core', 'Settings')+'

').show(); popup.find('.close').bind('click', function() { popup.remove(); }); if(typeof props.loadJS !== 'undefined') { var scriptname; if(props.loadJS === true) { scriptname = 'settings.js'; } else if(typeof props.loadJS === 'string') { scriptname = props.loadJS; } else { throw { name: 'InvalidParameter', message: 'The "loadJS" parameter must be either boolean or a string.' }; } if(props.cache) { $.ajaxSetup({cache: true}); } $.getScript(OC.filePath(props.appid, 'js', scriptname)) .fail(function(jqxhr, settings, e) { throw e; }); } if(!OC.Util.hasSVGSupport()) { OC.Util.replaceSVG(); } }).show(); }, 'html'); } }, /** * For menu toggling * @todo Write documentation */ registerMenu: function($toggle, $menuEl) { $menuEl.addClass('menu'); $toggle.on('click.menu', function(event) { if ($menuEl.is(OC._currentMenu)) { $menuEl.slideUp(OC.menuSpeed); OC._currentMenu = null; OC._currentMenuToggle = null; return false; } // another menu was open? else if (OC._currentMenu) { // close it OC._currentMenu.hide(); } $menuEl.slideToggle(OC.menuSpeed); OC._currentMenu = $menuEl; OC._currentMenuToggle = $toggle; return false; }); }, /** * @todo Write documentation */ unregisterMenu: function($toggle, $menuEl) { // close menu if opened if ($menuEl.is(OC._currentMenu)) { $menuEl.slideUp(OC.menuSpeed); OC._currentMenu = null; OC._currentMenuToggle = null; } $toggle.off('click.menu').removeClass('menutoggle'); $menuEl.removeClass('menu'); }, /** * Wrapper for matchMedia * * This is makes it possible for unit tests to * stub matchMedia (which doesn't work in PhantomJS) * @private */ _matchMedia: function(media) { if (window.matchMedia) { return window.matchMedia(media); } return false; }, /** * Returns the user's locale * * @return {String} locale string */ getLocale: function() { return $('html').prop('lang'); } }; /** * @namespace OC.search */ OC.search.customResults={}; OC.search.currentResult=-1; OC.search.lastQuery=''; OC.search.lastResults={}; OC.addStyle.loaded=[]; OC.addScript.loaded=[]; /** * @todo Write documentation */ OC.msg={ /** * @param selector * @todo Write documentation */ startSaving:function(selector){ OC.msg.startAction(selector, t('core', 'Saving...')); }, /** * @param selector * @param data * @todo Write documentation */ finishedSaving:function(selector, data){ OC.msg.finishedAction(selector, data); }, /** * @param selector * @param {string} message Message to display * @todo WRite documentation */ startAction:function(selector, message){ $(selector) .html( message ) .removeClass('success') .removeClass('error') .stop(true, true) .show(); }, /** * @param selector * @param data * @todo Write documentation */ finishedAction:function(selector, data){ if( data.status === "success" ){ $(selector).html( data.data.message ) .addClass('success') .removeClass('error') .stop(true, true) .delay(3000) .fadeOut(900) .show(); }else{ $(selector).html( data.data.message ) .addClass('error') .removeClass('success') .show(); } } }; /** * @todo Write documentation * @namespace */ OC.Notification={ queuedNotifications: [], getDefaultNotificationFunction: null, /** * @param callback * @todo Write documentation */ setDefault: function(callback) { OC.Notification.getDefaultNotificationFunction = callback; }, /** * Hides a notification * @param callback * @todo Write documentation */ hide: function(callback) { $('#notification').fadeOut('400', function(){ if (OC.Notification.isHidden()) { if (OC.Notification.getDefaultNotificationFunction) { OC.Notification.getDefaultNotificationFunction.call(); } } if (callback) { callback.call(); } $('#notification').empty(); if(OC.Notification.queuedNotifications.length > 0){ OC.Notification.showHtml(OC.Notification.queuedNotifications[0]); OC.Notification.queuedNotifications.shift(); } }); }, /** * Shows a notification as HTML without being sanitized before. * If you pass unsanitized user input this may lead to a XSS vulnerability. * Consider using show() instead of showHTML() * @param {string} html Message to display */ showHtml: function(html) { var notification = $('#notification'); if((notification.filter('span.undo').length == 1) || OC.Notification.isHidden()){ notification.html(html); notification.fadeIn().css('display','inline-block'); }else{ OC.Notification.queuedNotifications.push(html); } }, /** * Shows a sanitized notification * @param {string} text Message to display */ show: function(text) { var notification = $('#notification'); if((notification.filter('span.undo').length == 1) || OC.Notification.isHidden()){ notification.text(text); notification.fadeIn().css('display','inline-block'); }else{ OC.Notification.queuedNotifications.push($('
').text(text).html()); } }, /** * Returns whether a notification is hidden. * @return {boolean} */ isHidden: function() { return ($("#notification").text() === ''); } }; /** * Breadcrumb class * * @namespace * * @deprecated will be replaced by the breadcrumb implementation * of the files app in the future */ OC.Breadcrumb={ container:null, /** * @todo Write documentation * @param dir * @param leafName * @param leafLink */ show:function(dir, leafName, leafLink){ if(!this.container){//default this.container=$('#controls'); } this._show(this.container, dir, leafName, leafLink); }, _show:function(container, dir, leafname, leaflink){ var self = this; this._clear(container); // show home + path in subdirectories if (dir) { //add home var link = OC.linkTo('files','index.php'); var crumb=$('
'); crumb.addClass('crumb'); var crumbLink=$(''); crumbLink.attr('href',link); var crumbImg=$(''); crumbImg.attr('src',OC.imagePath('core','places/home')); crumbLink.append(crumbImg); crumb.append(crumbLink); container.prepend(crumb); //add path parts var segments = dir.split('/'); var pathurl = ''; jQuery.each(segments, function(i,name) { if (name !== '') { pathurl = pathurl+'/'+name; var link = OC.linkTo('files','index.php')+'?dir='+encodeURIComponent(pathurl); self._push(container, name, link); } }); } //add leafname if (leafname && leaflink) { this._push(container, leafname, leaflink); } }, /** * @todo Write documentation * @param {string} name * @param {string} link */ push:function(name, link){ if(!this.container){//default this.container=$('#controls'); } return this._push(OC.Breadcrumb.container, name, link); }, _push:function(container, name, link){ var crumb=$('
'); crumb.addClass('crumb').addClass('last'); var crumbLink=$(''); crumbLink.attr('href',link); crumbLink.text(name); crumb.append(crumbLink); var existing=container.find('div.crumb'); if(existing.length){ existing.removeClass('last'); existing.last().after(crumb); }else{ container.prepend(crumb); } return crumb; }, /** * @todo Write documentation */ pop:function(){ if(!this.container){//default this.container=$('#controls'); } this.container.find('div.crumb').last().remove(); this.container.find('div.crumb').last().addClass('last'); }, /** * @todo Write documentation */ clear:function(){ if(!this.container){//default this.container=$('#controls'); } this._clear(this.container); }, _clear:function(container) { container.find('div.crumb').remove(); } }; if(typeof localStorage !=='undefined' && localStorage !== null){ /** * User and instance aware localstorage * @namespace */ OC.localStorage={ namespace:'oc_'+OC.currentUser+'_'+OC.webroot+'_', /** * Whether the storage contains items * @param {string} name * @return {boolean} */ hasItem:function(name){ return OC.localStorage.getItem(name)!==null; }, /** * Add an item to the storage * @param {string} name * @param {string} item */ setItem:function(name,item){ return localStorage.setItem(OC.localStorage.namespace+name,JSON.stringify(item)); }, /** * Removes an item from the storage * @param {string} name * @param {string} item */ removeItem:function(name,item){ return localStorage.removeItem(OC.localStorage.namespace+name); }, /** * Get an item from the storage * @param {string} name * @return {null|string} */ getItem:function(name){ var item = localStorage.getItem(OC.localStorage.namespace+name); if(item === null) { return null; } else if (typeof JSON === 'undefined') { //fallback to jquery for IE6/7/8 return $.parseJSON(item); } else { return JSON.parse(item); } } }; }else{ //dummy localstorage OC.localStorage={ hasItem:function(){ return false; }, setItem:function(){ return false; }, getItem:function(){ return null; } }; } /** * check if the browser support svg images * @return {boolean} */ function SVGSupport() { return SVGSupport.checkMimeType.correct && !!document.createElementNS && !!document.createElementNS('http://www.w3.org/2000/svg', "svg").createSVGRect; } SVGSupport.checkMimeType=function(){ $.ajax({ url: OC.imagePath('core','breadcrumb.svg'), success:function(data,text,xhr){ var headerParts=xhr.getAllResponseHeaders().split("\n"); var headers={}; $.each(headerParts,function(i,text){ if(text){ var parts=text.split(':',2); if(parts.length===2){ var value=parts[1].trim(); if(value[0]==='"'){ value=value.substr(1,value.length-2); } headers[parts[0].toLowerCase()]=value; } } }); if(headers["content-type"]!=='image/svg+xml'){ OC.Util.replaceSVG(); SVGSupport.checkMimeType.correct=false; } } }); }; SVGSupport.checkMimeType.correct=true; /** * Replace all svg images with png for browser compatibility * @param $el * @deprecated use OC.Util.replaceSVG instead */ function replaceSVG($el){ return OC.Util.replaceSVG($el); } /** * prototypical inheritance functions * @todo Write documentation * usage: * MySubObject=object(MyObject) */ function object(o) { function F() {} F.prototype = o; return new F(); } /** * Initializes core */ function initCore() { /** * Set users locale to moment.js as soon as possible */ moment.locale(OC.getLocale()); /** * Calls the server periodically to ensure that session doesn't * time out */ function initSessionHeartBeat(){ // max interval in seconds set to 24 hours var maxInterval = 24 * 3600; // interval in seconds var interval = 900; if (oc_config.session_lifetime) { interval = Math.floor(oc_config.session_lifetime / 2); } // minimum one minute if (interval < 60) { interval = 60; } if (interval > maxInterval) { interval = maxInterval; } var url = OC.generateUrl('/heartbeat'); setInterval(function(){ $.post(url); }, interval * 1000); } // session heartbeat (defaults to enabled) if (typeof(oc_config.session_keepalive) === 'undefined' || !!oc_config.session_keepalive) { initSessionHeartBeat(); } if(!OC.Util.hasSVGSupport()){ //replace all svg images with png images for browser that dont support svg OC.Util.replaceSVG(); }else{ SVGSupport.checkMimeType(); } $('form.searchbox').submit(function(event){ event.preventDefault(); }); $('#searchbox').keyup(function(event){ if(event.keyCode===13){//enter if(OC.search.currentResult>-1){ var result=$('#searchresults tr.result a')[OC.search.currentResult]; window.location = $(result).attr('href'); } }else if(event.keyCode===38){//up if(OC.search.currentResult>0){ OC.search.currentResult--; OC.search.renderCurrent(); } }else if(event.keyCode===40){//down if(OC.search.lastResults.length>OC.search.currentResult+1){ OC.search.currentResult++; OC.search.renderCurrent(); } }else if(event.keyCode===27){//esc OC.search.hide(); if (FileList && typeof FileList.unfilter === 'function') { //TODO add hook system FileList.unfilter(); } }else{ var query=$('#searchbox').val(); if(OC.search.lastQuery!==query){ OC.search.lastQuery=query; OC.search.currentResult=-1; if (FileList && typeof FileList.filter === 'function') { //TODO add hook system FileList.filter(query); } if(query.length>2){ OC.search(query); }else{ if(OC.search.hide){ OC.search.hide(); } } } } }); var setShowPassword = function(input, label) { input.showPassword().keyup(); }; setShowPassword($('#adminpass'), $('label[for=show]')); setShowPassword($('#pass2'), $('label[for=personal-show]')); setShowPassword($('#dbpass'), $('label[for=dbpassword]')); var checkShowCredentials = function() { var empty = false; $('input#user, input#password').each(function() { if ($(this).val() === '') { empty = true; } }); if(empty) { $('#submit').fadeOut(); $('#remember_login').hide(); $('#remember_login+label').fadeOut(); } else { $('#submit').fadeIn(); $('#remember_login').show(); $('#remember_login+label').fadeIn(); } }; // hide log in button etc. when form fields not filled // commented out due to some browsers having issues with it // checkShowCredentials(); // $('input#user, input#password').keyup(checkShowCredentials); // user menu $('#settings #expand').keydown(function(event) { if (event.which === 13 || event.which === 32) { $('#expand').click(); } }); $('#settings #expand').click(function(event) { $('#settings #expanddiv').slideToggle(OC.menuSpeed); event.stopPropagation(); }); $('#settings #expanddiv').click(function(event){ event.stopPropagation(); }); //hide the user menu when clicking outside it $(document).click(function(){ $('#settings #expanddiv').slideUp(OC.menuSpeed); }); // all the tipsy stuff needs to be here (in reverse order) to work $('.displayName .action').tipsy({gravity:'se', fade:true, live:true}); $('.password .action').tipsy({gravity:'se', fade:true, live:true}); $('#upload').tipsy({gravity:'w', fade:true}); $('.selectedActions a').tipsy({gravity:'s', fade:true, live:true}); $('a.action.delete').tipsy({gravity:'e', fade:true, live:true}); $('a.action').tipsy({gravity:'s', fade:true, live:true}); $('td .modified').tipsy({gravity:'s', fade:true, live:true}); $('td.lastLogin').tipsy({gravity:'s', fade:true, html:true}); $('input').tipsy({gravity:'w', fade:true}); $('.extra-data').tipsy({gravity:'w', fade:true, live:true}); // toggle for menus $(document).on('mouseup.closemenus', function(event) { var $el = $(event.target); if ($el.closest('.menu').length || $el.closest('.menutoggle').length) { // don't close when clicking on the menu directly or a menu toggle return false; } if (OC._currentMenu) { OC._currentMenu.slideUp(OC.menuSpeed); } OC._currentMenu = null; OC._currentMenuToggle = null; }); /** * Set up the main menu toggle to react to media query changes. * If the screen is small enough, the main menu becomes a toggle. * If the screen is bigger, the main menu is not a toggle any more. */ function setupMainMenu() { // toggle the navigation var $toggle = $('#header .menutoggle'); var $navigation = $('#navigation'); // init the menu OC.registerMenu($toggle, $navigation); $toggle.data('oldhref', $toggle.attr('href')); $toggle.attr('href', '#'); $navigation.hide(); // show loading feedback $navigation.delegate('a', 'click', function(event) { var $app = $(event.target); if(!$app.is('a')) { $app = $app.closest('a'); } if(!event.ctrlKey) { $app.addClass('app-loading'); } }); } setupMainMenu(); // just add snapper for logged in users if($('#app-navigation').length && !$('html').hasClass('lte9')) { // App sidebar on mobile var snapper = new Snap({ element: document.getElementById('app-content'), disable: 'right', maxPosition: 250 }); $('#app-content').prepend(''); $('#app-navigation-toggle').click(function(){ if(snapper.state().state == 'left'){ snapper.close(); } else { snapper.open('left'); } }); // close sidebar when switching navigation entry var $appNavigation = $('#app-navigation'); $appNavigation.delegate('a', 'click', function(event) { var $target = $(event.target); // don't hide navigation when changing settings or adding things if($target.is('.app-navigation-noclose') || $target.closest('.app-navigation-noclose').length) { return; } if($target.is('.add-new') || $target.closest('.add-new').length) { return; } if($target.is('#app-settings') || $target.closest('#app-settings').length) { return; } snapper.close(); }); var toggleSnapperOnSize = function() { if($(window).width() > 768) { snapper.close(); snapper.disable(); } else { snapper.enable(); } }; $(window).resize(_.debounce(toggleSnapperOnSize, 250)); // initial call toggleSnapperOnSize(); } } $(document).ready(initCore); /** * Filter Jquery selector by attribute value */ $.fn.filterAttr = function(attr_name, attr_value) { return this.filter(function() { return $(this).attr(attr_name) === attr_value; }); }; /** * Returns a human readable file size * @param {number} size Size in bytes * @param {boolean} skipSmallSizes return '< 1 kB' for small files * @return {string} */ function humanFileSize(size, skipSmallSizes) { var humanList = ['B', 'kB', 'MB', 'GB', 'TB']; // Calculate Log with base 1024: size = 1024 ** order var order = size?Math.floor(Math.log(size) / Math.log(1024)):0; // Stay in range of the byte sizes that are defined order = Math.min(humanList.length - 1, order); var readableFormat = humanList[order]; var relativeSize = (size / Math.pow(1024, order)).toFixed(1); if(skipSmallSizes === true && order === 0) { if(relativeSize !== "0.0"){ return '< 1 kB'; } else { return '0 kB'; } } if(order < 2){ relativeSize = parseFloat(relativeSize).toFixed(0); } else if(relativeSize.substr(relativeSize.length-2,2)==='.0'){ relativeSize=relativeSize.substr(0,relativeSize.length-2); } return relativeSize + ' ' + readableFormat; } /** * Format an UNIX timestamp to a human understandable format * @param {number} timestamp UNIX timestamp * @return {string} Human readable format */ function formatDate(timestamp){ return OC.Util.formatDate(timestamp); } // /** * Get the value of a URL parameter * @link http://stackoverflow.com/questions/1403888/get-url-parameter-with-jquery * @param {string} name URL parameter * @return {string} */ function getURLParameter(name) { return decodeURI( (RegExp(name + '=' + '(.+?)(&|$)').exec(location.search) || [, null])[1] ); } /** * Takes an absolute timestamp and return a string with a human-friendly relative date * @param {number} timestamp A Unix timestamp */ function relative_modified_date(timestamp) { /* Were multiplying by 1000 to bring the timestamp back to its original value per https://github.com/owncloud/core/pull/10647#discussion_r16790315 */ return OC.Util.relativeModifiedDate(timestamp * 1000); } /** * Utility functions * @namespace */ OC.Util = { // TODO: remove original functions from global namespace humanFileSize: humanFileSize, /** * @param timestamp * @param format * @returns {string} timestamp formatted as requested */ formatDate: function (timestamp, format) { format = format || "MMMM D, YYYY h:mm"; return moment(timestamp).format(format); }, /** * @param timestamp * @returns {string} human readable difference from now */ relativeModifiedDate: function (timestamp) { return moment(timestamp).fromNow(); }, /** * Returns whether the browser supports SVG * @return {boolean} true if the browser supports SVG, false otherwise */ // TODO: replace with original function hasSVGSupport: SVGSupport, /** * If SVG is not supported, replaces the given icon's extension * from ".svg" to ".png". * If SVG is supported, return the image path as is. * @param {string} file image path with svg extension * @return {string} fixed image path with png extension if SVG is not supported */ replaceSVGIcon: function(file) { if (file && !OC.Util.hasSVGSupport()) { var i = file.lastIndexOf('.svg'); if (i >= 0) { file = file.substr(0, i) + '.png' + file.substr(i+4); } } return file; }, /** * Replace SVG images in all elements that have the "svg" class set * with PNG images. * * @param $el root element from which to search, defaults to $('body') */ replaceSVG: function($el) { if (!$el) { $el = $('body'); } $el.find('img.svg').each(function(index,element){ element=$(element); var src=element.attr('src'); element.attr('src',src.substr(0, src.length-3) + 'png'); }); $el.find('.svg').each(function(index,element){ element = $(element); var background = element.css('background-image'); if (background){ var i = background.lastIndexOf('.svg'); if (i >= 0){ background = background.substr(0,i) + '.png' + background.substr(i + 4); element.css('background-image', background); } } element.find('*').each(function(index, element) { element = $(element); var background = element.css('background-image'); if (background) { var i = background.lastIndexOf('.svg'); if(i >= 0){ background = background.substr(0,i) + '.png' + background.substr(i + 4); element.css('background-image', background); } } }); }); }, /** * Remove the time component from a given date * * @param {Date} date date * @return {Date} date with stripped time */ stripTime: function(date) { // FIXME: likely to break when crossing DST // would be better to use a library like momentJS return new Date(date.getFullYear(), date.getMonth(), date.getDate()); }, _chunkify: function(t) { // Adapted from http://my.opera.com/GreyWyvern/blog/show.dml/1671288 var tz = [], x = 0, y = -1, n = 0, code, c; while (x < t.length) { c = t.charAt(x); // only include the dot in strings var m = ((!n && c === '.') || (c >= '0' && c <= '9')); if (m !== n) { // next chunk y++; tz[y] = ''; n = m; } tz[y] += c; x++; } return tz; }, /** * Compare two strings to provide a natural sort * @param a first string to compare * @param b second string to compare * @return -1 if b comes before a, 1 if a comes before b * or 0 if the strings are identical */ naturalSortCompare: function(a, b) { var x; var aa = OC.Util._chunkify(a); var bb = OC.Util._chunkify(b); for (x = 0; aa[x] && bb[x]; x++) { if (aa[x] !== bb[x]) { var aNum = Number(aa[x]), bNum = Number(bb[x]); // note: == is correct here if (aNum == aa[x] && bNum == bb[x]) { return aNum - bNum; } else { // Forcing 'en' locale to match the server-side locale which is // always 'en'. // // Note: This setting isn't supported by all browsers but for the ones // that do there will be more consistency between client-server sorting return aa[x].localeCompare(bb[x], 'en'); } } } return aa.length - bb.length; } } /** * Utility class for the history API, * includes fallback to using the URL hash when * the browser doesn't support the history API. * * @namespace */ OC.Util.History = { _handlers: [], /** * Push the current URL parameters to the history stack * and change the visible URL. * Note: this includes a workaround for IE8/IE9 that uses * the hash part instead of the search part. * * @param params to append to the URL, can be either a string * or a map */ pushState: function(params) { var strParams; if (typeof(params) === 'string') { strParams = params; } else { strParams = OC.buildQueryString(params); } if (window.history.pushState) { var url = location.pathname + '?' + strParams; window.history.pushState(params, '', url); } // use URL hash for IE8 else { window.location.hash = '?' + strParams; // inhibit next onhashchange that just added itself // to the event queue this._cancelPop = true; } }, /** * Add a popstate handler * * @param handler function */ addOnPopStateHandler: function(handler) { this._handlers.push(handler); }, /** * Parse a query string from the hash part of the URL. * (workaround for IE8 / IE9) */ _parseHashQuery: function() { var hash = window.location.hash, pos = hash.indexOf('?'); if (pos >= 0) { return hash.substr(pos + 1); } if (hash.length) { // remove hash sign return hash.substr(1); } return ''; }, _decodeQuery: function(query) { return query.replace(/\+/g, ' '); }, /** * Parse the query/search part of the URL. * Also try and parse it from the URL hash (for IE8) * * @return map of parameters */ parseUrlQuery: function() { var query = this._parseHashQuery(), params; // try and parse from URL hash first if (query) { params = OC.parseQueryString(this._decodeQuery(query)); } // else read from query attributes if (!params) { params = OC.parseQueryString(this._decodeQuery(location.search)); } return params || {}; }, _onPopState: function(e) { if (this._cancelPop) { this._cancelPop = false; return; } var params; if (!this._handlers.length) { return; } params = (e && e.state) || this.parseUrlQuery() || {}; for (var i = 0; i < this._handlers.length; i++) { this._handlers[i](params); } } }; // fallback to hashchange when no history support if (window.history.pushState) { window.onpopstate = _.bind(OC.Util.History._onPopState, OC.Util.History); } else { $(window).on('hashchange', _.bind(OC.Util.History._onPopState, OC.Util.History)); } /** * Get a variable by name * @param {string} name * @return {*} */ OC.get=function(name) { var namespaces = name.split("."); var tail = namespaces.pop(); var context=window; for(var i = 0; i < namespaces.length; i++) { context = context[namespaces[i]]; if(!context){ return false; } } return context[tail]; }; /** * Set a variable by name * @param {string} name * @param {*} value */ OC.set=function(name, value) { var namespaces = name.split("."); var tail = namespaces.pop(); var context=window; for(var i = 0; i < namespaces.length; i++) { if(!context[namespaces[i]]){ context[namespaces[i]]={}; } context = context[namespaces[i]]; } context[tail]=value; }; // fix device width on windows phone (function() { if ("-ms-user-select" in document.documentElement.style && navigator.userAgent.match(/IEMobile\/10\.0/)) { var msViewportStyle = document.createElement("style"); msViewportStyle.appendChild( document.createTextNode("@-ms-viewport{width:auto!important}") ); document.getElementsByTagName("head")[0].appendChild(msViewportStyle); } })(); /** * Namespace for apps * @namespace OCA */ window.OCA = {}; /** * select a range in an input field * @link http://stackoverflow.com/questions/499126/jquery-set-cursor-position-in-text-area * @param {type} start * @param {type} end */ jQuery.fn.selectRange = function(start, end) { return this.each(function() { if (this.setSelectionRange) { this.focus(); this.setSelectionRange(start, end); } else if (this.createTextRange) { var range = this.createTextRange(); range.collapse(true); range.moveEnd('character', end); range.moveStart('character', start); range.select(); } }); }; /** * check if an element exists. * allows you to write if ($('#myid').exists()) to increase readability * @link http://stackoverflow.com/questions/31044/is-there-an-exists-function-for-jquery */ jQuery.fn.exists = function(){ return this.length > 0; }; ption value='backport/48522/stable30'>backport/48522/stable30 Nextcloud server, a safe home for all your data: https://github.com/nextcloud/serverwww-data
aboutsummaryrefslogtreecommitdiffstats
blob: 5974659e16bfe5575cfa2db760862789000e9566 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
<?php
/**
 * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
 * SPDX-License-Identifier: AGPL-3.0-or-later
 */
namespace OCP\RichObjectStrings;

/**
 * Class Definitions
 *
 * @since 11.0.0
 */
class Definitions {
	/**
	 * @var array
	 * @since 11.0.0
	 */
	public $definitions = [
		'addressbook' => [
			'author' => 'Nextcloud',
			'app' => 'dav',
			'since' => '11.0.0',
			'parameters' => [
				'id' => [
					'since' => '11.0.0',
					'required' => true,
					'description' => 'The id used to identify the addressbook on the instance',
					'example' => '42',
				],
				'name' => [
					'since' => '11.0.0',
					'required' => true,
					'description' => 'The display name of the addressbook which should be used in the visual representation',
					'example' => 'Contacts',
				],
			],
		],
		'addressbook-contact' => [
			'author' => 'Nextcloud',
			'app' => 'dav',
			'since' => '11.0.0',
			'parameters' => [
				'id' => [
					'since' => '11.0.0',
					'required' => true,
					'description' => 'The id used to identify the contact on the instance',
					'example' => '42',
				],
				'name' => [
					'since' => '11.0.0',
					'required' => true,
					'description' => 'The display name of the contact which should be used in the visual representation',
					'example' => 'John Doe',
				],
			],
		],
		'announcement' => [
			'author' => 'Joas Schilling',
			'app' => 'announcementcenter',
			'since' => '11.0.0',
			'parameters' => [
				'id' => [
					'since' => '11.0.0',
					'required' => true,
					'description' => 'The id used to identify the announcement on the instance',
					'example' => '42',
				],
				'name' => [
					'since' => '11.0.0',
					'required' => true,
					'description' => 'The announcement subject which should be used in the visual representation',
					'example' => 'file.txt',
				],
				'link' => [
					'since' => '11.0.0',
					'required' => false,
					'description' => 'The full URL to the file',
					'example' => 'http://localhost/index.php/apps/announcements/#23',
				],
			],
		],
		'app' => [
			'author' => 'Nextcloud',
			'app' => 'updatenotification',
			'since' => '11.0.0',
			'parameters' => [
				'id' => [
					'since' => '11.0.0',
					'required' => true,
					'description' => 'The app id',
					'example' => 'updatenotification',
				],
				'name' => [
					'since' => '11.0.0',
					'required' => true,
					'description' => 'The name of the app which should be used in the visual representation',
					'example' => 'Update notification',
				],
			],
		],
		'calendar' => [
			'author' => 'Nextcloud',
			'app' => 'dav',
			'since' => '11.0.0',
			'parameters' => [
				'id' => [
					'since' => '11.0.0',
					'required' => true,
					'description' => 'The id used to identify the calendar on the instance',
					'example' => '42',
				],
				'name' => [
					'since' => '11.0.0',
					'required' => true,
					'description' => 'The display name of the calendar which should be used in the visual representation',
					'example' => 'Personal',
				],
			],
		],
		'calendar-event' => [
			'author' => 'Nextcloud',
			'app' => 'dav',
			'since' => '11.0.0',
			'parameters' => [
				'id' => [
					'since' => '11.0.0',
					'required' => true,
					'description' => 'The id used to identify the event on the instance',
					'example' => '42',
				],
				'name' => [
					'since' => '11.0.0',
					'required' => true,
					'description' => 'The display name of the event which should be used in the visual representation',
					'example' => 'Workout',
				],
				'link' => [
					'since' => '19.0.0',
					'required' => false,
					'description' => 'A link to the page displaying the calendar',
					'example' => 'http://localhost/index.php/apps/calendar/dayGridMonth/2020-01-20/edit/sidebar/base64string/1579046400'
				]
			],
		],
		'call' => [
			'author' => 'Nextcloud',
			'app' => 'spreed',
			'since' => '11.0.2',
			'parameters' => [
				'id' => [
					'since' => '11.0.2',
					'required' => true,
					'description' => 'The id used to identify the call on the instance',
					'example' => '42',
				],
				'name' => [
					'since' => '11.0.2',
					'required' => true,
					'description' => 'The display name of the call which should be used in the visual representation',
					'example' => 'Company call',
				],
				'call-type' => [
					'since' => '11.0.2',
					'required' => true,
					'description' => 'The type of the call: one2one, group or public',
					'example' => 'one2one',
				],
				'link' => [
					'since' => '19.0.0',
					'required' => false,
					'description' => 'The link to the conversation',
					'example' => 'https://localhost/index.php/call/R4nd0mToken',
				],
				'icon-url' => [
					'since' => '27.0.0',
					'required' => false,
					'description' => 'The icon url to use as avatar',
					'example' => 'https://localhost/ocs/v2.php/apps/spreed/api/v1/room/R4nd0mToken/avatar'
				],
				'message-id' => [
					'since' => '27.0.0',
					'required' => false,
					'description' => 'The id of a message that was referred to',
					'example' => '12345',
				],
			],
		],
		'circle' => [
			'author' => 'Maxence Lange',
			'app' => 'circles',
			'since' => '12.0.0',
			'parameters' => [
				'id' => [
					'since' => '12.0.0',
					'required' => true,
					'description' => 'The id used to identify the circle on the instance',
					'example' => '42',
				],
				'name' => [
					'since' => '12.0.0',
					'required' => true,
					'description' => 'The display name of the circle which should be used in the visual representation',
					'example' => 'My friends',
				],
				'link' => [
					'since' => '12.0.0',
					'required' => true,
					'description' => 'The full URL to the circle',
					'example' => 'http://localhost/index.php/apps/circles/#42',
				],
			],
		],
		'deck-board' => [
			'author' => 'Nextcloud',
			'app' => 'deck',
			'since' => '21.0.0',
			'parameters' => [
				'id' => [
					'since' => '21.0.0',
					'required' => true,
					'description' => 'The id used to identify the board on the instance',
					'example' => '1',
				],
				'name' => [
					'since' => '21.0.0',
					'required' => true,
					'description' => 'The display name of the deck board',
					'example' => 'Personal',
				],
				'link' => [
					'since' => '21.0.0',
					'required' => true,
					'description' => 'The full URL to the board',
					'example' => 'http://localhost/index.php/apps/deck/#/board/1',
				],
			],
		],
		'deck-card' => [
			'author' => 'Nextcloud',
			'app' => 'deck',
			'since' => '21.0.0',
			'parameters' => [
				'id' => [
					'since' => '21.0.0',
					'required' => true,
					'description' => 'The id used to identify the card on the instance',
					'example' => '1',
				],
				'name' => [
					'since' => '21.0.0',
					'required' => true,
					'description' => 'The title of the deck card',
					'example' => 'Foo Bar',
				],
				'boardname' => [
					'since' => '21.0.0',
					'required' => true,
					'description' => 'The display name of board which contains the card',
					'example' => 'Personal',
				],
				'stackname' => [
					'since' => '21.0.0',
					'required' => true,
					'description' => 'The display name of the stack which contains the card in the board',
					'example' => 'To do',
				],
				'link' => [
					'since' => '21.0.0',
					'required' => true,
					'description' => 'The full URL to the card directly',
					'example' => 'https://nextcloud21.local/index.php/apps/deck/#/board/1/card/1',
				],
			],
		],
		'email' => [
			'author' => 'Nextcloud',
			'app' => 'sharebymail',
			'since' => '11.0.0',
			'parameters' => [
				'id' => [
					'since' => '11.0.0',
					'required' => true,
					'description' => 'The mail-address used to identify the event on the instance',
					'example' => 'test@localhost',
				],
				'name' => [
					'since' => '11.0.0',
					'required' => true,
					'description' => 'The display name of a matching contact or the email (fallback) which should be used in the visual representation',
					'example' => 'Foo Bar',
				],
			],
		],
		'file' => [
			'author' => 'Nextcloud',
			'app' => 'dav',
			'since' => '11.0.0',
			'parameters' => [
				'id' => [
					'since' => '11.0.0',
					'required' => true,
					'description' => 'The id used to identify the file on the instance',
					'example' => '42',
				],
				'name' => [
					'since' => '11.0.0',
					'required' => true,
					'description' => 'The file name which should be used in the visual representation',
					'example' => 'file.txt',
				],
				'size' => [
					'since' => '21.0.0',
					'required' => false,
					'description' => 'The file size in bytes',
					'example' => '3145728',
				],
				'path' => [
					'since' => '11.0.0',
					'required' => true,
					'description' => 'The full path of the file for the user, should not start with a slash',
					'example' => 'path/to/file.txt',
				],
				'link' => [
					'since' => '11.0.0',
					'required' => false,
					'description' => 'The full URL to the file',
					'example' => 'http://localhost/index.php/f/42',
				],
				'mimetype' => [
					'since' => '16.0.0',
					'required' => false,
					'description' => 'The mimetype of the file/folder to allow clients to show a placeholder',
					'example' => 'text/plain',
				],
				'preview-available' => [
					'since' => '16.0.0',
					'required' => false,
					'description' => 'Whether or not a preview is available. If `no` the mimetype icon should be used',
					'example' => 'yes',
				],
				'mtime' => [
					'since' => '25.0.0',
					'required' => false,
					'description' => 'The mtime of the file/folder as unix timestamp',
					'example' => '1661854213',
				],
				'etag' => [
					'since' => '25.0.0',
					'required' => false,
					'description' => 'The ETag of the file/folder',
					'example' => 'abcdefghi',
				],
				'permissions' => [
					'since' => '25.0.0',
					'required' => false,
					'description' => 'The permissions on the file/folder',
					'example' => '3',
				],
				'width' => [
					'since' => '29.0.0',
					'required' => false,
					'description' => 'The width in pixels if the file is an image',
					'example' => '1920',
				],
				'height' => [
					'since' => '29.0.0',
					'required' => false,
					'description' => 'The height in pixels if the file is an image',
					'example' => '1080',
				],
				'blurhash' => [
					'since' => '30.0.0',
					'required' => false,
					'description' => 'The blurhash of the image',
					'example' => 'LEHV9uae2yk8pyo0adR*.7kCMdnj',
				],
			],
		],
		'forms-form' => [
			'author' => 'Nextcloud',
			'app' => 'forms',
			'since' => '21.0.1',
			'parameters' => [
				'id' => [
					'since' => '21.0.1',
					'required' => true,
					'description' => 'The form-hash of the form',
					'example' => 'q72GGqbfbLBC6xNB',
				],
				'name' => [
					'since' => '21.0.1',
					'required' => true,
					'description' => 'The title of the form',
					'example' => 'Nice Form',
				],
				'link' => [
					'since' => '21.0.1',
					'required' => true,
					'description' => 'The full URL to the board',
					'example' => 'http://localhost/index.php/apps/forms/q72GGqbfbLBC6xNB',
				],
			],
		],
		'guest' => [
			'author' => 'Nextcloud',
			'app' => 'spreed',
			'since' => '17.0.0',
			'parameters' => [
				'id' => [
					'since' => '17.0.0',
					'required' => true,
					'description' => 'The id used to identify the guest user',
					'example' => '42',
				],
				'name' => [
					'since' => '17.0.0',
					'required' => true,
					'description' => 'Potential displayname of the guest user',
					'example' => 'Foobar Cats',
				],
			],
		],
		'highlight' => [
			'author' => 'Nextcloud',
			'app' => 'core',
			'since' => '13.0.0',
			'parameters' => [
				'id' => [
					'since' => '13.0.0',
					'required' => true,
					'description' => 'The id used to identify the highlighted object on the instance',
					'example' => '42',
				],
				'name' => [
					'since' => '13.0.0',
					'required' => true,
					'description' => 'The string that should be highlighted.',
					'example' => 'Hello World',
				],
				'link' => [
					'since' => '13.0.0',
					'required' => false,
					'description' => 'The full URL that should be opened when clicking the highlighted text.',
					'example' => 'http://localhost/index.php/f/42',
				],
			],
		],
		'geo-location' => [
			'author' => 'Nextcloud',
			'app' => 'core',
			'since' => '22.0.0',
			'parameters' => [
				'id' => [
					'since' => '22.0.0',
					'required' => true,
					'description' => 'The geo URI (https://en.wikipedia.org/wiki/Geo_URI_scheme) to identify the location',
					'example' => 'geo:52.5450511,13.3741463',
				],
				'name' => [
					'since' => '22.0.0',
					'required' => true,
					'description' => 'A description of the location',
					'example' => 'Nextcloud Berlin Office',
				],
				'latitude' => [
					'since' => '22.0.0',
					'required' => true,
					'description' => 'The latitude of the location MUST be the same as in the id',
					'example' => '52.5450511',
				],
				'longitude' => [
					'since' => '22.0.0',
					'required' => true,
					'description' => 'The longitude of the location MUST be the same as in the id',
					'example' => '13.3741463',
				],
			],
		],
		'open-graph' => [
			'author' => 'Maxence Lange',
			'app' => 'mood',
			'since' => '12.0.0',
			'parameters' => [
				'id' => [
					'since' => '12.0.0',
					'required' => true,
					'description' => 'The id used to identify the open graph data on the instance',
					'example' => '42',
				],
				'name' => [
					'since' => '12.0.0',
					'required' => true,
					'description' => 'The open graph title of the website',
					'example' => 'This is a website',
				],
				'description' => [
					'since' => '12.0.0',
					'required' => false,
					'description' => 'The open graph description from the website',
					'example' => 'This is the description of the website',
				],
				'thumb' => [
					'since' => '12.0.0',
					'required' => false,
					'description' => 'The full URL of the open graph thumbnail',
					'example' => 'http://localhost/index.php/apps/mood/data/image?url=https%3A%2F%2Fthumb.example.com%2Fimage.png',
				],
				'website' => [
					'since' => '12.0.0',
					'required' => false,
					'description' => 'The name of the described website',
					'example' => 'Nextcloud - App Store',
				],
				'link' => [
					'since' => '12.0.0',
					'required' => false,
					'description' => 'The full link to the website',
					'example' => 'https://apps.nextcloud.com/apps/mood',
				],
			],
		],
		'pending-federated-share' => [
			'author' => 'Nextcloud',
			'app' => 'dav',
			'since' => '11.0.0',
			'parameters' => [
				'id' => [
					'since' => '11.0.0',
					'required' => true,
					'description' => 'The id used to identify the federated share on the instance',
					'example' => '42',
				],
				'name' => [
					'since' => '11.0.0',
					'required' => true,
					'description' => 'The name of the shared item which should be used in the visual representation',
					'example' => 'file.txt',
				],
			],
		],
		'systemtag' => [
			'author' => 'Nextcloud',
			'app' => 'core',
			'since' => '11.0.0',
			'parameters' => [
				'id' => [
					'since' => '11.0.0',
					'required' => true,
					'description' => 'The id used to identify the systemtag on the instance',
					'example' => '23',
				],
				'name' => [
					'since' => '11.0.0',
					'required' => true,
					'description' => 'The display name of the systemtag which should be used in the visual representation',
					'example' => 'Project 1',
				],
				'visibility' => [
					'since' => '11.0.0',
					'required' => true,
					'description' => 'If the user can see the systemtag',
					'example' => '1',
				],
				'assignable' => [
					'since' => '11.0.0',
					'required' => true,
					'description' => 'If the user can assign the systemtag',
					'example' => '0',
				],
			],
		],
		'talk-attachment' => [
			'author' => 'Nextcloud',
			'app' => 'talk',
			'since' => '18.0.0',
			'parameters' => [
				'id' => [
					'since' => '18.0.0',
					'required' => true,
					'description' => 'The id used to identify the attachment on the instance',
					'example' => '12345',
				],
				'name' => [
					'since' => '18.0.0',
					'required' => true,
					'description' => 'The name of the attachment',
					'example' => 'John Doe',
				],
				'conversation' => [
					'since' => '18.0.0',
					'required' => true,
					'description' => 'The token of the conversation',
					'example' => 'a1b2c3d4',
				],
				'mimetype' => [
					'since' => '18.0.0',
					'required' => false,
					'description' => 'The mimetype of the file/folder to allow clients to show a placeholder',
					'example' => 'text/plain',
				],
				'preview-available' => [
					'since' => '18.0.0',
					'required' => false,
					'description' => 'Whether or not a preview is available. If `no` the mimetype icon should be used',
					'example' => 'yes',
				],
			],
		],
		'talk-poll' => [
			'author' => 'Nextcloud',
			'app' => 'talk',
			'since' => '25.0.0',
			'parameters' => [
				'id' => [
					'since' => '25.0.0',
					'required' => true,
					'description' => 'The id used to identify the poll on the instance',
					'example' => '12345',
				],
				'name' => [
					'since' => '25.0.0',
					'required' => true,
					'description' => 'The poll question',
					'example' => 'What is the question?',
				],
			],
		],
		'user' => [
			'author' => 'Nextcloud',
			'app' => 'core',
			'since' => '11.0.0',
			'parameters' => [
				'id' => [
					'since' => '11.0.0',
					'required' => true,
					'description' => 'The id used to identify the user on the instance',
					'example' => 'johndoe',
				],
				'name' => [
					'since' => '11.0.0',
					'required' => true,
					'description' => 'The display name of the user which should be used in the visual representation',
					'example' => 'John Doe',
				],
				'server' => [
					'since' => '11.0.0',
					'required' => false,
					'description' => 'The URL of the instance the user lives on',
					'example' => 'localhost',
				],
			],
		],
		'user-group' => [
			'author' => 'Nextcloud',
			'app' => 'core',
			'since' => '11.0.0',
			'parameters' => [
				'id' => [
					'since' => '11.0.0',
					'required' => true,
					'description' => 'The id used to identify the group on the instance',
					'example' => 'supportteam',
				],
				'name' => [
					'since' => '11.0.0',
					'required' => true,
					'description' => 'The display name of the group which should be used in the visual representation',
					'example' => 'Support Team',
				],
			],
		],
	];

	/**
	 * @param string $type
	 * @return array
	 * @throws InvalidObjectExeption
	 * @since 11.0.0
	 */
	public function getDefinition($type) {
		if (isset($this->definitions[$type])) {
			return $this->definitions[$type];
		}

		throw new InvalidObjectExeption('Object type is undefined');
	}
}