This commit is contained in:
Xavier Beaudouin
2024-02-15 09:25:34 +01:00
parent 9bc292c9f3
commit a5cb461dc0
3145 changed files with 0 additions and 236034 deletions

View File

@ -1,932 +0,0 @@
Dotclear 2.16 - 2020-03-13
===========================================================
* 🐘 PHP 5.6+ is required, PHP 7.4 compliance
* 🛡 Security: all requests from/to Dotclear and DotAddict servers use now HTTPS
* jQuery upgraded to 3.4.1, older version will be removed, jQuery not anymore requested for "Remember me" feature
* New "static" mode for home page
* Media description may now be updated
* Add <i [lang="…"]>…</i> support to Dotclear wiki, syntax: ££text[|lang]££
* Lib: Update Codemirror to 5.52.0
* Lib: Update CKEditor to 4.14.0
* Lib: Clearbricks now supports MySQL 8+
* 🐛 → Various bugs, a11y concerns and typos fixed
* 🌼 → Some locales and cosmetic adjustments
Dotclear 2.15.3 - 2019-11-28
===========================================================
* Fix: Avoid weird side-effect of JS minifier
* Fix: insertion of default type media (non image/audio/video) in XHTML entries
* Fix: Cope with old themes for 'remember me' string defined in JS
Dotclear 2.15.2 - 2019-10-01
===========================================================
* Fix: Ajax saving of files in theme editor when using codemirror
* Fix: Video insertion with CKEditor or LegacyEditor
* Fix: Badge position for dashboard modules counters
Dotclear 2.15.1 - 2019-08-29
===========================================================
* Fix: SQL request for CSP unsafe-inline setting
* Fix: CKEditor configuration for foreign language (unabled to save post modifications)
Dotclear 2.15 - 2019-08-13
===========================================================
* 🐘 PHP 5.6+ is required, PHP 7.3 compliance
* Add drag'n'drop sorting system for dashboard blocks
* Backend context is preserved on switching blog (as far as possible, depending on user's grants)
* No more inline javascript, default/install CSP directive modified accordingly
* Add settings (in maintenance plugin) for CSP system
* Set correct lang attribute (useful for browser/editor spelling) for content (post/page) depending on entry setting, and CK editor UI in user language
* Add spellcheck="true" attribute on input/textarea
* Refactoring of notices/messages system on backend
* Add undo/redo buttons to CKEditor toolbar
* Add title/legend reminder on media popup insertion (1st tab)
* Add font loading capabilities for ?pf= system - plugin are now able to load css fonts
* Add WebP image format support to Dotclear (may depends on your server PHP capabilities)
* Add <sub>…</sub> support in Dotclear wiki, syntax : _indice_
* Template system: Allow ?sub for category/categories attributes of tpl:EntryIf, and for url/urls attributes of tpl:CategoryIf
* Responsive tables/lists (posts, pages, users, …)
* Spams preview (administrative board) now shows HTML code rather than interpreted content
* Fix: port used behind reverse proxy (Clearbricks)
* Lib: Update Codemirror to 5.48.0
* Lib: Update CKEditor to 4.12.0
* 🗑 → No more flash players (flv,mp3)
* 🐛 → Various bugs, a11y concerns and typos fixed
* 🌼 → Some locales and cosmetic adjustments
Dotclear 2.14.3 - 2018-09-26
===========================================================
* 🛡 Security: Avoid XML upload in media manager
* Fix: Upgrade modification for media_exclusion default setting
* Fix: cope with PHP.ini setting memory_limit set to -1 (unlimited)
Dotclear 2.14.2 - 2018-09-04
===========================================================
* 🛡 Security: Authenticated cross-site scripting (XSS) was possible due to the .ahtml (or .bhtml, .chtml, …) file extension being allowed in the media manager. Thank's Josiah Pierce for report (CVE-2018-16358)
* 🛡 Security: Unregister phar wrapper in order to avoid PHP Phar extension vulerability
* Fix: Enter key in some input fields were not redirect to the parent form
* Fix: Unable to save modified theme's files in theme editor, when Codemirror is used
* Fix: Back to the original global_filters() template function (will be rewritten in the next 2.15)
Dotclear 2.14.1 - 2018-08-17
===========================================================
* 🐘 PHP 5.6+ is required - PHP 5.5 is buggy with the 2.14 release
* Fix: install wizzard was broken
* Fix: smallest admin font size was set when saving user prefs
* Fix: minifying JS scripts may cause problems with regular expressions
* Fix: empty JS var was set for syntax coloration if disabled
Dotclear 2.14 - 2018-08-13
===========================================================
* 🛡 Security: Fix potential reflective XSS, thank's Zekvan Arslan for report (via Daniel Bishtawi from https://www.netsparker.com/)
* 🐘 PHP 7.2 compliance
* Use specialized fields whenever it's possible (email, …)
* Add definition list capabilities (dl, dt, dd) to wiki (= <term>, : <definition>)
* Add <sup>…</sup> support in wiki, syntax : ^exponant^
* Add syntax property/method to dblayer driver
* Replace some js oriented background fading by CSS3 animation
* Enhance some visual focus indicators
* Enhance key event management in popup (Esc, Enter, …)
* Template filters may now be extended (or modified) by 3rd party plugins (via behaviors)
* PSR-2 code formatting as far as possible (work in progress)
* Add two new ways to order tags (by oldest or newest associated post publication date)
* Update Codemirror to 5.38.0
* Update CKEditor to 4.9.2
* Update jQuery migrate plugin to 1.4.1
* Update jQuery UI (custom) 1.12.1
* Add a dark mode (via user preferences) for administration, CSS refactoring
* Animate some counters on dashboard icons (nb of comments, spam comments and posts)
* 🐛 → Various bugs and typos fixed
* 🌼 → Some locales and cosmetic adjustments
Dotclear 2.13.1 - 2018-01-27
===========================================================
* Fix: Weird behaviour of theme editor when typing any of "t", "r", "u" and "e" characters
* Fix: Unable to save an entry with dcLegacyEditor in XHTML mode, visual pane
Dotclear 2.13 - 2018-01-13
===========================================================
* 🐘 PHP 5.5+ is required
* 🛡 Security: New password management system (including silent migration)
* 🛡 Security: Add Referrer-Policy header in admin pages
* 🛡 Security: Fix potential XSS - thank's Trí Chim Trích for report
* Dotclear news are now displayed in async way by js
* Dotclear core update check is now done by async js - a forced check may still be done on <admin>/update.php page
* Add utf8mb4 driver (MySQL server 5.7.7+)
* Add target="blank" option in simpleMenu
* Update CKEditor from 4.6.2 to 4.7.3
* Update CodeMirror from 5.25.1 to 5.32.1
* Add required attribute for mandatory fields
* Fix: Avoid horizontal scrolling table when longest comment's usernames in list of comments
* Fix: Cope with MySQLi connection via socket
* Fix: Error messages markup and styling
* Fix: Set caret at the end of the inserted thing (img, url, blockquote, …) in Legacy editor if current selection is empty
* Fix: Cope with query part only in SimpleMenu URLs
* 🐛 → Various bugs and typos fixed
* 🌼 → Some locales and cosmetic adjustments
Dotclear 2.12.2 - merged in 2.13
===========================================================
* Fix: lang attribute was missing on entry alone contexts for currywurst and dotty templatesets
* Fix: Add http:// protocol before media.dotaddict.org for csp_admin_img
* Fix: tpl:sysIf blog_lang generated code
* Fix: Duplicate auto-generated URI (entries)
* Fix: Do not use border and background on select to use the system aspect of them in Firefox.
* Fix: For select element, target Safari to cope with font-size select/option problem.
* Fix: Error messages styling
Dotclear 2.12.1 - 2017-08-13
===========================================================
* Fix: 3rd party filters for template tags (std filters are not more modifiable)
* Fix: Media filename are now used without modification for media title on upload (advanced mode)
Dotclear 2.12 - 2017-07-27
===========================================================
* 🛡 Security: Fix potential XSS
* 🛡 Security: Enforce uniqness of the recovery key
* 🛡 Security: Switch hash method from sha1 to sha512 (new installation only)
* Two new values for base font size (37.5% and 87.5%)
* Adaptive admin font size is now optional
* Reduce base font size on very small devices
* Refactor some functions to closures
* No CSP directives in safe mode
* Add current blog domain for script and style CSP directives
* Backlinks:
* Retrieving ping URLs, let trackback first, then pingback, then finally webmention
* Get source post content to compose webmention excerpt and retrieve title
* Use source post title as blog name if this one is unknown (Anonymous blog is used if neither title nor blog name are known)
* Datepicker's look refreshed
* Allow 3rd party additional headers (URL handler)
* Dublin core metadata removed
* Using theme\<theme_name> namespace for _public.php and _prepend.php, in order to simplify theme copy and hack
* Temporary password will have to be changed at first login (after resetting password)
* Add ukrainian language
* French help updated for theme editor
* Add an option to disable Dotclear updates check (super-admin only)
* Fix: Blogs admin (ie not super-admin) got back their blogs list but only super-admin may do actions
* Fix: Post/page edition layout on different screen sizes
* Fix: x-frame-options URL in admin
* Fix: Cope with several copies of a same smiley in content
* Fix: Allow 3rd party filters for template tags
* Fix: Use getURLFor instead of old getBase function for breadcrumb
* Fix: Give mysql/mysqli driver choice for DC 1.2 import
* Clearbricks lib update from 0.9 to 1.0
* jQuery lib update from 2.2.0 to 2.2.4 (last release of jQuery 2.n branch)
* CKEditor lib update from 4.6.1 to 4.6.2
* CodeMirror lib update from 5.15.3 to 5.25.1
* 🐛 → Various bugs and typos fixed
* 🌼 → Some locales and cosmetic adjustments
* 📣 Warning: Next major release (2.13) will require PHP 5.5+
Dotclear 2.11.2 - 2016-12-29
===========================================================
* Fix: Ensure compatibility with old version of PHP (5.3, 5.4)
* Fix: New path of CSP report for maintenance deletion task
* Fix: Broken entry preview
* Fix: Avoid outgoing link on images in media manager
* 🌼 → Do not include empty div as it disrupts CSS flexbox system
Dotclear 2.11.1 - 2016-12-28
===========================================================
* Fix: admin menu not visible and some plugin admin not accessible with PHP < 5.5
Dotclear 2.11 - 2016-12-28
===========================================================
* 🐘 PHP 5.3+ is required
* 🛡 Security : Prevents XSS injection in media title, thanks smarterbitbybit for report
* Cope with locale for sorting order if possible (work in progress)
* Rich-text-editor (xhtml) may be disabled for Blog/Category description, widget's textareas, …
* Add direct access to module's settings from plugins management page (depends on _define.php of modules)
* Menus (except favorites) are now lexically sorted (except "new post" item)
* Add Entry date as sort order in comments list
* Switch admin CSS to Sass/Compass (work in progress)
* Add 'l' and 'm' accesskey for editor toolbars, respectively for 'insert link' and 'select media' buttons
* Add new categories attribute to EntryIf template tag
* Remove Dublin-core metadata from <head> in template-sets
* ToolMan (js) not more used, thank's Tim Taylor for all this years together!
* Soft redesign of administration pages using responsive font-size and OS system fonts (IE 10+)
* Add a user preference to hide additional/secondary information
* Add actions on blog list, new sort order: blog status
* Update CKEditor to 4.6.1
* Open trackbacks with behaviors and add basic Webmention support
* Add First Publication mecanism and an option to auto-ping when fired
* Berlin theme is now based on Dotty template-set
* Move advanced and plugins blogs prefs in two separate foldable sections
* Add legend and title insertion option for image insertion in entry
* Some notices and messages may be hidden
* Add urls attribute to CategoryIf template tag
* CSP: Move admin CSP admin/csp_report.txt to DC_VAR/csp/csp_report.json
* CSP: Violations are now stored only once in report if repeated
* a11y: Remove empty link (href=#) from admin
* Fix: Proxies may use standard HTTP(S) ports and SSL may now run through a proxy
* Fix: Prevents precondition failed during activated theme update
* 🐛 → Various bugs and typos fixed
* 🌼 → A lot of locales and cosmetic adjustments
* 🚽 → Housecleaning of no more used scripts, images, resources, IE 9- :-)
Dotclear 2.10.4 - 2016-11-02
===========================================================
* PostgreSQL < 9.1 fix
Dotclear 2.10.3 - 2016-11-01
===========================================================
* Security: Fix CVE-2016-7903: Password Reset Address Spoof — Thank's Hongkun Zeng for report
* Security: Fix CVE-2016-7902: Media Manager, unrestricted File Upload — Thank's Hongkun Zeng for report
* CSP: Cope with external sources used in editor's iframe to preview public external content
* Fix: Cope with post.post_position field during flat import
* Fix: Prevents precondition failed during currently activated theme update
* Fix: Remove unecessary header (cope by dotclear) in page plugin
* Fix: Let some proxies playing with standard http and https ports
* Fix: Let SSL runs through a proxy, it may be ok, sometimes
* 🐛 → Various bugs and typos fixed
Dotclear 2.10.2 - 2016-08-17
===========================================================
* Update fails with PostgreSQL db support → fixed
Dotclear 2.10.1 - 2016-08-15
===========================================================
* CSP (Content-Security-Policies) :
* Fix default directive for new installation
* Cope with media public URL for media manager
* Cope with blog public URL for post/page preview
* Codemirror lib is now packed as the other Javascript lib are
Dotclear 2.10 - 2016-08-13
===========================================================
* Security: Prevents .htaccess upload, thanks wiswat
* Security: Prevents download of a zip media folder outside root media folder, thanks wiswat
* Security: Prevents sort of SSRF/XSPA vulnerability in feed import, thanks wiswat
* Security: Prevents reflected XSS in meda manager, thanks Chen Ruiqi
* Security: Fix somes vulnerabilities in blogroll plugin, thanks Onur Yılmaz - Netsparker (https://www.netsparker.com)
* Fix mix-content preview
* Pure CSS3 sticky footer for admin pages (aka « footer de merde »)
* Add missing breadcrumb styles for blowup theme
* Currently logged super-admin may now change it's id wihtout loosing access at next login
* The favorites icons may now be hidden from dashboard in user preferences
* Number of posts/pages/comments are now displayed at top of lists, including quick filters depending on their status
* Search widget has now a placeholder option (HTML5 only)
* Add Apache 2.4+ directives in .htaccess
* New favorites media folders (displayed at the top of recent folder list) in media manager
* New pure HTML5 template set named dotty cloned from currywurst templateset
* Codemirror lib updated (2.35.0 → 5.15.2) and moved to core:
* 40+ Codemirror themes are available — set in user preferences
* Fullscreen mode has been added (F11 switching key)
* 3rd party plugins may now load and run it with dcPage::jsLoadCodeMirror() and dcPage::jsRunCodeMirror(), see themeEditor plugin for example
* New mark button for legacy editor (HTML5 only)
* New with_category attribute for tpl:Entries
* Add a /var directory:
* Set with DC_VAR constant in inc/config.php
* Admin URL of a var file should be retrieve with dcPage::getVF()
* Public URL of a var file should be retrieve with dcBlog::getVF()
* 3rd party plugins should create their own folder inside /var (aka DC_VAR) to keep it correctly organized
* Emails and web site have been added to the comments filters' list
* Some columns for posts and pages lists are now optional — set in user preferences
* Add Post URL sample in blog parameters
* CKEditor lib update (4.5.8 → 4.6.0)
* Wiki syntax: new ") <text>" mark to generate aside blocks
* CSP (Content Security Policies) have been implemented on admin pages:
* settings may be adjusted in system settings / about:config → system (see csp_admin… values)
* violation reports will be stored in admin/csp_report.txt (PHP 5.4+ only)
* new behaviour adminPageHTTPHeaderCSP may be used by 3rd party to adjust CSP directives
* New behaviour adminPageHTTPheaders
* New "Go Top" button displayed for long admin pages
* 🐛 → Various bugs and typos fixed
* 🌼 → Some locales and cosmetic adjustments
Dotclear 2.9.1 - 2016-03-27
===========================================================
* Security: Add shtml extension to default media exclusion extension control, thanks Nitin Venkatesh for report
* Changing theme is now allowed even with read-only theme folder
* Audio media are not more preloaded in media manager pages
* Array settings/prefs are stored with 'array' type rather than 'string'
* 🐛 → Various bug fixes
* 🌼 → Some cosmetic adjustments
Dotclear 2.9 - 2016-02-29
===========================================================
* Additionnal menu items are now lexically sorted (default items and favorites order will be preserved)
* Wiki syntax : Added ""marked text"" support (HTML5 only)
* Session TTL are now adjustable (set DC_SESSION_TTL in inc/config.php)
* Add behaviors for posts/pages/comments/users lists' columns → let 3rd party plugin playing with them
* Blog and user lists are now lexically sorted
* Some new filters have been added for post lists
* Add a search engine in media manager (looking in filename, title and description metadata)
* Add recent folders direct access mechanism for the media manager (setting in user prefs)
* Add a another display mode (list) to the media manager
* Details about currently selected thumbnail in media manager are now displayed
* Shortcut access to the upload file form is now displayed on top on media page
* Default insertion size (width and height) may now be defined for video media
* Flash player fallback insertion is now optional for audio and video media
* Modules may have dependencies on Dotclear core version too (using 'core' as module name)
* Avoid mixed content (http vs https) for post/page preview: will open preview in another window if necessary
* Finnish translation has been added
* Content-length header is not more sent in HTTP response (should fix very long delays on some servers)
* Template engine : add tpl:EntryAuthorEmailMD5 and tpl:EntryCategoryDescription tags
* A new pref/setting array type is now available (JSON encoded in db)
* Cope with sort of "un-attached" media → allows new features as "featured media" plugin
* CKEditor library updated from 4.5.1 to 4.5.8
* Update jQuery from 1.11.3 to 2.2.0, jQuery-migrate from 1.2.1 to 1.3.0, jQuery-ui-custom from 1.11.2 to 1.11.4
* Provide jQuery 2.2.0 for public use (themes/plugins) - 1.4.2 (default) and 1.11.3 still provided
* Some locales added or updated
* PHP 7 compliance, PHP 5.3 min
* Fix : Cope with "unknown" scheme in url (ie nor http: neither https: is defined in origin url)
* Fix : Let select another theme even if theme folder is read-only
* Fix : XML-RPC media uploaded are not more twice Base64 decoded
* And plenty of other 🐛 🔫, various 🌼 adjustments, and also lot of 🍻 drunk
Dotclear 2.8.2 - 2015-10-25
===========================================================
* Security fix : Fixed potential XSS on comments management page
* Security fix : Enforce media exclusion control
* Php 5.5 leaves NULL chars in unpack ==> add trim, fixed
* Media title (in standard mode) is now taken into account on upload
* Some 🐛 🔫
Dotclear 2.8.1 - 2015-09-23
===========================================================
* Fix admin pager parameters escaping - thanks Keiko Yashiki from JPCERT/CC for reporting this XSS
* Error on changing post author in entries' lists: fixed
* Cope with unknown URL scheme in X-Frame-Options
* One ot two of 🍻 drunk
Dotclear 2.8 - 2015-08-13
===========================================================
* New module dependencies system (plugins)
* Theme editor: Cope with css theme sub-folder
* extension/heritage system applied to mustek templateset
* installation wizard now allows SQLite engine
* Legacy editor toolbar may now be displayed below textarea
* Breadcrumb plugin added to the distribution, included in mustek/currywurst templatesets
* Allow a fifth parameter (optional) for image to insert a legend using figure/figcaption tags (wiki)
* XHTML validator removed from legacy editor
* Update jQuery from 1.11.2 to 1.11.3
* Add a blog parameter to disable internal search
* Add some sort orders and filters criteria for posts and comments
* Update CKEditor from 4.4.8 to 4.5.2
* Add IP and antispam filter columns when displaying spams
* Add actions to directly blacklist IP from comments list
* Lexical sort order for tags and widgets
* Use HTML5 audio tag for MP3 attachments
* Bye the 🐈, welcome the 🐸
* Lot of 🐛 🔫
* Various 🌼 adjustments
* Full of 🍻 drunk
Dotclear 2.7.4 - 2015-02-13
===========================================================
* Berlin theme: resources usage has been optimized
* currywurst templateset: head-linkrel block name fixed
* Current editor syntax: now displayed near edited field (post/page/quick entry)
* Some admin URLs were malformed: fixed
* Post/page preview: anti-clickjacking system fixed
* The cat is valid now
Dotclear 2.7.3 - 2015-01-13
===========================================================
* Restore advanced edition of category description (as in 2.6)
* Various bug fixes
* Some cosmetic adjustments
Dotclear 2.7.2 - 2014-12-25
===========================================================
* Dotclear wiki could not be used by standard user: fixed
Dotclear 2.7.1 - 2014-12-25
===========================================================
* Various bug fixes
* Some cosmetic adjustments
Dotclear 2.7 - 2014-12-13
===========================================================
* Security : protection against clickjacking may be activated (see blog parameters)
* Switch to HTML5 : backend, templatesets and themes
* ARIA roles in da place (a11y)
* Multiple templatesets : mustek (legacy) and currywurst
* Themes may use extension/heritage template mechanisms
* New theme (Berlin) based on currywurst templateset
* New WYSIWYG editor (CKEditor)
* Dotclear Wiki now produces HTML5 compatible markup
* Video and audio HTML5 tags are now used (with fallback to flash if possible)
* Copying default theme to user-defined theme folder is not more necessary
* Preview of comment may be optional (see blog parameters)
* Widgets may be put offline without deleting them
* jQuery version may be choosen between 1.4.2 (default) and 1.11.1 (see blog parameters)
* Number of posts listed on home page may be different than other pages (see blog parameters)
* Hidden folders are now hidden in media manager (set DC_SHOW_HIDDEN_DIRS to true in config.php to display them)
* User-defined template files may be reset (deleted) in theme editor
* Drag'n'drop now enabled on touch screens
* Alternative syntax may be set for comments by third-party plugins
* A lot of bug fixes
* Much more cosmetic adjustements and enhancements
Dotclear 2.6.4 - 2014-08-18
===========================================================
* Security fix: Sanitize search request. Thanks to Takayuki Uchiyama
* Security fix: Strenghened xmlrpc (see http://www.breaksec.com/?p=6362)
Dotclear 2.6.3 - 2014-05-16
===========================================================
* Security fix: Strengthened xmlrpc auth. Thanks to Egidio Romano
* Security fix: Strengthened categories ordering. Thanks to Egidio Romano
Dotclear 2.6.2 - 2014-01-20
===========================================================
* Security fix: Fixed potential code injection on password protected post/page. Thanks to Charlie Briggs
* Bugfix: cope with numeric module (plugin/theme) id
* Bugfix: Bad SQL syntax when using SQLite
* Bugfix: BlogParentThemeURL template value is back
* Various bug fixes
Dotclear 2.6.1 - 2013-11-22
===========================================================
* Bugfix: trackbacks/pingbacks post URL
* Bugfix: short/full list of tags (post edition)
* Bugfix: Toolbar not drawn on new comment form (administration)
* Various bug fixes
* Some cosmetic adjustments
Dotclear 2.6 - 2013-11-13
===========================================================
* Various bug fixes
* Various cosmetic adjustments
Dotclear 2.6-RC - 2013-10-18
===========================================================
* PHP 5.2 required
* jQuery upgraded to 1.10.2 (including jQuery migrate plugin 1.2.1)
* mySQLi support (now proposed by default rather than mySQL)
* Administration revamped, relooked, redesigned, new icons, new ergonomic's behaviours
* Administration is now responsive (easier to cope with it on small devices)
* Administration menu re-organized
* a11y (accessibility) everywhere, with and whithout Js
* Success, notice and warning messages have been harmonized
* daInstaller has been dispatched in core (in plugins and blog themes management)
* Global help is now available, contextual help is available on every page
* Media manager enhanced
* Maintenance plugin revamped and enhanced (now includes export features)
* Categories management enhanced
* Plugins and themes management revamped
* New “Plumetis” variation for Blowup theme
* Jasmine is now used for unit testing of js components
* A lot of bug fixes
* A lot of cosmetics adjustments
* A lot of enhancements
Dotclear 2.5.3 - 2013-09-13
===========================================================
* Bugfix: l10n Clearbricks library
* Bugfix: post's comments and trackbacks counters
* Check public and cache directories (existence and permissions)
* Avoid Categorie's identical URL as far as possible
* Cope with alpha layers in PNG images for thumbnails generation
* Add password strength indicators
* Fix permission form (checkboxes management)
* Better management of antispam filters
* Minor enhancements
* Various bug fixes
* Various cosmetic adjustments
Dotclear 2.5.2 - 2013-08-14
===========================================================
* Security fix: Fixed potential XSS
* Bugfix: l10n Clearbricks library
* <tpl:LoopPosition> now works <tpl:Attachments>
* Dotclear update check may now be forced (ignoring cache)
* Enforce integration of daInstaller plugin
* Tags link button is now available on page editor
* Default cache age is now 1 week instead of 2 hours
* Quick entry dashboard module is not activated by default on new installation
* New template {{tpl:BlogParentThemeURL}} (return URL of parent theme of blog's theme if any, URL of blog's theme otherwise)
* Fix post comments number on comments deletion
* Fix order of backup files
* Minor enhancements
* Various bug fixes
* Various cosmetic adjustments
Dotclear 2.5.1 - 2013-07-20
===========================================================
* Security fix: Replacement of swfupload.swf by a jQuery plugin
* Security enhancement: Strenghened lists display
* Thumbnails quality improved
* Minor enhancements
* Various bug fixes
* Various cosmetic adjustments
Dotclear 2.5.0 - 2013-03-12
===========================================================
* Security fix: XSS vulnerabilities in swfupload.swf (media enhanced uploader)
* Ductile theme may now use webfont (from Google, Adobe and similar providers)
* daInstaller plugin is now included in the official distribution
* The media enhanced uploader may now be temporarily enabled or disabled
* Add mass expand on posts and comments lists
* Allow wildcard for IP address on comments filters
* Add ability to delete non empty category (and move its content to another category)
* Every types of entries may be used to inserted an entry link in current edited post
* Add (none) option to image insertion title pattern
* Smileys are not more converted in image in pre,code,kbd,script and math contents
* Notes' title can be now enclosed in h4 (default), h3 or p HTML tag
* Now display translated name and desc of plugins
* Add publication date validation on post and page editing forms
* Add description to widgets
* Add syntax color option to theme editor plugin
* Add delete button on media item page
* Add/complement display modes (all pages, home page only, except on home page) for all widgets
* {{tpl:Widgets}} without type attribute set displays now all widgets (from nav, extra and custom)
* Add {{tpl:else}}, {{tpl:TagCount}}, <tpl:TagIf>, {{tpl:CategoryEntriesCount}} template tags
* Add cat_only, no_tag and content_only attributes to {{tpl:EntryFirstImage}} tag
* Add capitalize attribute to template filters' list
* Enhance links lookup anti spam filter
* Add hidden optional attribute for pages
* Adaptative compression rate for thumbnails generation
* Add timestamp on admin information messages
* Update to jQuery 1.8.3 and jQuery-UI 1.9.2 (custom)
* Add default favicon.ico
* Add default attributes settings for image,mp3,flv insertion
* Various bug fixes
* Various cosmetic updates and contrast adjustments
Dotclear 2.4.4 - 2012-08-13
===========================================================
* Bugfix: Programmed entries works again.
* Compatibility fix: widgets are now fully php >=5.3 compliant
* Security fix: potential CSRF in user management
* has_tag now part of dotclear core, moved from tag plugin.
* empty title fixed on rss reader widget
Dotclear 2.4.3 - 2012-05-18
===========================================================
* Admin: My favorites menu can be hidden
* Admin: Fix wordpress importer
* Admin: about:config and user:pref tables are now more readable
* Ductile theme: Blog logo can be changed
* New lithuanian language (thanks to Paulius Černakauskas)
* Various bug fixes
Dotclear 2.4.2 - 2012-02-11
===========================================================
* Security fix release
* 4 XSS vulnerabilities fixed, discovered by High-Tech Bridge
Dotclear 2.4.1.2 - 2011-12-24
===========================================================
* Happy Christmas!
* Security: fixed one SQL injection vulnerability in Clearbricks, thanks to Adjaya
* New behaviour: publicGetURLFor
* New behaviour: publicRegisterURL
* New behaviour: templatePrepareParams
* Changed the way to get artefacts URLs, through $core->url->getURLFor calls, instead of $core->url->getBase()
* new/updated parameter sql_only in $core->blog->getPosts and $core->blog->getComments
Dotclear 2.4.0 - 2011-11-13
===========================================================
* Admin: new iconset from Thomas Daveluy
* Admin: Accessibility enhancements
* Added a custom widget sidebar
* Added a new theme (Ductile)
* Added a new plugin (simpleMenu)
* handling of postgres non default schemas (db_prefix = 'schema.prefix')
* New iconset mechanism
* New behaviour: coreBlogBeforeGetPosts
* Security fix: Spam comments feed now checks for blog permission. Thanks to Romuald Brunet.
* Various bug fixes
Dotclear 2.3.1 - 2011-06-14
===========================================================
* Updated makefile for cleaner distrib.
* Better localization handling for prefs and shortcuts.
* Misc JS & CSS cleaning.
* Import/Export preferences-related bugfix.
* Administrative mail address is now configurable.
* Security: one minor fix and changes for two potential problems. Thanks to Jeremie Boutoille
Dotclear 2.3.0 - 2011-05-16
===========================================================
* Admin: Major backend redesign
* Admin: Customizable Dashboard
* Admin: New Favourites admin submenu
* Admin: New user preferences backend
* Admin: Accessibility enhancements
* Admin: Inline help extended
* Templates: Default theme templates moved to inc/public/default-templates
* Clearbricks: External libraries relocated to inc/libs
* Clearbricks: fixed utf-8 and mysql strict mode problems
* Added a safe mode connection, disabling all plugins
* Mysqli support (config.php may need to be updated manually)
* Fixed dcLog bug with pgsql
* Fixed comment/trackbacks counters reset.
* Several other bug fixes
Dotclear 2.2.3 - 2011-04-01
===========================================================
* Security fix in media manager. Thx to Raphaël
* Bugfix : 2.2.2 was preventing manual thumbnail regeneration.
* Database handling bugfixes
Dotclear 2.2.2 - 2011-01-17
===========================================================
* Bugfix: 2.2.1 was blocking new installations
* Autoupdate procedure should now be "bad ftp client configuration"-proof.
* Several other small bugfixes
Dotclear 2.2.1 - 2011-01-15
===========================================================
* ExternalMedia is not part of the core distribution anymore
* New attribute to tpl:SysIf: blog_id
* New behaviour: adminMediaItemForm
* Several bugfixes
* Several code optimizations
* Several typos corrected
* Security fix in Clearbricks. Thx to François Pierre-Doray for pointing it out.
Dotclear 2.2 - 2010-07-01
===========================================================
* New installation wizard.
* Several new behaviours:
- adminCommentHeaders
- adminCommentsActionsCombo
- adminCommentsActions
- adminCommentsActionsContent
- adminBeforeCommentDelete
- adminPostsActionsHeaders
- adminUsersActionsCombo
- coreBeforeCategoryCreate & coreAfterCategoryCreate
- coreBeforeCategoryUpdate & coreAfterCategoryUpdate
- coreBeforeLogCreate & coreAfterLogCreate
- coreBeforePostCreate & coreAfterPostCreate
- coreBeforePostUpdate & coreAfterPostUpdate
- coreMediaConstruct
- templateCustomSortByAlias
- urlHandlerGetArgsDocument
* New methods for several core classes.
* Metadata integration to the core.
* Error handlers can now be extended.
* Templates: blocks can now be recursive.
* Templates: Entries & Comments tags can now be sorted.
* Templates: The template subsystem is quicker, linier, and ready to be extended.
* Complete reworking of the settings system
* Correct handling of postgresql non default schemas.
* Admin: Autocompletion and further enhancing to tags handling.
* Admin: Accessibility & ergonomic tweaks.
* Admin: Administrator tag in users list.
* Comment cookies are now specific to the blog rather than to the domain.
* Password changes can now be mandatory.
* jQuery updated to 1.4.2.
* And way too many bugfixes and typos squashes to be listed.
Dotclear 2.1.7 - 2010-05-25
===========================================================
* Auto-update procedure fix
Dotclear 2.1.6 - 2009-10-01
===========================================================
* Install procedure fixes
* Admin: Page managers can now create pages
* Admin: several typos corrected.
* Admin: Widgets now work in IE8.
* Admin: Password protected posts can now be previewed.
* Templates: tpl:Meta* are now tpl:Tags*.
* Templates: <tpl:Entries lastn="0"> now display all posts.
* new behavior: adminPageHTMLHead
* DB schema: new blog_id field in log table
* Media manager: Pubic folder can now be set on a different host.
* WordPress import fixes
* Dailymotion insertion fix
* Upgrade procedure: CRLF removed in files that were bugging the upgrade.
* JQuery updated to 1.3
* IE7-js update
* security: Full Path Disclosure protection. Thx to Karim Ayad for pointing it out.
* and way too many bugfixes to be listed.
Dotclear 2.1.5 - 2009-02-05
===========================================================
* Security release
* Youtube insertion update
Dotclear 2.1.4 - 2008-12-21
===========================================================
* Security flaw fix
* WordPress import refining
* XML-RPC improvements
Dotclear 2.1.3 - 2008-11-19
===========================================================
* Admin: New upgrade procedure
* Admin: Fixed video insertion bug
* Template: New attributes
* url on EntryIf
* only_category on Blogroll
* no_context on Pagination
* Template: New tag
* BlogID
* Admin: escaped blog_id on authentication page
Dotclear 2.1.1 - 2008-11-07
===========================================================
* Admin: Automatic Update bug fixes
* Admin: Disable Automatic Update if no digests file
* Admin: Javascript fixes in authentication page
* Admin: Fixed errors with categories select boxes
* Template: Added level attribute in tpl:Categories
* Media: Added H.264/MPEG-4 AVC for mp4 files
Dotclear 2.1 - 2008-11-01
===========================================================
* Subcategories
* Admin: Automatic Update
* Admin: Flash 10 support for uploader
* Admin: mailto link in comment details
* Admin: Embedded video size selection
* Admin: Restrict session cookie path to admin
* Media: H.264/MPEG-4 AVC (HD) support with m4v files
* Inherited themes
* WordPress XML-RPC methods support
* True unicode URLs
* Plugin: Widgets as template tags
* Plugin: Filters in entries widgets and Blogroll
* Plugin: Added vimeo.com in external media
* Template: New tags
* LoopPosition
* CommentAuthorDomain
* CommentAuthorMD5
* EntryFirstImage
* EntryCategoryShortURL
* CategoryIf
* CategoryFirstChildren
* CategoryParents
* EntryCategoriesBreadcrum
* MediaURL
Dotclear 2.0.2 - 2008-09-05
===========================================================
* New installation procedure
* Plugin: WordPress import fixes
* Plugin: Plain text export as downloadable files
* Plugin: Message about URLs in Dotclear 1.2 import
* Public: Display a message if search returns no result
* Admin: Fixed some CSS bugs
* Admin: Batch select/unselect entries
* Admin: In a media item, find entries containing it
Dotclear 2.0.1 - 2008-08-16
===========================================================
* Plugin: Fixed a bug with Dotclear 1.2 URLs import.
* Plugin: Fixed a l10n bug in Pages
* Admin: Enhanced plugins resources loading and cache
Dotclear 2.0 - 2008-08-01
===========================================================
* Public: Atom becomes the default feed format. RSS 2 is always available.
* Admin: design enhancements and new Dotclear logo
* Admin: entries preview in blog context
* L10N: New language manager with zip files support
* Plugin: Import/Export plugin version 2.0 with import from Dotclear 1.2 and WordPress
* Plugin: Pages enhancements (preview, sorting)
* Plugin: support for jamendo and deezer in External Media
* JSMin on JavaScript files instead of JS packing
* SQLite 3 only support (PDO based)
* Many bug fixes and major performances improvements
Dotclear 2.0 RC2 - 2008-06-21
===========================================================
* FairTrackback spam filter
* Language pack infrastructure
* Bug fix on comment search with author "0"
* Javascript fixes
* dcAuth::sessionExists and dcAuth::checkSession new methods
* Right management in dcAuth::sudo
* Media File sorting options in media manager
* CandyUpload, new uploader tool based on SWFUpload
* New search engine robots options
* New image options
* L10N: Japanese and Portugues (Brazil) language packs
* Many bug fixes and enhancements
Dotclear 2.0 RC1 - 2008-05-01
===========================================================
* New: Pages plugin
* New: Theme editor plugin
* Entries: Text and WYSIWYG enhancements
* Entries: Markup validator
* Entries: Insertion of links to other entries from toolbar
* Entries: External media insertion (dailymotion, youtube, google video)
* Tags: Same list for new and existing entries
* Tags: Tags can be removed on all associated entries
* Tags: Tags can be removed on a post selection
* Admin: Ask password for user management tasks, theme upload and plugin upload
* Admin: New contextual help viewer
* Media manager: Recreate thumbnails option
* Media manager: Custom medium thumbnail size (per blog)
* Media manager: Zip files extract support
* Media manager: Zip file download of directory
* Media manager: File exclusion pattern option
* Themes and plugins: Zip as new package format
* Themes and plugins: Upload
* Themes and plugins: Upgrade within administration interface
* Themes and plugins: Deletion
* Public: New default theme: Blowup (fully customizable)
* Public: Changed the way commenter cookie is handled
* Themes: Template files moved to tpl/ directory
* L10N: Polish, Catalan and Spanish translations
* Misc: jQuery upgraded to 1.2.3
* Misc: Crushed png files
* Fixed many bugs
Dotclear 2.0 beta 7 - 2007-07-12
===========================================================
* New way to display comments and trackbacks on entries in backend
* Dashboard visual improvements
* Default cache dir created by installation process
* Option to limit posts and comments in feeds
* Introduced UDBS for installation and upgrade
* Changed handling of XML-RPC URLs
* New option to force HTTPS redirect if wanted
* Enforced cookies security (directory and ssl support)
* Added Plugin auto-install and auto-upgrade support
* Added trackbacks ttl and moderation preferences
* Added an Internal search engine
* FLV support in backend with Neolao player
* Added nice messages if database is broken or Dotclear not installed
* upgrade jQuery to 1.1.3
* Fixed many bugs
* Fixed security issues in backend
Dotclear 2.0 beta 6 - 2007-02-19
===========================================================
* New antispam plugin, with a set of filters (rbl, ipblacklist, spamwords, akismet)
* New admin dashboard page
* Fixed unwanted logout bug
* Added settings to disable template caching and allow PHP code
* Blog preferences panel bug fix
* New XML-RPC Client and Server
* Comment posting permissions bug fix
Dotclear 2.0 beta 5.4 - 2007-01-19
===========================================================
* Minor change on spam display in comments.php
* Command line upgrade script and fix in load_plugin_file.php
* Make akismet configurable only by superadmin with DC_AKISMET_SUPER
* SQL optimisations
* New comments view in post
Dotclear 2.0 beta 5.2 - 2007-01-11
===========================================================
* Fixed a bug with imageMeta::getMeta
* Enhanced dynamic file uploader
* Move clearbricks files to their own repository
* Fixed a bug with auto_br in wikiSimpleComment
* Support for language restriction in feeds
* Default theme structure changes
* Fixed a PHP 5.0 compatibility issue
* Installation Wizard
Dotclear 2.0 beta 4 - 2006-12-26
===========================================================
* Performances enhancements.
* Administration UI enhancements.
* More user-friendly Widgets (version 1.5).
* Switch to jQuery <http://jquery.com>.
* Added jQuery in default theme.
* Major changes in HTTP client and Feed Parser based on a
generic socket handler.
* PHP 5.2 compatibility.
* Code documentation (all core and most of clearbricks).
* Many bug fixes.
Dotclear 2.0 beta 3 - 2006-11-05
===========================================================
* Disallow special wrappers for fopen like functions.
* XML/RPC improvements.
* Read IPTC and EXIF metadata in uploaded pictures.
* MySQL 4.1 support only.
* Metadata import from Dotclear 1.2.x.
* Akismet plugin.
* Pings plugin.
* Added a priority setting for plugins.
* Many bug fixes.
Dotclear 2.0 beta 2 - 2006-08-09
===========================================================
* DC_PLUGIN_ROOT can handle more than one path.
* OPML/XBEL import in blogroll plugin.
* Fixed a security issue in html::absoluteURLs().
* Fixed issues with timezone on scheduled entries.
* Multiple categories selection in tpl:Entries.
* Improved dbLayer.
* Changed category feed URL.
* Feeds for tags (entries and comments).
* Added attachments count on backend and frontend.
* New settings code design. Can now handle wide system settings.
* Memory usage improvements with autoloader.
* Some code cleanup.
* Feed parser improvements.
* Themes can be configured if needed.
* XMP support on JPEG files.
* Media manager improvements.
* Spamplemousse now uses DNSBL (and the guy who left the bug was fired).
* Javascript editor and toolbar improvements.
* RDS support (XML/RPC API discovery).
* Added a theme with user stylesheet.
* Plugins manager

View File

@ -1,9 +0,0 @@
# CONTRIBUTING
Dotclear is an open source project. If you'd like to contribute, you can send
a pull request, or feel free to use any other way you'd prefer.
There are many way to contribute :
* Report bugs (https://git.dotclear.org/dev/dotclear and https://git.dotclear.org/dev/dotclear/issues/new)
* Add documentation (https://dotclear.org/documentation/2.0 in English, https://fr.dotclear.org/documentation/2.0 in French)

View File

@ -1,52 +0,0 @@
This is a credits file of people that have contributed to the Dotclear project.
Dotclear Team
-------------
Thomas Bouron
Luce Carević
Anne Cavalier
Noé Cendrier
Benoit Clerc
Grégory Corvisier
Florent Cotton
Jean-Christian Denis
Gilles Aka Gvx
Philippe Hénaff
Bruno Hondelatte
Franck Lafay
Kévin Lepeltier
Olivier Meunier
Franck Paul
Michel Pelletier
Xavier Plantefève
Nicolas Roudaire
Jean-Michel Royer
Anne Sophie Tranchet
Alain Vagner
Dotclear Translators
--------------------
Benjamin Bank
Alain Béarez
Claire Cambier
Luis Correia
Andreas Diller
Alain Fagot
Sabrina Favier
Charles Hebert
Guillaume Jonquiere
Dennis S. L. Jørgensen
Miguel A. Muñoz
Sebestyén Muráncsik
Nnidŷu
Polo
Aina Chabert Ramon
Adnan Shameem
Enrique Matias Sanchez
Jan Skrasek
Takafumi
Regina Timbó
... and all contributors.

View File

@ -1,339 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -1,109 +0,0 @@
# README
## WHAT IS DOTCLEAR ?
Dotclear is an open-source web publishing software.
Take control over your blog!
Dotclear project's purpose is to provide a user-friendly
tool allowing anyone to publish on the web, regardless of
their technical skills.
### Features:
* Easy publication
* Fully customizable theme
* User-friendly administration
* Flexible template system
* Media management
* Choose from several editing syntax (wiki, markdown, textile or directly in wysiwyg)
* Flexible comment system
* Built-in antispam
* Localization
* Presentation widgets
* Themes and plugins
* Pages
* Tags and categories
* Automated installation
* Support for several database types
* Multiblog
* Multi-user with permissions
* Standards compliant
* Accessible
* Importing / exporting
* Naturally optimized for search engines
* Syndication feeds
* Complete trackback support
* Full Unicode support
* XML/RPC client support
* Extensible
* Performance and scalability
* Twice free
## REQUIREMENTS
In order to run Dotclear you need:
* A web server (Apache, Cherokee, Nginx, lighttpd, etc.)
* PHP 5.6 with the following modules:
* mbstring
* iconv
* simplexml
* mysql, mysqli, postgresql or sqlite
* A database server (MySQL or PostgreSQL) or SQLite.
## INSTALLATION
### Automatic installation
The easiest way to install the blog engine is automatic installation.
Download the [one minute install file][1], upload it to your web space. Then open it in your favorite browser. You'll only have to follow the instructions on screen. See the [documentation][2] for more information.
### Standard installation.
You need to download [Dotclear archive][3], extract it then upload your files to your web space using an FTP client.
Then open your favorite browser and go to http://your.host.name/dotclear/admin/install/. A message alerts you that you haven't got a configuration file and offers to run the wizard. Click this link.
## DOCUMENTATION
Still unsure if you want to move? A "[guided tour][4]" is what you need.
Dotclear is fully documented:
* If you have moved in already, the [User Manual][5] is there for you.
* The managers will turn to the [Administration Guide][6].
* Decorators and craftsmen will surely enjoy reading the [Developer and designer resources][7].
Dotclear documentation uses a wiki. Feel free to contribute.
## License
Copyright Olivier Meunier & Association Dotclear
GPL-2.0-only (https://www.gnu.org/licenses/gpl-2.0.html)
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
CONTRIBUTING
------------
Dotclear is an open source project. If you'd like to contribute, please read the [CONTRIBUTING file](CONTRIBUTING.md).
You can submit a pull request, or feel free to use any other way you'd prefer.
Repositories:
-------------
https://git.dotclear.org/dotclear/ (official)
https://github.com/dotclear/dotclear (Github)
[1]: https://download.dotclear.org/loader/dotclear-loader.php
[2]: https://dotclear.org/documentation/2.0/admin/install
[3]: https://dotclear.org/download
[4]: https://dotclear.org/documentation/2.0/overview/tour
[5]: https://dotclear.org/documentation/2.0/usage
[6]: https://dotclear.org/documentation/2.0/admin
[7]: https://dotclear.org/documentation/2.0/resources

View File

@ -1,601 +0,0 @@
<?php
/**
* @package Dotclear
* @subpackage Backend
*
* @copyright Olivier Meunier & Association Dotclear
* @copyright GPL-2.0-only
*/
require dirname(__FILE__) . '/../inc/admin/prepend.php';
dcPage::check('usage,contentadmin');
$core->auth->user_prefs->addWorkspace('interface');
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<meta name="ROBOTS" content="NOARCHIVE,NOINDEX,NOFOLLOW" />
<meta name="GOOGLEBOT" content="NOSNIPPET" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Bibliothèque de styles - Dotclear - 2.7</title>
<link rel="icon" type="image/png" href="images/favicon96-login.png" />
<?php
$js = [];
if ($core->auth->user_prefs->interface->darkmode) {
echo dcPage::cssLoad('style/default-dark.css');
} else {
echo dcPage::cssLoad('style/default.css');
}
if ($core->auth->user_prefs->interface->htmlfontsize) {
$js['htmlFontSize'] = $core->auth->user_prefs->interface->htmlfontsize;
}
// Set some JSON data
echo dcUtils::jsJson('dotclear_init', $js);
?>
<script src="js/jquery/jquery.js"></script>
<script src="js/jquery/jquery-ui.custom.js"></script>
<script src="js/jquery/jquery.ui.touch-punch.js"></script>
<script src="js/jquery/jquery.pageTabs.js"></script>
<script src="js/jquery/jquery.biscuit.js"></script>
<script src="js/prepend.js"></script>
<script src="js/common.js"></script>
<script src="js/prelude.js"></script>
<script src="js/_charte.js"></script>
</head>
<body id="dotclear-admin" class="no-js guideline<?php $core->auth->user_prefs->interface->dynfontsize ? ' responsive-font' : '';?>">
<ul id="prelude">
<li><a href="#content">Aller au contenu</a></li>
<li><a href="#main-menu">Aller au menu</a></li>
<li><a href="#qx">Aller à la recherche</a></li>
</ul>
<div id="header">
<h1><a href="./index.php"><span class="hidden">Dotclear</span></a></h1>
<div id="top-info-blog">
<p>Bibliothèque de styles - Dotclear - 2.6+</p>
</div>
<ul id="top-info-user"><li>Octobre 2013</li></ul>
</div><!-- /header -->
<div id="wrapper" class="clearfix">
<div class="hidden-if-no-js collapser-box"><button type="button" id="collapser" class="void-btn">
<img class="collapse-mm visually-hidden" src="images/collapser-hide.png" alt="Cacher le menu" />
<img class="expand-mm visually-hidden" src="images/collapser-show.png" alt="Montrer le menu" />
</button></div>
<div id="main">
<div id="content" class="clearfix">
<h2>Typographie</h2>
<h3 id="texte">Textes</h3>
<p>La font-size de base est à 1.2rem (la valeur <code>1rem</code> correspond à 10px). Si vous utilisez l'unité <code>rem</code> pensez à faire précéder la déclaration par son équivalent
en pixels pour rester compatible avec Internet Explorer. L'interlignage courant est à 1.5.</p>
<p>La liste suivante est de class <code>"nice"</code>. Elle est semblable aux listes ordinaires mais avec des puces carrées.</p>
<ul class="nice">
<li>Les textes courants sont en Arial, Helvetica ou sans-serif. </li>
<li>Le code adopte la fonte Andale Mono, Courier New ou monospace.</li>
<li>Les liens ont des aspects différents au focus et au survol. Il faut conserver cette distinction, nécessaire à l'accessibilité et l'ergonomie.</li>
</ul>
<h3 id="titres">Titre h3</h3>
<p>Le titre de niveau h1 est réservé au titre du site-admin. Le titre de niveau h2 est réservé au breadcrumb/titre de la page courante. On utilise les titres de niveau h3 en premier niveau de titre à l'intérieur des pages, comme sur la page Import/Export.</p>
<p>Il ne faut pas choisir un niveau de titre en fonction de son aspect mais respecter une hiérarchie cohérente. On peut obtenir visuellement l'aspect d'un titre h3 en donnant à l'élément la class <code>"as_h3"</code>.</p>
<h4>Titre de niveau h4</h4>
<p>On peut obtenir visuellement l'aspect d'un titre h4 en donnant à l'élément la class <code>"as_h4"</code>.</p>
<h5>Titre de niveau h5</h5>
<p>Le titre de niveau h5 est assez peu employé mais son style est prévu. Dans une admin de base, on utilise les niveaux
h5 pour certains éléments du sidebar du billet, mais un style particulier leur est alors appliqué pour ressembler aux autres
items de ce sidebar.</p>
<div class="fieldset">
<h4>Titres des encadrés</h4>
<p>Les titres de boîte encadrées (div de class <code>"fieldset"</code>, comme ici) se présentent comme ci-dessus.</p>
<p>On peut utiliser, quel que soit le niveau hx de cet intertitre la class <code>"pretty-title"</code> pour obtenir l'effet ci-dessus.</p>
</div>
<h4 class="smart-title">Autre variante</h4>
<p>On dispose également d'une class <code>"smart-title"</code> pour obtenir une présentation comme celle du titre de ce paragraphe.</p>
<h2>Layouts</h2>
<h3 id="onglets">Onglets</h3>
<p>Les descriptions des constructions en multi-colonnes ci-dessous présentent un exemple de répartition en onglets.</p>
<p>Chacun de ces onglets doit être défini à l'aide d'une <code>&lt;div class="multi-part"&gt;</code>. Ils seront alors automatiquement présentés sous forme d'onglets.</p>
<h3 id="multi-colonnage">Multi-colonnage</h3>
<div id="one-box" class="multi-part" title="One-box">
<h4>Boîtes distribuées horizontalement</h4>
<div class="one-box">
<div class="box">
<p><span class="step">1</span> Toutes les boîtes de class <code>"box"</code> placées à l'intérieur d'une boîte de class <code>"one-box"</code> se distribuent horizontalement (imaginez que chaque boîte est un mot dans un paragraphe). Si les largeurs de ces boîtes ne sont pas spécifiquement définies dans la CSS, elle s'ajustent à leur contenu.</p>
</div>
<div class="box">
<p><span class="step">2</span> Voici une petite boîte.</p>
</div>
<div class="box">
<p><span class="step">3</span> Une autre petite boîte.</p>
</div>
<div class="box">
<p><span class="step">4</span> Par défaut les « lignes » de boîtes <code>"box"</code> sont justifiées au sein de la boîte <code>"one-box"</code> et l'espacement se répartit entre elles.</p>
</div>
<div class="box">
<p><span class="step">5</span> Si vous souhaitez un autre alignement des boîtes entre elles vous pouvez ajouter les class :</p>
<ul class="nice clear">
<li><code>"txt-left"</code>,</li>
<li><code>"txt-right"</code></li>
<li>ou <code>"txt-center"</code></li>
</ul>
<p>à la class <code>"one-box"</code>.</p>
</div>
<div class="box">
<p><span class="step">6</span> Le cadre placé ici autour de chaque boîte ne fait pas partie des styles par défaut.</p>
</div>
</div>
</div>
<div id="two-boxes" class="multi-part" title="Two-boxes">
<h4>Boîtes distribuées deux par deux</h4>
<div>
<div class="two-boxes odd">
<p><span class="step">1</span> Les boîtes de class <code>"two-boxes"</code> ont une règle CSS <code>display:inline-block;</code>. Elles se rangent alternativement à gauche et à droite. Pour plus de clarté, les blocs sont ici numérotés avec leur ordre dans le flux.</p>
</div><!--
--><div class="two-boxes even">
<p><span class="step">2</span> On peut assortir une boîte des class <code>"odd"</code> (nothing left) et <code>"even"</code> pour que les marges se placent correctement.</p>
</div><!--
--><div class="two-boxes odd">
<p><span class="step">3</span> Attention, il faut soit ne pas retourner à la ligne entre la fermeture d'une boîte <code>"two-boxes"</code> et l'ouverture de la suivante soit adopter la méthode de commentaire vide mise en place ici et expliquée chez <a href="https://www.alsacreations.com/astuce/lire/1432-display-inline-block-espaces-indesirables.html">Alsacréations</a> («&nbsp;Méthode 2&nbsp;»).</p>
</div><!--
--><div class="two-boxes even">
<div class="two-boxes odd">
<p><span class="step">4</span> On peut bien sûr imbriquer des boîtes de class <code>"two-boxes"</code>
au sein d'une boîte <code>"two-boxes" afin qu'elles…</code>…</p>
</div><div class="two-boxes even">
<p><span class="step">4 bis</span>… se distribuent horizontalement comme dans une boîte <code>"one-box"</code>.</p>
</div>
</div>
</div>
</div>
<div id="three-boxes" class="multi-part" title="Three-boxes">
<h4>Boîtes distribuées trois par trois</h4>
<div>
<div class="three-boxes">
<div class="box">
<p>Sur le même principe que les « two-boxes » on peut utiliser des boîtes de class <code>"three-boxes"</code> pour répartir les contenus sur trois colonnes de 30% chacune (le reste est occupé par les marges).</p>
</div>
</div><!--
--><div class="three-boxes">
<div class="box">
<p>Comme pour les "two-boxes" il faut soit ne pas laisser d'espace ou de retour à la ligne entre les boîtes, soit adopter la méthode recommandée plus haut.</p>
</div>
</div><!--
--><div class="three-boxes">
<div class="box">
<p>Dans les « two-boxes » comme dans les « three-boxes », on peut placer à l'intérieur plusieurs autres div de class="box" qui s'afficheront les unes à côté des autres ou l'une en dessous de l'autre selon la place dont elles disposent.</p>
</div>
</div>
</div>
</div>
<div id="two-cols-50-50" class="multi-part" title="Two-cols (50/50)">
<h4>Deux colonnes flottantes de largeurs égales</h4>
<div class="two-cols clearfix">
<div class="col">
<p>La div englobante porte la class <code>"two-cols"</code>, chacune de ses div porte la class <code>"col"</code>.
Sans autre précision les deux colonnes sont d'égale largeur.</p>
</div>
<div class="col">
<p>Attention : ces colonnes sont construites avec des flottants, il faut donc penser à mettre une class <code>clear</code> à l'élément suivant ou ajouter la class <code>"clearfix"</code> à la <code>div class="two-cols"</code>.</p>
</div>
</div>
</div>
<div id="two-cols-70-30" class="multi-part" title="Two-cols (70/30)">
<h4>Deux colonnes flottantes de largeurs inégales</h4>
<div class="two-cols clearfix">
<div class="col70">
<p><span class="step">col70</span> La div englobante porte la class <code>"two-cols"</code>.
Pour obtenir des colonnes inégales, on dispose des classes <code>"col70"</code> et <code>col30</code> à attribuer à l'une ou à l'autre de ses colonnes.</p>
</div>
<div class="col30">
<p><span class="step">col30</span> Penser à mettre une class <code>"clear"</code> à l'élément suivant ou ajouter la class <code>"clearfix"</code> <code>div class="two-cols"</code>.</p>
</div>
</div>
</div>
<div id="three-cols" class="multi-part" title="Three-cols (deprecated)">
<h4>Trois colonnes flottantes de largeurs égales</h4>
<p class="warning"><strong>Deprecated.</strong> Ces règles sont conservées dans la 2.6 par souci de rétro-compatibilité mais il est recommandé d'utiliser désormais le colonnage <a href="#three-boxes">three-boxes</a>.</p>
<div class="three-cols clearfix">
<div class="col">
<h5>Colonne 1</h5>
<p>La div englobante porte la class <code>"three-cols"</code>, chacune de ses div porte la class <code>"col"</code>. Les trois colonnes sont d'égale largeur.</p>
</div>
<div class="col">
<h5>Colonne 2</h5>
<p>Voici une deuxième colonne. N'oubliez pas d'ajouter la class <code>"clearfix"</code> à la class <code>"three-cols"</code> ou un élément de class <code>"clear"</code> après cet élément.</p>
</div>
<div class="col">
<h5>Colonne 3</h5>
<p>Voilà la troisième colonne.</p>
</div>
</div>
</div>
<hr />
<p><strong>Note :</strong> dans les exemples les valeurs et les numérotations sont placées dans un <code>span class="step"</code> (et ressortent donc dans un petit bloc à fond gris).</p>
<h2>Interactions</h2>
<h3 id="elements">Éléments de formulaire</h3>
<form class="two-cols clearfix" action="#">
<div class="col">
<p><label for="ex1">Label simple + input text :</label><input id="ex1" type="text" /></p>
<p class="form-note">p class="form-note".</p>
<p><label for="ex4" class="classic">Label class="classic" + input text :</label> <input id="ex4" type="text" /></p>
<p><label for="ex2" class="required"><abbr title="Champ obligatoire">*</abbr> Label class="required" :</label> <input id="ex2" type="text" required placeholder="exemple" /><span class="form-note">span class="form-note"</span></p>
<p><label for="ex11" class="bold">Label class="bold" :</label> <input id="ex11" type="text" /></p>
<p class="form-note">La class="bold" est bien sûr à écrire en minuscules.</p>
<p><label for="ex3">Input class="maximal" :</label> <input id="ex3" type="text" class="maximal" /></p>
</div>
<div class="col">
<p class="field"><label for="ex5">p.field label + input :</label><input id="ex5" type="text" /></p>
<p class="field"><label for="ex6">p.field label + select :</label>
<select id="ex6"><option value="opt2">Option 2</option><option selected="selected" value="opt2">Option 2</option></select>
</p>
<p><label class="classic" for="ex7"><input type="checkbox" checked="checked" id="ex7" value="1" name="ex7" />
Checkbox (label.classic)</label></p>
<p><label class="classic" for="ex8-1"><input type="radio" checked="checked" id="ex8-1" value="ex8-1" name="ex8-1" />
Bouton radio 1 (label.classic)</label></p>
<p><label class="classic" for="ex8-2"><input type="radio" id="ex8-2" value="ex8-2" name="ex8-2" />
Bouton radio 2 (label.classic)</label></p>
<p class="form-note">Les checkboxes et les boutons radio sont dans la balise &lt;label&gt;.</p>
<p><label class="classic" for="ex9"><input type="checkbox"
checked="checked" id="ex9" value="1" title="intitulé du champ" /></label> <label
for="ex10" class="classic">checkbox.classic + label class="classic" :</label> <input id="ex10" type="text" /></p>
</div>
</form>
<form action="#" class="clear">
<fieldset>
<legend>Légende de fieldset</legend>
<p>Attention: Les fieldsets ne doivent être utilisés que pour isoler un groupe de champs au sein d'un formulaire.</p>
</fieldset>
</form>
<h3 id="boutons">Boutons</h3>
<div class="clearfix">
<p><a class="button add">a.button.add</a> Se place en haut à droite (dans un p.top-add)</p>
<p><input type="button" value="Type button" /> <a href="#" class="button">a.button</a> <input type="reset" value="Type reset" /> <a href="#" class="button reset">a.reset</a></p>
<p><input type="submit" value="Type submit" /> <input type="submit" class="delete" value="Type submit class delete" /> <a href="#" class="button delete">a.button delete</a></p>
<p><input type="submit" value="Type submit class disabled" class="disabled" /></p>
</div>
<h3 id="messages">Messages</h3>
<h4 class="smart-title">Messages système</h4>
<p>Il existe quatre types de messages système auxquels correspondent des classes CSS : .error, .message, .success, .warning-msg. Ils s'affichent en haut de page, sous le titre/breadcrumb.</p>
<div class="message">
<p>Message simple. Le plus souvent horodaté dcPage::message</p>
</div>
<div class="success">
<p>Message de succès. Le plus souvent horodaté dcPage::success</p>
</div>
<div class="warning-msg">
<p>Message warning. Non horodaté dcPage::warning</p>
</div>
<div class="error">
<p>Message d'erreur. Non horodaté dcPage::error</p>
</div>
<p>La classe .static-msg peut être utilisée directement pour affichage en haut de page :</p>
<div class="static-msg">
<p>Comme le message simple mais sans effets de transition.</p>
</div>
<p>Un type de message réservé à Dotclear peut s'afficher en haut de la page :</p>
<div class="dc-update">
<h3>Dotclear 42 est disponible</h3>
<p><a class="button submit" href="#">Mettre à jour maintenant</a>
<a class="button" href="u#">Me le rappeler plus tard</a></p>
<p class="updt-info"><a href="#">Informations sur cette version</a></p>
</div>
<h4 class="smart-title">Messages contextuels</h4>
<p class="warn">Paragraphe de message d'alerte class warn ou warning.</p>
<p class="info">Paragraphe de message de class info.</p>
<p>Ces messages sont en display:inline-block. Le fond s'adapte à la longueur du message.</p>
<h2>Navigation</h2>
<h3 id="direct">Selecteur d'accès direct</h3>
<p>Sur des pages longues et denses comme les pages about:config ou about:preferences, on peut utiliser un sélecteur pour faciliter l'accès direct aux sections.</p>
<p class="anchor-nav">
<label class="classic" for="lp_nav">Aller à : </label>
<select id="lp_nav" name="lp_nav">
<option value="#l_accessibility">accessibility</option>
<option value="#l_dashboard">dashboard</option>
<option value="#l_dmhostingmonitor">dmhostingmonitor</option>
<option value="#l_dmpending">dmpending</option>
<option value="#l_favorites">favorites</option>
<option value="#l_filters">filters</option>
<option value="#l_interface">interface</option>
<option value="#l_lists">lists</option>
<option value="#l_toggles">toggles</option>
</select>
<input type="submit" id="lp_submit" value="Ok" style="display: none;" />
<input type="hidden" value="aboutConfig" name="p" />
</p>
<h3 id="prevnext">Navigation contextuelle</h3>
<p><a title="Titre du lien" href="https://fr.dotclear.org/blog" class="onblog_link outgoing">Lien vers le blog <img alt="" src="images/outgoing-link.svg" /></a></p>
<p class="nav_prevnext"><a title="Titre de l'élément précédente" href="post.php?id=4145">«&nbsp;Élément précédent</a> | <a title="Titre de l'élément suivant" href="#">Élément suivant&nbsp;»</a></p>
<h3 id="pseudo-tabs">Pseudo-onglets </h3>
<p>Les pseudo-onglets permettent d'ajouter des sous-pages qui sont des liens vers d'autres pages, par opposition aux onglets qui sont des sections internes à la page.</p>
<p>Les pseudo-onglets sont à positionner immédiatement après le breadcrumb (ici un hr simule le trait sous le breadcrumb).</p>
<p>Ces pseudo-onglets doivent être définis avec un <code>&lt;ul class="pseudo-tabs"&gt;</code> et des <code>&lt;li&gt;</code>.</p>
<hr style="margin-bottom: .75em;" />
<ul class="pseudo-tabs">
<li><a href="#">Page 1</a></li>
<li><a href="#">Autre faux onglet</a></li>
<li><a href="#" class="active">Onglet actif</a></li>
<li><a href="#">Liste 4</a></li>
</ul>
<h2 id="common">Tableaux</h2>
<p>Il existe deux mises en forme type de tableaux selon que l'on cherche à faire un tableau ordinaire
ou un tableau dont on peut déplacer les lignes par glisser déposer (voir plus bas). Cependant certaines règles
sont communes à tout les tableaux.</p>
<h3>Règles communes</h3>
<h4>Largeur du tableau</h4>
<p>Sauf pour des tableaux particuliers (absents dans l'admin mais qui pourraient être nécessaires
à un plugin,les tableaux occupent toute la largeur de la page. Afin que les tableaux soient consultables
sur un mobile en navigant horizontalement, on englobe le tableau dans une <code>div class="table-outer"</code>,
qui servira de «&nbsp;conteneur&nbsp;».</p>
<h4>Accessibilité</h4>
<p>Les éléments caption, th, scope sont nécessaires à l'accessibilité. Ne les oubliez pas&nbsp;!&nbsp;».
On peut utiliser la <code>class="hidden"</code> sur l'élément <code>caption</code> (qui accueille
le titre du tableau) si vous ne souhaitez pas qu'il soit affiché sur la page.</p>
<h4>Les classes</h4>
<p>Des classes particulières peuvent être attribuées aux lignes :</p>
<ul>
<li><code>line</code> (systématique) : pour les traits horizontaux et le fond gris léger
au survol&nbsp;;</li>
<li><code>offline</code> : pour un noir estompé (gris quoi).</li>
</ul>
<p>Des classes particulières peuvent être appliquées aux cellules :</p>
<ul>
<li><code>nowrap</code> : pas de retour à la ligne dans la cellule, quelle que soit la
largeur de la page&nbsp;;</li>
<li><code>maximal</code> : la cellule prendra toute la largeur restante disponible&nbsp;;</li>
<li><code>count</code> : le contenu de la cellule sera aligné à droite avec un petit retrait.</li>
</ul>
<h3 id="courants">Tableau classique</h3>
<div class="table-outer">
<table>
<caption class="hidden">Liste des publications</caption>
<tr>
<th colspan="2" class="first">Titre</th>
<th scope="col">Date</th>
<th scope="col">Catégorie</th>
<th scope="col">Auteur</th>
<th scope="col">Commentaires</th>
<th scope="col">Rétroliens</th>
<th scope="col">État</th>
</tr>
<tr class="line">
<td class="nowrap"><input type="checkbox" name="name1" value="value1" /></td>
<td class="maximal" scope="row"><a href="#">Mon cher Franck</a></td>
<td class="nowrap count">06/08/2013 19:16</td>
<td class="nowrap"><a href="#">Les aventures du clafoutis</a></td>
<td class="nowrap">kozlika</td><td class="nowrap count">4</td>
<td class="nowrap count">0</td><td class="nowrap status"><img alt="Publié" title="Publié" src="images/check-on.png" /> <img alt="Sélectionné" title="Sélectionné" src="images/selected.png" /> </td>
</tr>
<tr class="line offline">
<td class="nowrap"><input type="checkbox" name="name2" value="value2" /></td>
<td class="maximal" scope="row"><a href="#">Dotclear 2.3.0</a></td>
<td class="nowrap count">16/05/2011 22:29</td>
<td class="nowrap"><a href="#">Les aventures du clafoutis</a></td>
<td class="nowrap">kozlika</td><td class="nowrap count">5</td>
<td class="nowrap count">0</td><td class="nowrap status"><img alt="Non publié" title="Non publié" src="images/check-off.png" /> <img alt="Sélectionné" title="Sélectionné" src="images/selected.png" /> </td>
</tr>
<tr class="line">
<td class="nowrap"><input type="checkbox" name="entries[]" value="2148" /></td>
<td class="maximal" scope="row"><a href="#">Causons opéra au Tamm Bara</a></td>
<td class="nowrap count">24/11/2009 23:10</td>
<td class="nowrap"><a href="#">Les aventures du clafoutis</a></td>
<td class="nowrap">kozlika</td>
<td class="nowrap count">4</td><td class="nowrap count">1</td>
<td class="nowrap status"><img alt="Publié" title="Publié" src="images/check-on.png" /> </td>
</tr>
<tr class="line">
<td class="nowrap"><input type="checkbox" name="entries[]" value="2136" /></td>
<td class="maximal" scope="row"><a href="#">Souffler six bougies</a></td>
<td class="nowrap count">14/08/2009 00:00</td><td class="nowrap"><a href="#">Les aventures du clafoutis</a></td>
<td class="nowrap">kozlika</td>
<td class="nowrap count">4</td><td class="nowrap count">2</td><td class="nowrap status"><img alt="Publié" title="Publié" src="images/check-on.png" /> </td>
</tr>
<tr class="line">
<td class="nowrap"><input type="checkbox" name="entries[]" value="2129" /></td>
<td class="maximal" scope="row"><a href="#">Dotclear et grenadine, troisième édition</a></td>
<td class="nowrap count">15/06/2009 07:39</td>
<td class="nowrap"><a href="#">Les aventures du clafoutis</a></td>
<td class="nowrap">kozlika</td>
<td class="nowrap count">9</td>
<td class="nowrap count">1</td>
<td class="nowrap status"><img alt="Publié" title="Publié" src="images/check-on.png" /> </td>
</tr>
<tr class="line">
<td class="nowrap"><input type="checkbox" name="entries[]" value="2111" /></td>
<td class="maximal" scope="row"><a href="#">L'abc dotclear est né</a></td>
<td class="nowrap count">19/03/2009 10:31</td><td class="nowrap"><a href="#">Les aventures du clafoutis</a></td>
<td class="nowrap">kozlika</td>
<td class="nowrap count">1</td><td class="nowrap count">0</td>
<td class="nowrap status"><img alt="Publié" title="Publié" src="images/check-on.png" /> </td>
</tr>
</table>
</div>
<h3 id="dragable">Tableau avec ordonnancement</h3>
<p>Les tableaux permettant l'ordonnancement doivent offrir la possibilité d'effectuer le classement grâce à
des inputs placés en début de ligne pour que le classement soit possible même lorsque cette fonctionnalité est
désactivée (via les préférences utilisateurs, voire une désactivation complète du javascript dans le navigateur).</p>
<div class="table-outer">
<table class="maximal dragable">
<thead>
<tr>
<th colspan="3">Titre</th>
<th>Date</th>
<th>Auteur</th>
<th>Commentaires</th>
<th>Rétroliens</th>
<th>État</th>
</tr>
</thead>
<tbody id="pageslist">
<tr class="line" id="p10899">
<td class="nowrap handle minimal">
<input type="text" size="2" name="order[10899]" maxlength="3" value="1" class="position" title="position de Mentions légales" />
</td>
<td class="nowrap">
<input type="checkbox" name="entries[]" value="10899" title="Sélectionner cette page" />
</td>
<td class="maximal"><a href="#">Mentions légales</a>
</td>
<td class="nowrap">17/12/2008 07:35</td>
<td class="nowrap">franck</td>
<td class="nowrap">0</td>
<td class="nowrap">0</td>
<td class="nowrap status">
<img alt="Publié" title="Publié" src="images/check-on.png" />
</td>
</tr>
<tr class="line" id="p10937">
<td class="nowrap handle minimal">
<input type="text" size="2" name="order[10937]" maxlength="3" value="2" class="position" title="position de Page active et cachée" />
</td>
<td class="nowrap">
<input type="checkbox" name="entries[]" value="10937" title="Sélectionner cette page" />
</td>
<td class="maximal"><a href="#">Page active et cachée</a>
</td>
<td class="nowrap">26/10/2012 11:08</td>
<td class="nowrap">admin</td>
<td class="nowrap">0</td>
<td class="nowrap">0</td>
<td class="nowrap status">
<img alt="Publié" title="Publié" src="images/check-on.png" />
<img alt="Masqué" title="Masqué" src="images/hidden.png" />
</td>
</tr>
<tr class="line offline" id="p11047">
<td class="nowrap handle minimal">
<input type="text" size="2" name="order[11047]" maxlength="3" value="3" class="position" title="position de Page révisionnable" />
</td>
<td class="nowrap">
<input type="checkbox" name="entries[]" value="11047" title="Sélectionner cette page" />
</td>
<td class="maximal"><a href="#">Page révisionnable</a>
</td>
<td class="nowrap">14/12/2012 13:26</td>
<td class="nowrap">admin</td>
<td class="nowrap">0</td>
<td class="nowrap">0</td>
<td class="nowrap status">
<img alt="En attente" title="En attente" src="images/check-wrn.png" />
</td>
</tr>
<tr class="line offline" id="p10939">
<td class="nowrap handle minimal">
<input type="text" size="2" name="order[10939]" maxlength="3" value="4" class="position" title="position de Programme" />
</td>
<td class="nowrap">
<input type="checkbox" name="entries[]" value="10939" title="Sélectionner cette page" />
</td>
<td class="maximal"><a href="#">Programme</a>
</td>
<td class="nowrap">26/10/2020 11:23</td>
<td class="nowrap">admin</td>
<td class="nowrap">0</td>
<td class="nowrap">0</td>
<td class="nowrap status">
<img alt="Programmé" title="Programmé" src="images/scheduled.png" />
</td>
</tr>
<tr class="line offline" id="p10940">
<td class="nowrap handle minimal">
<input type="text" size="2" name="order[10940]" maxlength="3" value="5" class="position" title="position de Protégée" />
</td>
<td class="nowrap">
<input type="checkbox" name="entries[]" value="10940" title="Sélectionner cette page" />
</td>
<td class="maximal"><a href="#">Protégée</a>
</td>
<td class="nowrap">26/10/2012 11:23</td>
<td class="nowrap">admin</td>
<td class="nowrap">0</td>
<td class="nowrap">0</td>
<td class="nowrap status">
<img alt="En attente" title="En attente" src="images/check-wrn.png" />
<img alt="Protégé" title="Protégé" src="images/locker.png" />
</td>
</tr>
</tbody>
</table>
</div>
<h2 id="iconset">Icônes</h2>
<p>Les icônes utilisées dans l'administration sont présentes en deux formats&nbsp; 64*64px pour les grandes
(qui sont affichées sur le tableau de bord si la page correspondante est choisie en favori par l'utilisateur) et
16*16px pour les petits formats.</p>
<p>La plupart sont dérivées de la fonte d'icônes <a href="https://www.elegantthemes.com/blog/resources/elegant-icon-font">Elegant Font</a>. Les autres sont des images vectorielles réalisées
par la DC Team. Nous les avons nommées <em>Traviata</em>. La palette de couleurs utilisée est la suivante&nbsp;:</p>
<p class="txt-center"><img src="images/palette-traviata.png" alt="palette des couleurs utilisées pour les icônes" /></p>
<p class="txt-center">Bleu&nbsp;: #137bbb - Vert&nbsp;: #9ac123 - Rouge&nbsp;: #c44d58 - Bleu ciel&nbsp;: #a2cbe9 - Gris clair&nbsp;: #ececec -
Gris moyen&nbsp;: #b2b2b2 - Gris foncé&nbsp;: #676e78.</p>
</div><!-- /content -->
</div><!-- /main -->
<div id="main-menu">
<ul><li class="pretty-title">Typographie
<ul>
<li><a href="#texte">Texte</a></li>
<li><a href="#titres">Titres hx</a></li>
</ul>
</li>
<li class="pretty-title">Layouts
<ul>
<li><a href="#onglets">Onglets</a></li>
<li><a href="#multi-colonnage">Multi-colonnage</a></li>
</ul>
</li>
<li class="pretty-title">Interactions
<ul>
<li><a href="#elements">Éléments de formulaire</a></li>
<li><a href="#boutons">Boutons</a></li>
<li><a href="#messages">Messages</a></li>
</ul>
</li>
<li class="pretty-title">Navigation
<ul>
<li><a href="#direct">Accès direct</a></li>
<li><a href="#prevnext">Précédent, suivant</a></li>
<li><a href="#pseudo-tabs">Pseudo-onglets</a></li>
</ul>
</li>
<li class="pretty-title">Tableaux
<ul>
<li><a href="#commons">Règles communes</a></li>
<li><a href="#courants">Tableaux courants</a></li>
<li><a href="#dragables">Tableaux ordonnancés</a></li>
</ul>
</li>
</ul>
<div class="info vertical-separator">
<p>Cette page vise à présenter les règles graphiques et conventions utilisées dans les pages de l'administration
d'une installation Dotclear, à l'usage des contributeurs et développeurs d'extensions. Elle en est elle-même
une illustration. L'observation de son code source peut donc servir de complément aux descriptions.</p>
</div>
</div><!-- /main-menu -->
<div id="footer">
<a href="https://dotclear.org/" title="Merci de manger des clafoutis."><img src="style/dc_logos/w-dotclear90.png" alt="Merci d'utiliser Dotclear 2.6-dev." /></a>
</div><!-- /footer -->
<!--
.
,;:'`'::
__||
_____/LLLL\_
\__________"|
~^~^~^~^~^~^~^~^~^~
-->
</div><!-- /wrapper -->
</body>
</html>

View File

@ -1,410 +0,0 @@
<?php
/**
* @package Dotclear
* @subpackage Backend
*
* @copyright Olivier Meunier & Association Dotclear
* @copyright GPL-2.0-only
*/
require dirname(__FILE__) . '/../inc/admin/prepend.php';
# If we have a session cookie, go to index.php
if (isset($_SESSION['sess_user_id'])) {
$core->adminurl->redirect('admin.home');
}
# Loading locales for detected language
# That's a tricky hack but it works ;)
$dlang = http::getAcceptLanguage();
$dlang = ($dlang == '' ? 'en' : $dlang);
if ($dlang != 'en' && preg_match('/^[a-z]{2}(-[a-z]{2})?$/', $dlang)) {
l10n::lang($dlang);
l10n::set(dirname(__FILE__) . '/../locales/' . $dlang . '/main');
}
if (defined('DC_ADMIN_URL')) {
$page_url = DC_ADMIN_URL . $core->adminurl->get('admin.auth');
} else {
$page_url = http::getHost() . $_SERVER['REQUEST_URI'];
}
$change_pwd = $core->auth->allowPassChange() && isset($_POST['new_pwd']) && isset($_POST['new_pwd_c']) && isset($_POST['login_data']);
$login_data = !empty($_POST['login_data']) ? html::escapeHTML($_POST['login_data']) : null;
$recover = $core->auth->allowPassChange() && !empty($_REQUEST['recover']);
$safe_mode = !empty($_REQUEST['safe_mode']);
$akey = $core->auth->allowPassChange() && !empty($_GET['akey']) ? $_GET['akey'] : null;
$user_id = $user_pwd = $user_key = $user_email = null;
$err = $msg = null;
# Auto upgrade
if (empty($_GET) && empty($_POST)) {
require dirname(__FILE__) . '/../inc/dbschema/upgrade.php';
try {
if (($changes = dcUpgrade::dotclearUpgrade($core)) !== false) {
$msg = __('Dotclear has been upgraded.') . '<!-- ' . $changes . ' -->';
}
} catch (Exception $e) {
$err = $e->getMessage();
}
}
# If we have POST login informations, go throug auth process
if (!empty($_POST['user_id']) && !empty($_POST['user_pwd'])) {
$user_id = !empty($_POST['user_id']) ? $_POST['user_id'] : null;
$user_pwd = !empty($_POST['user_pwd']) ? $_POST['user_pwd'] : null;
}
# If we have COOKIE login informations, go throug auth process
elseif (isset($_COOKIE['dc_admin']) && strlen($_COOKIE['dc_admin']) == 104) {
# If we have a remember cookie, go through auth process with user_key
$user_id = substr($_COOKIE['dc_admin'], 40);
$user_id = @unpack('a32', @pack('H*', $user_id));
if (is_array($user_id)) {
$user_id = trim($user_id[1]);
$user_key = substr($_COOKIE['dc_admin'], 0, 40);
$user_pwd = null;
} else {
$user_id = null;
}
}
# Recover password
if ($recover && !empty($_POST['user_id']) && !empty($_POST['user_email'])) {
$user_id = !empty($_POST['user_id']) ? $_POST['user_id'] : null;
$user_email = !empty($_POST['user_email']) ? html::escapeHTML($_POST['user_email']) : '';
try
{
$recover_key = $core->auth->setRecoverKey($user_id, $user_email);
$subject = mail::B64Header('Dotclear ' . __('Password reset'));
$message =
__('Someone has requested to reset the password for the following site and username.') . "\n\n" .
$page_url . "\n" . __('Username:') . ' ' . $user_id . "\n\n" .
__('To reset your password visit the following address, otherwise just ignore this email and nothing will happen.') . "\n" .
$page_url . '?akey=' . $recover_key;
$headers[] = 'From: ' . (defined('DC_ADMIN_MAILFROM') && DC_ADMIN_MAILFROM ? DC_ADMIN_MAILFROM : 'dotclear@local');
$headers[] = 'Content-Type: text/plain; charset=UTF-8;';
mail::sendMail($user_email, $subject, $message, $headers);
$msg = sprintf(__('The e-mail was sent successfully to %s.'), $user_email);
} catch (Exception $e) {
$err = $e->getMessage();
}
}
# Send new password
elseif ($akey) {
try
{
$recover_res = $core->auth->recoverUserPassword($akey);
$subject = mb_encode_mimeheader('Dotclear ' . __('Your new password'), 'UTF-8', 'B');
$message =
__('Username:') . ' ' . $recover_res['user_id'] . "\n" .
__('Password:') . ' ' . $recover_res['new_pass'] . "\n\n" .
preg_replace('/\?(.*)$/', '', $page_url);
$headers[] = 'From: ' . (defined('DC_ADMIN_MAILFROM') && DC_ADMIN_MAILFROM ? DC_ADMIN_MAILFROM : 'dotclear@local');
$headers[] = 'Content-Type: text/plain; charset=UTF-8;';
mail::sendMail($recover_res['user_email'], $subject, $message, $headers);
$msg = __('Your new password is in your mailbox.');
} catch (Exception $e) {
$err = $e->getMessage();
}
}
# Change password and retry to log
elseif ($change_pwd) {
try
{
$tmp_data = explode('/', $_POST['login_data']);
if (count($tmp_data) != 3) {
throw new Exception();
}
$data = [
'user_id' => base64_decode($tmp_data[0]),
'cookie_admin' => $tmp_data[1],
'user_remember' => $tmp_data[2] == '1'
];
if ($data['user_id'] === false) {
throw new Exception();
}
# Check login informations
$check_user = false;
if (isset($data['cookie_admin']) && strlen($data['cookie_admin']) == 104) {
$user_id = substr($data['cookie_admin'], 40);
$user_id = @unpack('a32', @pack('H*', $user_id));
if (is_array($user_id)) {
$user_id = trim($data['user_id']);
$user_key = substr($data['cookie_admin'], 0, 40);
$check_user = $core->auth->checkUser($user_id, null, $user_key) === true;
} else {
$user_id = trim($user_id);
}
}
if (!$core->auth->allowPassChange() || !$check_user) {
$change_pwd = false;
throw new Exception();
}
if ($_POST['new_pwd'] != $_POST['new_pwd_c']) {
throw new Exception(__("Passwords don't match"));
}
if ($core->auth->checkUser($user_id, $_POST['new_pwd']) === true) {
throw new Exception(__("You didn't change your password."));
}
$cur = $core->con->openCursor($core->prefix . 'user');
$cur->user_change_pwd = 0;
$cur->user_pwd = $_POST['new_pwd'];
$core->updUser($core->auth->userID(), $cur);
$core->session->start();
$_SESSION['sess_user_id'] = $user_id;
$_SESSION['sess_browser_uid'] = http::browserUID(DC_MASTER_KEY);
if ($data['user_remember']) {
setcookie('dc_admin', $data['cookie_admin'], strtotime('+15 days'), '', '', DC_ADMIN_SSL);
}
$core->adminurl->redirect('admin.home');
} catch (Exception $e) {
$err = $e->getMessage();
}
}
# Try to log
elseif ($user_id !== null && ($user_pwd !== null || $user_key !== null)) {
# We check the user
$check_user = $core->auth->checkUser($user_id, $user_pwd, $user_key, false) === true;
if ($check_user) {
$check_perms = $core->auth->findUserBlog() !== false;
} else {
$check_perms = false;
}
$cookie_admin = http::browserUID(DC_MASTER_KEY . $user_id .
$core->auth->cryptLegacy($user_id)) . bin2hex(pack('a32', $user_id));
if ($check_perms && $core->auth->mustChangePassword()) {
$login_data = join('/', [
base64_encode($user_id),
$cookie_admin,
empty($_POST['user_remember']) ? '0' : '1'
]);
if (!$core->auth->allowPassChange()) {
$err = __('You have to change your password before you can login.');
} else {
$err = __('In order to login, you have to change your password now.');
$change_pwd = true;
}
} elseif ($check_perms && !empty($_POST['safe_mode']) && !$core->auth->isSuperAdmin()) {
$err = __('Safe Mode can only be used for super administrators.');
} elseif ($check_perms) {
$core->session->start();
$_SESSION['sess_user_id'] = $user_id;
$_SESSION['sess_browser_uid'] = http::browserUID(DC_MASTER_KEY);
if (!empty($_POST['blog'])) {
$_SESSION['sess_blog_id'] = $_POST['blog'];
}
if (!empty($_POST['safe_mode']) && $core->auth->isSuperAdmin()) {
$_SESSION['sess_safe_mode'] = true;
}
if (!empty($_POST['user_remember'])) {
setcookie('dc_admin', $cookie_admin, strtotime('+15 days'), '', '', DC_ADMIN_SSL);
}
$core->adminurl->redirect('admin.home');
} else {
if (isset($_COOKIE['dc_admin'])) {
unset($_COOKIE['dc_admin']);
setcookie('dc_admin', false, -600, '', '', DC_ADMIN_SSL);
}
if ($check_user) {
$err = __('Insufficient permissions');
} else {
$err = __('Wrong username or password');
}
}
}
if (isset($_GET['user'])) {
$user_id = $_GET['user'];
}
header('Content-Type: text/html; charset=UTF-8');
// Prevents Clickjacking as far as possible
header('X-Frame-Options: SAMEORIGIN'); // FF 3.6.9+ Chrome 4.1+ IE 8+ Safari 4+ Opera 10.5+
?>
<!DOCTYPE html>
<html lang="<?php echo $dlang; ?>">
<head>
<meta charset="UTF-8" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="Content-Language" content="<?php echo $dlang; ?>" />
<meta name="ROBOTS" content="NOARCHIVE,NOINDEX,NOFOLLOW" />
<meta name="GOOGLEBOT" content="NOSNIPPET" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title><?php echo html::escapeHTML(DC_VENDOR_NAME); ?></title>
<link rel="icon" type="image/png" href="images/favicon96-logout.png" />
<link rel="shortcut icon" href="../favicon.ico" type="image/x-icon" />
<?php
echo dcPage::jsCommon();
?>
<link rel="stylesheet" href="style/default.css" type="text/css" media="screen" />
<?php
# --BEHAVIOR-- loginPageHTMLHead
$core->callBehavior('loginPageHTMLHead');
echo dcPage::jsLoad('js/_auth.js');
?>
</head>
<body id="dotclear-admin" class="auth">
<form action="<?php echo $core->adminurl->get('admin.auth'); ?>" method="post" id="login-screen">
<h1 role="banner"><?php echo html::escapeHTML(DC_VENDOR_NAME); ?></h1>
<?php
if ($err) {
echo '<div class="error" role="alert">' . $err . '</div>';
}
if ($msg) {
echo '<p class="success" role="alert">' . $msg . '</p>';
}
if ($akey) {
echo '<p><a href="' . $core->adminurl->get('admin.auth') . '">' . __('Back to login screen') . '</a></p>';
} elseif ($recover) {
echo
'<div class="fieldset" role="main"><h2>' . __('Request a new password') . '</h2>' .
'<p><label for="user_id">' . __('Username:') . '</label> ' .
form::field('user_id', 20, 32,
[
'default' => html::escapeHTML($user_id),
'autocomplete' => 'username'
]
) .
'</p>' .
'<p><label for="user_email">' . __('Email:') . '</label> ' .
form::email('user_email',
[
'default' => html::escapeHTML($user_email),
'autocomplete' => 'email'
]
) .
'</p>' .
'<p><input type="submit" value="' . __('recover') . '" />' .
form::hidden('recover', 1) . '</p>' .
'</div>' .
'<div id="issue">' .
'<p><a href="' . $core->adminurl->get('admin.auth') . '">' . __('Back to login screen') . '</a></p>' .
'</div>';
} elseif ($change_pwd) {
echo
'<div class="fieldset"><h2>' . __('Change your password') . '</h2>' .
'<p><label for="new_pwd">' . __('New password:') . '</label> ' .
form::password('new_pwd', 20, 255,
[
'autocomplete' => 'new-password'
]
) . '</p>' .
'<p><label for="new_pwd_c">' . __('Confirm password:') . '</label> ' .
form::password('new_pwd_c', 20, 255,
[
'autocomplete' => 'new-password'
]
) . '</p>' .
'</div>' .
'<p><input type="submit" value="' . __('change') . '" />' .
form::hidden('login_data', $login_data) . '</p>';
} else {
if (is_callable([$core->auth, 'authForm'])) {
echo $core->auth->authForm($user_id);
} else {
if ($safe_mode) {
echo '<div class="fieldset" role="main">';
echo '<h2>' . __('Safe mode login') . '</h2>';
echo
'<p class="form-note">' .
__('This mode allows you to login without activating any of your plugins. This may be useful to solve compatibility problems') . '&nbsp;</p>' .
'<p class="form-note">' . __('Disable or delete any plugin suspected to cause trouble, then log out and log back in normally.') .
'</p>';
} else {
echo '<div class="fieldset" role="main">';
}
echo
'<p><label for="user_id">' . __('Username:') . '</label> ' .
form::field('user_id', 20, 32,
[
'default' => html::escapeHTML($user_id),
'autocomplete' => 'username'
]
) . '</p>' .
'<p><label for="user_pwd">' . __('Password:') . '</label> ' .
form::password('user_pwd', 20, 255,
[
'autocomplete' => 'current-password'
]
) . '</p>' .
'<p>' .
form::checkbox('user_remember', 1) .
'<label for="user_remember" class="classic">' .
__('Remember my ID on this device') . '</label></p>' .
'<p><input type="submit" value="' . __('log in') . '" class="login" /></p>';
if (!empty($_REQUEST['blog'])) {
echo form::hidden('blog', html::escapeHTML($_REQUEST['blog']));
}
if ($safe_mode) {
echo
form::hidden('safe_mode', 1) .
'</div>';
} else {
echo '</div>';
}
echo
'<p id="cookie_help" class="error">' . __('You must accept cookies in order to use the private area.') . '</p>';
echo '<div id="issue">';
if ($safe_mode) {
echo
'<p><a href="' . $core->adminurl->get('admin.auth') . '" id="normal_mode_link">' . __('Get back to normal authentication') . '</a></p>';
} else {
echo '<p id="more"><strong>' . __('Connection issue?') . '</strong></p>';
if ($core->auth->allowPassChange()) {
echo '<p><a href="' . $core->adminurl->get('admin.auth', ['recover' => 1]) . '">' . __('I forgot my password') . '</a></p>';
}
echo '<p><a href="' . $core->adminurl->get('admin.auth', ['safe_mode' => 1]) . '" id="safe_mode_link">' . __('I want to log in in safe mode') . '</a></p>';
}
echo '</div>';
}
}
?>
</form>
</body>
</html>

View File

@ -1,113 +0,0 @@
<?php
/**
* @package Dotclear
* @subpackage Backend
*
* @copyright Olivier Meunier & Association Dotclear
* @copyright GPL-2.0-only
*/
require dirname(__FILE__) . '/../inc/admin/prepend.php';
dcPage::checkSuper();
$blog_id = '';
$blog_url = '';
$blog_name = '';
$blog_desc = '';
# Create a blog
if (!isset($_POST['id']) && (isset($_POST['create']))) {
$cur = $core->con->openCursor($core->prefix . 'blog');
$blog_id = $cur->blog_id = $_POST['blog_id'];
$blog_url = $cur->blog_url = $_POST['blog_url'];
$blog_name = $cur->blog_name = $_POST['blog_name'];
$blog_desc = $cur->blog_desc = $_POST['blog_desc'];
try
{
# --BEHAVIOR-- adminBeforeBlogCreate
$core->callBehavior('adminBeforeBlogCreate', $cur, $blog_id);
$core->addBlog($cur);
# Default settings and override some
$core->blogDefaults($cur->blog_id);
$blog_settings = new dcSettings($core, $cur->blog_id);
$blog_settings->addNamespace('system');
$blog_settings->system->put('lang', $core->auth->getInfo('user_lang'));
$blog_settings->system->put('blog_timezone', $core->auth->getInfo('user_tz'));
if (substr($blog_url, -1) == '?') {
$blog_settings->system->put('url_scan', 'query_string');
} else {
$blog_settings->system->put('url_scan', 'path_info');
}
# --BEHAVIOR-- adminAfterBlogCreate
$core->callBehavior('adminAfterBlogCreate', $cur, $blog_id, $blog_settings);
dcPage::addSuccessNotice(sprintf(__('Blog "%s" successfully created'), html::escapeHTML($cur->blog_name)));
$core->adminurl->redirect("admin.blog", ['id' => $cur->blog_id]);
} catch (Exception $e) {
$core->error->add($e->getMessage());
}
}
if (!empty($_REQUEST['id'])) {
$edit_blog_mode = true;
include dirname(__FILE__) . '/blog_pref.php';
} else {
dcPage::open(__('New blog'), dcPage::jsConfirmClose('blog-form'),
dcPage::breadcrumb(
[
__('System') => '',
__('Blogs') => $core->adminurl->get("admin.blogs"),
__('New blog') => ''
])
);
echo
'<form action="' . $core->adminurl->get("admin.blog") . '" method="post" id="blog-form">' .
'<div>' . $core->formNonce() . '</div>' .
'<p><label class="required" for="blog_id"><abbr title="' . __('Required field') . '">*</abbr> ' . __('Blog ID:') . '</label> ' .
form::field('blog_id', 30, 32,
[
'default' => html::escapeHTML($blog_id),
'extra_html' => 'required placeholder="' . __('Blog ID') . '"'
]
) . '</p>' .
'<p class="form-note">' . __('At least 2 characters using letters, numbers or symbols.') . '</p> ';
echo
'<p><label class="required" for="blog_name"><abbr title="' . __('Required field') . '">*</abbr> ' . __('Blog name:') . '</label> ' .
form::field('blog_name', 30, 255,
[
'default' => html::escapeHTML($blog_name),
'extra_html' => 'required placeholder="' . __('Blog name') . '" lang="' . $core->auth->getInfo('user_lang') . '" ' .
'spellcheck="true"'
]
) . '</p>' .
'<p><label class="required" for="blog_url"><abbr title="' . __('Required field') . '">*</abbr> ' . __('Blog URL:') . '</label> ' .
form::url('blog_url',
[
'size' => 30,
'default' => html::escapeHTML($blog_url),
'extra_html' => 'required placeholder="' . __('Blog URL') . '"'
]
) . '</p>' .
'<p class="area"><label for="blog_desc">' . __('Blog description:') . '</label> ' .
form::textarea('blog_desc', 60, 5,
[
'default' => html::escapeHTML($blog_desc),
'extra_html' => 'lang="' . $core->auth->getInfo('user_lang') . '" spellcheck="true"'
]) . '</p>' .
'<p><input type="submit" accesskey="s" name="create" value="' . __('Create') . '" /></p>' .
'</form>';
dcPage::helpBlock('core_blog_new');
dcPage::close();
}

View File

@ -1,74 +0,0 @@
<?php
/**
* @package Dotclear
* @subpackage Backend
*
* @copyright Olivier Meunier & Association Dotclear
* @copyright GPL-2.0-only
*/
require dirname(__FILE__) . '/../inc/admin/prepend.php';
dcPage::checkSuper();
$blog_id = '';
$blog_name = '';
if (!empty($_POST['blog_id'])) {
try {
$rs = $core->getBlog($_POST['blog_id']);
} catch (Exception $e) {
$core->error->add($e->getMessage());
}
if ($rs->isEmpty()) {
$core->error->add(__('No such blog ID'));
} else {
$blog_id = $rs->blog_id;
$blog_name = $rs->blog_name;
}
}
# Delete the blog
if (!$core->error->flag() && $blog_id && !empty($_POST['del'])) {
if (!$core->auth->checkPassword($_POST['pwd'])) {
$core->error->add(__('Password verification failed'));
} else {
try {
$core->delBlog($blog_id);
dcPage::addSuccessNotice(sprintf(__('Blog "%s" successfully deleted'), html::escapeHTML($blog_name)));
$core->adminurl->redirect("admin.blogs");
} catch (Exception $e) {
$core->error->add($e->getMessage());
}
}
}
dcPage::open(__('Delete a blog'), '',
dcPage::breadcrumb(
[
__('System') => '',
__('Blogs') => $core->adminurl->get("admin.blogs"),
__('Delete a blog') => ''
])
);
if (!$core->error->flag()) {
echo
'<div class="warning-msg"><p><strong>' . __('Warning') . '</strong></p>' .
'<p>' . sprintf(__('You are about to delete the blog %s. Every entry, comment and category will be deleted.'),
'<strong>' . $blog_id . ' (' . $blog_name . ')</strong>') . '</p></div>' .
'<p>' . __('Please give your password to confirm the blog deletion.') . '</p>';
echo
'<form action="' . $core->adminurl->get("admin.blog.del") . '" method="post">' .
'<div>' . $core->formNonce() . '</div>' .
'<p><label for="pwd">' . __('Your password:') . '</label> ' .
form::password('pwd', 20, 255, ['autocomplete' => 'current-password']) . '</p>' .
'<p><input type="submit" class="delete" name="del" value="' . __('Delete this blog') . '" />' .
form::hidden('blog_id', $blog_id) . '</p>' .
'</form>';
}
dcPage::close();

View File

@ -1,907 +0,0 @@
<?php
/**
* @package Dotclear
* @subpackage Backend
*
* @copyright Olivier Meunier & Association Dotclear
* @copyright GPL-2.0-only
*/
$standalone = !isset($edit_blog_mode);
$blog_id = false;
if ($standalone) {
require dirname(__FILE__) . '/../inc/admin/prepend.php';
dcPage::check('admin');
$blog_id = $core->blog->id;
$blog_status = $core->blog->status;
$blog_name = $core->blog->name;
$blog_desc = $core->blog->desc;
$blog_settings = $core->blog->settings;
$blog_url = $core->blog->url;
$action = $core->adminurl->get("admin.blog.pref");
$redir = $core->adminurl->get("admin.blog.pref");
} else {
dcPage::checkSuper();
try
{
if (empty($_REQUEST['id'])) {
throw new Exception(__('No given blog id.'));
}
$rs = $core->getBlog($_REQUEST['id']);
if (!$rs) {
throw new Exception(__('No such blog.'));
}
$blog_id = $rs->blog_id;
$blog_status = $rs->blog_status;
$blog_name = $rs->blog_name;
$blog_desc = $rs->blog_desc;
$blog_settings = new dcSettings($core, $blog_id);
$blog_url = $rs->blog_url;
} catch (Exception $e) {
$core->error->add($e->getMessage());
}
$action = $core->adminurl->get("admin.blog");
$redir = $core->adminurl->get("admin.blog", ['id' => "%s"], '&', true);
}
# Language codes
$lang_combo = dcAdminCombos::getAdminLangsCombo();
# Status combo
$status_combo = dcAdminCombos::getBlogStatusescombo();
# Date format combo
$now = time();
$date_formats = $blog_settings->system->date_formats;
$time_formats = $blog_settings->system->time_formats;
$date_formats_combo = ['' => ''];
foreach ($date_formats as $format) {
$date_formats_combo[dt::str($format, $now)] = $format;
}
$time_formats_combo = ['' => ''];
foreach ($time_formats as $format) {
$time_formats_combo[dt::str($format, $now)] = $format;
}
# URL scan modes
$url_scan_combo = [
'PATH_INFO' => 'path_info',
'QUERY_STRING' => 'query_string'
];
# Post URL combo
$post_url_combo = [
__('year/month/day/title') => '{y}/{m}/{d}/{t}',
__('year/month/title') => '{y}/{m}/{t}',
__('year/title') => '{y}/{t}',
__('title') => '{t}',
__('post id/title') => '{id}/{t}',
__('post id') => '{id}'
];
if (!in_array($blog_settings->system->post_url_format, $post_url_combo)) {
$post_url_combo[html::escapeHTML($blog_settings->system->post_url_format)] = html::escapeHTML($blog_settings->system->post_url_format);
}
# Note title tag combo
$note_title_tag_combo = [
__('H4') => 0,
__('H3') => 1,
__('P') => 2
];
# Image title combo
$img_title_combo = [
__('(none)') => '',
__('Title') => 'Title ;; separator(, )',
__('Title, Date') => 'Title ;; Date(%b %Y) ;; separator(, )',
__('Title, Country, Date') => 'Title ;; Country ;; Date(%b %Y) ;; separator(, )',
__('Title, City, Country, Date') => 'Title ;; City ;; Country ;; Date(%b %Y) ;; separator(, )'
];
if (!in_array($blog_settings->system->media_img_title_pattern, $img_title_combo)) {
$img_title_combo[html::escapeHTML($blog_settings->system->media_img_title_pattern)] = html::escapeHTML($blog_settings->system->media_img_title_pattern);
}
# Image default size combo
$img_default_size_combo = [];
try {
$media = new dcMedia($core);
$img_default_size_combo[__('original')] = 'o';
foreach ($media->thumb_sizes as $code => $size) {
$img_default_size_combo[__($size[2])] = $code;
}
} catch (Exception $e) {
$core->error->add($e->getMessage());
}
# Image default alignment combo
$img_default_alignment_combo = [
__('None') => 'none',
__('Left') => 'left',
__('Right') => 'right',
__('Center') => 'center'
];
# Image default legend and title combo
$img_default_legend_combo = [
__('Legend and title') => 'legend',
__('Title') => 'title',
__('None') => 'none'
];
# Robots policy options
$robots_policy_options = [
'INDEX,FOLLOW' => __("I would like search engines and archivers to index and archive my blog's content."),
'INDEX,FOLLOW,NOARCHIVE' => __("I would like search engines and archivers to index but not archive my blog's content."),
'NOINDEX,NOFOLLOW,NOARCHIVE' => __("I would like to prevent search engines and archivers from indexing or archiving my blog's content.")
];
# jQuery available versions
$jquery_root = dirname(__FILE__) . '/../inc/js/jquery';
$jquery_versions_combo = [__('Default') . ' (' . DC_DEFAULT_JQUERY . ')' => ''];
if (is_dir($jquery_root) && is_readable($jquery_root)) {
if (($d = @dir($jquery_root)) !== false) {
while (($entry = $d->read()) !== false) {
if ($entry != '.' && $entry != '..' && substr($entry, 0, 1) != '.' && is_dir($jquery_root . '/' . $entry)) {
if ($entry != DC_DEFAULT_JQUERY) {
$jquery_versions_combo[$entry] = $entry;
}
}
}
}
}
# Update a blog
if ($blog_id && !empty($_POST) && $core->auth->check('admin', $blog_id)) {
$cur = $core->con->openCursor($core->prefix . 'blog');
$cur->blog_id = $_POST['blog_id'];
$cur->blog_url = preg_replace('/\?+$/', '?', $_POST['blog_url']);
$cur->blog_name = $_POST['blog_name'];
$cur->blog_desc = $_POST['blog_desc'];
if ($core->auth->isSuperAdmin() && in_array($_POST['blog_status'], $status_combo)) {
$cur->blog_status = (int) $_POST['blog_status'];
}
$media_img_t_size = (integer) $_POST['media_img_t_size'];
if ($media_img_t_size < 0) {$media_img_t_size = 100;}
$media_img_s_size = (integer) $_POST['media_img_s_size'];
if ($media_img_s_size < 0) {$media_img_s_size = 240;}
$media_img_m_size = (integer) $_POST['media_img_m_size'];
if ($media_img_m_size < 0) {$media_img_m_size = 448;}
$media_video_width = (integer) $_POST['media_video_width'];
if ($media_video_width < 0) {$media_video_width = 400;}
$media_video_height = (integer) $_POST['media_video_height'];
if ($media_video_height < 0) {$media_video_height = 300;}
$nb_post_for_home = abs((integer) $_POST['nb_post_for_home']);
if ($nb_post_for_home < 1) {$nb_post_for_home = 1;}
$nb_post_per_page = abs((integer) $_POST['nb_post_per_page']);
if ($nb_post_per_page < 1) {$nb_post_per_page = 1;}
$nb_post_per_feed = abs((integer) $_POST['nb_post_per_feed']);
if ($nb_post_per_feed < 1) {$nb_post_per_feed = 1;}
$nb_comment_per_feed = abs((integer) $_POST['nb_comment_per_feed']);
if ($nb_comment_per_feed < 1) {$nb_comment_per_feed = 1;}
try
{
if ($cur->blog_id != null && $cur->blog_id != $blog_id) {
$rs = $core->getBlog($cur->blog_id);
if ($rs) {
throw new Exception(__('This blog ID is already used.'));
}
}
# --BEHAVIOR-- adminBeforeBlogUpdate
$core->callBehavior('adminBeforeBlogUpdate', $cur, $blog_id);
if (!preg_match('/^[a-z]{2}(-[a-z]{2})?$/', $_POST['lang'])) {
throw new Exception(__('Invalid language code'));
}
$core->updBlog($blog_id, $cur);
# --BEHAVIOR-- adminAfterBlogUpdate
$core->callBehavior('adminAfterBlogUpdate', $cur, $blog_id);
if ($cur->blog_id != null && $cur->blog_id != $blog_id) {
if ($blog_id == $core->blog->id) {
$core->setBlog($cur->blog_id);
$_SESSION['sess_blog_id'] = $cur->blog_id;
$blog_settings = $core->blog->settings;
} else {
$blog_settings = new dcSettings($core, $cur->blog_id);
}
$blog_id = $cur->blog_id;
}
$blog_settings->addNameSpace('system');
$blog_settings->system->put('editor', $_POST['editor']);
$blog_settings->system->put('copyright_notice', $_POST['copyright_notice']);
$blog_settings->system->put('post_url_format', $_POST['post_url_format']);
$blog_settings->system->put('lang', $_POST['lang']);
$blog_settings->system->put('blog_timezone', $_POST['blog_timezone']);
$blog_settings->system->put('date_format', $_POST['date_format']);
$blog_settings->system->put('time_format', $_POST['time_format']);
$blog_settings->system->put('comments_ttl', abs((integer) $_POST['comments_ttl']));
$blog_settings->system->put('trackbacks_ttl', abs((integer) $_POST['trackbacks_ttl']));
$blog_settings->system->put('allow_comments', !empty($_POST['allow_comments']));
$blog_settings->system->put('allow_trackbacks', !empty($_POST['allow_trackbacks']));
$blog_settings->system->put('comments_pub', empty($_POST['comments_pub']));
$blog_settings->system->put('trackbacks_pub', empty($_POST['trackbacks_pub']));
$blog_settings->system->put('comments_nofollow', !empty($_POST['comments_nofollow']));
$blog_settings->system->put('wiki_comments', !empty($_POST['wiki_comments']));
$blog_settings->system->put('comment_preview_optional', !empty($_POST['comment_preview_optional']));
$blog_settings->system->put('enable_xmlrpc', !empty($_POST['enable_xmlrpc']));
$blog_settings->system->put('note_title_tag', $_POST['note_title_tag']);
$blog_settings->system->put('nb_post_for_home', $nb_post_for_home);
$blog_settings->system->put('nb_post_per_page', $nb_post_per_page);
$blog_settings->system->put('use_smilies', !empty($_POST['use_smilies']));
$blog_settings->system->put('no_search', !empty($_POST['no_search']));
$blog_settings->system->put('inc_subcats', !empty($_POST['inc_subcats']));
$blog_settings->system->put('media_img_t_size', $media_img_t_size);
$blog_settings->system->put('media_img_s_size', $media_img_s_size);
$blog_settings->system->put('media_img_m_size', $media_img_m_size);
$blog_settings->system->put('media_video_width', $media_video_width);
$blog_settings->system->put('media_video_height', $media_video_height);
$blog_settings->system->put('media_img_title_pattern', $_POST['media_img_title_pattern']);
$blog_settings->system->put('media_img_use_dto_first', !empty($_POST['media_img_use_dto_first']));
$blog_settings->system->put('media_img_no_date_alone', !empty($_POST['media_img_no_date_alone']));
$blog_settings->system->put('media_img_default_size', $_POST['media_img_default_size']);
$blog_settings->system->put('media_img_default_alignment', $_POST['media_img_default_alignment']);
$blog_settings->system->put('media_img_default_link', !empty($_POST['media_img_default_link']));
$blog_settings->system->put('media_img_default_legend', $_POST['media_img_default_legend']);
$blog_settings->system->put('nb_post_per_feed', $nb_post_per_feed);
$blog_settings->system->put('nb_comment_per_feed', $nb_comment_per_feed);
$blog_settings->system->put('short_feed_items', !empty($_POST['short_feed_items']));
if (isset($_POST['robots_policy'])) {
$blog_settings->system->put('robots_policy', $_POST['robots_policy']);
}
$blog_settings->system->put('jquery_needed', !empty($_POST['jquery_needed']));
$blog_settings->system->put('jquery_version', $_POST['jquery_version']);
$blog_settings->system->put('prevents_clickjacking', !empty($_POST['prevents_clickjacking']));
$blog_settings->system->put('static_home', !empty($_POST['static_home']));
$blog_settings->system->put('static_home_url', $_POST['static_home_url']);
# --BEHAVIOR-- adminBeforeBlogSettingsUpdate
$core->callBehavior('adminBeforeBlogSettingsUpdate', $blog_settings);
if ($core->auth->isSuperAdmin() && in_array($_POST['url_scan'], $url_scan_combo)) {
$blog_settings->system->put('url_scan', $_POST['url_scan']);
}
dcPage::addSuccessNotice(__('Blog has been successfully updated.'));
http::redirect(sprintf($redir, $blog_id));
} catch (Exception $e) {
$core->error->add($e->getMessage());
}
}
// Display
if ($standalone) {
$breadcrumb = dcPage::breadcrumb(
[
html::escapeHTML($blog_name) => '',
__('Blog settings') => ''
]
);
} else {
$breadcrumb = dcPage::breadcrumb(
[
__('System') => '',
__('Blogs') => $core->adminurl->get("admin.blogs"),
__('Blog settings') . ' : ' . html::escapeHTML($blog_name) => ''
]);
}
$desc_editor = $core->auth->getOption('editor');
$rte_flag = true;
$rte_flags = @$core->auth->user_prefs->interface->rte_flags;
if (is_array($rte_flags) && in_array('blog_descr', $rte_flags)) {
$rte_flag = $rte_flags['blog_descr'];
}
dcPage::open(__('Blog settings'),
dcPage::jsJson('blog_pref', [
'warning_path_info' => __('Warning: except for special configurations, it is generally advised to have a trailing "/" in your blog URL in PATH_INFO mode.'),
'warning_query_string' => __('Warning: except for special configurations, it is generally advised to have a trailing "?" in your blog URL in QUERY_STRING mode.')
]) .
dcPage::jsConfirmClose('blog-form') .
($rte_flag ? $core->callBehavior('adminPostEditor', $desc_editor['xhtml'], 'blog_desc', ['#blog_desc'], 'xhtml') : '') .
dcPage::jsLoad('js/_blog_pref.js') .
# --BEHAVIOR-- adminBlogPreferencesHeaders
$core->callBehavior('adminBlogPreferencesHeaders') .
dcPage::jsPageTabs(),
$breadcrumb
);
if ($blog_id) {
if (!empty($_GET['add'])) {
dcPage::success(__('Blog has been successfully created.'));
}
if (!empty($_GET['upd'])) {
dcPage::success(__('Blog has been successfully updated.'));
}
echo
'<div class="multi-part" id="params" title="' . __('Parameters') . '">' .
'<div id="standard-pref"><h3>' . __('Blog parameters') . '</h3>' .
'<form action="' . $action . '" method="post" id="blog-form">';
echo
'<div class="fieldset"><h4>' . __('Blog details') . '</h4>' .
$core->formNonce();
echo
'<p><label for="blog_name" class="required"><abbr title="' . __('Required field') . '">*</abbr> ' . __('Blog name:') . '</label>' .
form::field('blog_name', 30, 255,
[
'default' => html::escapeHTML($blog_name),
'extra_html' => 'required placeholder="' . __('Blog name') . ' lang="' . $blog_settings->system->lang .
'" spellcheck="true"'
]
) . '</p>';
echo
'<p class="area"><label for="blog_desc">' . __('Blog description:') . '</label>' .
form::textarea('blog_desc', 60, 5,
[
'default' => html::escapeHTML($blog_desc),
'extra_html' => 'lang="' . $blog_settings->system->lang . '" spellcheck="true"'
]) . '</p>';
if ($core->auth->isSuperAdmin()) {
echo
'<p><label for="blog_status">' . __('Blog status:') . '</label>' .
form::combo('blog_status', $status_combo, $blog_status) . '</p>';
} else {
/*
Only super admins can change the blog ID and URL, but we need to pass
their values to the POST request via hidden html input values so as
to allow admins to update other settings.
Otherwise dcCore::getBlogCursor() throws an exception.
*/
echo
form::hidden('blog_id', html::escapeHTML($blog_id)) .
form::hidden('blog_url', html::escapeHTML($blog_url));
}
echo '</div>';
echo
'<div class="fieldset"><h4>' . __('Blog configuration') . '</h4>' .
'<p><label for="editor">' . __('Blog editor name:') . '</label>' .
form::field('editor', 30, 255, html::escapeHTML($blog_settings->system->editor)) .
'</p>' .
'<p><label for="lang">' . __('Default language:') . '</label>' .
form::combo('lang', $lang_combo, $blog_settings->system->lang, 'l10n') .
'</p>' .
'<p><label for="blog_timezone">' . __('Blog timezone:') . '</label>' .
form::combo('blog_timezone', dt::getZones(true, true), html::escapeHTML($blog_settings->system->blog_timezone)) .
'</p>' .
'<p><label for="copyright_notice">' . __('Copyright notice:') . '</label>' .
form::field('copyright_notice', 30, 255,
[
'default' => html::escapeHTML($blog_settings->system->copyright_notice),
'extra_html' => 'lang="' . $blog_settings->system->lang . '" spellcheck="true"'
]) .
'</p>' .
'</div>';
echo
'<div class="fieldset"><h4>' . __('Comments and trackbacks') . '</h4>' .
'<div class="two-cols">' .
'<div class="col">' .
'<p><label for="allow_comments" class="classic">' .
form::checkbox('allow_comments', '1', $blog_settings->system->allow_comments) .
__('Accept comments') . '</label></p>' .
'<p><label for="comments_pub" class="classic">' .
form::checkbox('comments_pub', '1', !$blog_settings->system->comments_pub) .
__('Moderate comments') . '</label></p>' .
'<p><label for="comments_ttl" class="classic">' . sprintf(__('Leave comments open for %s days') . '.',
form::number('comments_ttl', [
'min' => 0,
'max' => 999,
'default' => $blog_settings->system->comments_ttl]
)) .
'</label></p>' .
'<p class="form-note">' . __('No limit: leave blank.') . '</p>' .
'<p><label for="wiki_comments" class="classic">' .
form::checkbox('wiki_comments', '1', $blog_settings->system->wiki_comments) .
__('Wiki syntax for comments') . '</label></p>' .
'<p><label for="comment_preview_optional" class="classic">' .
form::checkbox('comment_preview_optional', '1', $blog_settings->system->comment_preview_optional) .
__('Preview of comment before submit is not mandatory') . '</label></p>' .
'</div>' .
'<div class="col">' .
'<p><label for="allow_trackbacks" class="classic">' .
form::checkbox('allow_trackbacks', '1', $blog_settings->system->allow_trackbacks) .
__('Accept trackbacks') . '</label></p>' .
'<p><label for="trackbacks_pub" class="classic">' .
form::checkbox('trackbacks_pub', '1', !$blog_settings->system->trackbacks_pub) .
__('Moderate trackbacks') . '</label></p>' .
'<p><label for="trackbacks_ttl" class="classic">' . sprintf(__('Leave trackbacks open for %s days') . '.',
form::number('trackbacks_ttl', [
'min' => 0,
'max' => 999,
'default' => $blog_settings->system->trackbacks_ttl]
)) .
'</label></p>' .
'<p class="form-note">' . __('No limit: leave blank.') . '</p>' .
'<p><label for="comments_nofollow" class="classic">' .
form::checkbox('comments_nofollow', '1', $blog_settings->system->comments_nofollow) .
__('Add "nofollow" relation on comments and trackbacks links') . '</label></p>' .
'</div>' .
'<br class="clear" />' . //Opera sucks
'</div>' .
'<br class="clear" />' . //Opera sucks
'</div>';
echo
'<div class="fieldset"><h4>' . __('Blog presentation') . '</h4>' .
'<div class="two-cols">' .
'<div class="col">' .
'<p><label for="date_format">' . __('Date format:') . '</label> ' .
form::field('date_format', 30, 255, html::escapeHTML($blog_settings->system->date_format)) .
form::combo('date_format_select', $date_formats_combo, ['extra_html' => 'title="' . __('Pattern of date') . '"']) .
'</p>' .
'<p class="chosen form-note">' . __('Sample:') . ' ' . dt::str(html::escapeHTML($blog_settings->system->date_format)) . '</p>' .
'<p><label for="time_format">' . __('Time format:') . '</label>' .
form::field('time_format', 30, 255, html::escapeHTML($blog_settings->system->time_format)) .
form::combo('time_format_select', $time_formats_combo, ['extra_html' => 'title="' . __('Pattern of time') . '"']) .
'</p>' .
'<p class="chosen form-note">' . __('Sample:') . ' ' . dt::str(html::escapeHTML($blog_settings->system->time_format)) . '</p>' .
'<p><label for="use_smilies" class="classic">' .
form::checkbox('use_smilies', '1', $blog_settings->system->use_smilies) .
__('Display smilies on entries and comments') . '</label></p>' .
'<p><label for="no_search" class="classic">' .
form::checkbox('no_search', '1', $blog_settings->system->no_search) .
__('Disable internal search system') . '</label></p>' .
'</div>' .
'<div class="col">' .
'<p><label for="nb_post_for_home" class="classic">' . sprintf(__('Display %s entries on first page'),
form::number('nb_post_for_home', [
'min' => 1,
'max' => 999,
'default' => $blog_settings->system->nb_post_for_home]
)) .
'</label></p>' .
'<p><label for="nb_post_per_page" class="classic">' . sprintf(__('Display %s entries per page'),
form::number('nb_post_per_page', [
'min' => 1,
'max' => 999,
'default' => $blog_settings->system->nb_post_per_page]
)) .
'</label></p>' .
'<p><label for="nb_post_per_feed" class="classic">' . sprintf(__('Display %s entries per feed'),
form::number('nb_post_per_feed', [
'min' => 1,
'max' => 999,
'default' => $blog_settings->system->nb_post_per_feed]
)) .
'</label></p>' .
'<p><label for="nb_comment_per_feed" class="classic">' . sprintf(__('Display %s comments per feed'),
form::number('nb_comment_per_feed', [
'min' => 1,
'max' => 999,
'default' => $blog_settings->system->nb_comment_per_feed]
)) .
'</label></p>' .
'<p><label for="short_feed_items" class="classic">' .
form::checkbox('short_feed_items', '1', $blog_settings->system->short_feed_items) .
__('Truncate feeds') . '</label></p>' .
'<p><label for="inc_subcats" class="classic">' .
form::checkbox('inc_subcats', '1', $blog_settings->system->inc_subcats) .
__('Include sub-categories in category page and category posts feed') . '</label></p>' .
'</div>' .
'</div>' .
'<br class="clear" />' . //Opera sucks
'<hr />' .
'<p><label for="static_home" class="classic">' .
form::checkbox('static_home', '1', $blog_settings->system->static_home) .
__('Display an entry as static home page') . '</label></p>' .
'<p><label for="static_home_url" class="classic">' . __('Entry URL (its content will be used for the static home page):') . '</label> ' .
form::field('static_home_url', 30, 255, html::escapeHTML($blog_settings->system->static_home_url)) .
' <button type="button" id="static_home_url_selector">' . __('Choose an entry') . '</button>' .
'</p>' .
'<p class="form-note">' . __('Leave empty to use the default presentation.') . '</p> ' .
'</div>';
echo
'<div class="fieldset"><h4 id="medias-settings">' . __('Media and images') . '</h4>' .
'<p class="form-note warning">' .
__('Please note that if you change current settings bellow, they will now apply to all new images in the media manager.') .
' ' . __('Be carefull if you share it with other blogs in your installation.') . '<br />' .
__('Set -1 to use the default size, set 0 to ignore this thumbnail size (images only).') . '</p>' .
'<div class="two-cols">' .
'<div class="col">' .
'<h5>' . __('Generated image sizes (max dimension in pixels)') . '</h5>' .
'<p class="field"><label for="media_img_t_size">' . __('Thumbnail') . '</label> ' .
form::number('media_img_t_size', [
'min' => -1,
'max' => 999,
'default' => $blog_settings->system->media_img_t_size
]) .
'</p>' .
'<p class="field"><label for="media_img_s_size">' . __('Small') . '</label> ' .
form::number('media_img_s_size', [
'min' => -1,
'max' => 999,
'default' => $blog_settings->system->media_img_s_size
]) .
'</p>' .
'<p class="field"><label for="media_img_m_size">' . __('Medium') . '</label> ' .
form::number('media_img_m_size', [
'min' => -1,
'max' => 999,
'default' => $blog_settings->system->media_img_m_size
]) .
'</p>' .
'<h5>' . __('Default size of the inserted video (in pixels)') . '</h5>' .
'<p class="field"><label for="media_video_width">' . __('Width') . '</label> ' .
form::number('media_video_width', [
'min' => -1,
'max' => 999,
'default' => $blog_settings->system->media_video_width
]) .
'</p>' .
'<p class="field"><label for="media_video_height">' . __('Height') . '</label> ' .
form::number('media_video_height', [
'min' => -1,
'max' => 999,
'default' => $blog_settings->system->media_video_height
]) .
'</p>' .
'</div>' .
'<div class="col">' .
'<h5>' . __('Default image insertion attributes') . '</h5>' .
'<p class="vertical-separator"><label for="media_img_title_pattern">' . __('Inserted image title') . '</label>' .
form::combo('media_img_title_pattern', $img_title_combo, html::escapeHTML($blog_settings->system->media_img_title_pattern)) . '</p>' .
'<p><label for="media_img_use_dto_first" class="classic">' .
form::checkbox('media_img_use_dto_first', '1', $blog_settings->system->media_img_use_dto_first) .
__('Use original media date if possible') . '</label></p>' .
'<p><label for="media_img_no_date_alone" class="classic">' .
form::checkbox('media_img_no_date_alone', '1', $blog_settings->system->media_img_no_date_alone) .
__('Do not display date if alone in title') . '</label></p>' .
'<p class="form-note info">' . __('It is retrieved from the picture\'s metadata.') . '</p>' .
'<p class="field vertical-separator"><label for="media_img_default_size">' . __('Size of inserted image:') . '</label>' .
form::combo('media_img_default_size', $img_default_size_combo,
(html::escapeHTML($blog_settings->system->media_img_default_size) != '' ? html::escapeHTML($blog_settings->system->media_img_default_size) : 'm')) .
'</p>' .
'<p class="field"><label for="media_img_default_alignment">' . __('Image alignment:') . '</label>' .
form::combo('media_img_default_alignment', $img_default_alignment_combo, html::escapeHTML($blog_settings->system->media_img_default_alignment)) .
'</p>' .
'<p><label for="media_img_default_link">' .
form::checkbox('media_img_default_link', '1', $blog_settings->system->media_img_default_link) .
__('Insert a link to the original image') . '</label></p>' .
'<p class="field"><label for="media_img_default_legend">' . __('Image legend and title:') . '</label>' .
form::combo('media_img_default_legend', $img_default_legend_combo, html::escapeHTML($blog_settings->system->media_img_default_legend)) .
'</p>' .
'</div>' .
'</div>' .
'<br class="clear" />' . //Opera sucks
'</div>' .
'</div>';
echo '<div id="advanced-pref"><h3>' . __('Advanced parameters') . '</h3>';
if ($core->auth->isSuperAdmin()) {
echo '<div class="fieldset"><h4>' . __('Blog details') . '</h4>';
echo
'<p><label for="blog_id" class="required"><abbr title="' . __('Required field') . '">*</abbr> ' . __('Blog ID:') . '</label>' .
form::field('blog_id', 30, 32, html::escapeHTML($blog_id), '', '', false, 'required placeholder="' . __('Blog ID') . '"') . '</p>' .
'<p class="form-note">' . __('At least 2 characters using letters, numbers or symbols.') . '</p> ' .
'<p class="form-note warn">' . __('Please note that changing your blog ID may require changes in your public index.php file.') . '</p>';
echo
'<p><label for="blog_url" class="required"><abbr title="' . __('Required field') . '">*</abbr> ' . __('Blog URL:') . '</label>' .
form::url('blog_url', [
'size' => 50,
'max' => 255,
'default' => html::escapeHTML($blog_url),
'extra_html' => 'required placeholder="' . __('Blog URL') . '"'
]) .
'</p>' .
'<p><label for="url_scan">' . __('URL scan method:') . '</label>' .
form::combo('url_scan', $url_scan_combo, $blog_settings->system->url_scan) . '</p>';
try
{
# Test URL of blog by testing it's ATOM feed
$file = $blog_url . $core->url->getURLFor('feed', 'atom');
$path = '';
$status = '404';
$content = '';
$client = netHttp::initClient($file, $path);
if ($client !== false) {
$client->setTimeout(4);
$client->setUserAgent($_SERVER['HTTP_USER_AGENT']);
$client->get($path);
$status = $client->getStatus();
$content = $client->getContent();
}
if ($status != '200') {
// Might be 404 (URL not found), 670 (blog not online), ...
echo
'<p class="form-note warn">' .
sprintf(__('The URL of blog or the URL scan method might not be well set (<code>%s</code> return a <strong>%s</strong> status).'),
html::escapeHTML($file), $status) .
'</p>';
} else {
if (substr($content, 0, 6) != '<?xml ') {
// Not well formed XML feed
echo
'<p class="form-note warn">' .
sprintf(__('The URL of blog or the URL scan method might not be well set (<code>%s</code> does not return an ATOM feed).'),
html::escapeHTML($file)) .
'</p>';
}
}
} catch (Exception $e) {
$core->error->add($e->getMessage());
}
echo '</div>';
}
echo
'<div class="fieldset"><h4>' . __('Blog configuration') . '</h4>' .
'<p><label for="post_url_format">' . __('New post URL format:') . '</label>' .
form::combo('post_url_format', $post_url_combo, html::escapeHTML($blog_settings->system->post_url_format)) .
'</p>' .
'<p class="chosen form-note">' . __('Sample:') . ' ' . $core->blog->getPostURL('', date('Y-m-d H:i:00', $now), __('Dotclear'), 42) . '</p>' .
'</p>' .
'<p><label for="note_title_tag">' . __('HTML tag for the title of the notes on the blog:') . '</label>' .
form::combo('note_title_tag', $note_title_tag_combo, $blog_settings->system->note_title_tag) .
'</p>' .
'<p><label for="enable_xmlrpc" class="classic">' .
form::checkbox('enable_xmlrpc', '1', $blog_settings->system->enable_xmlrpc) .
__('Enable XML/RPC interface') . '</label>' . '</p>' .
'<p class="form-note info">' . __('XML/RPC interface allows you to edit your blog with an external client.') . '</p>';
if ($blog_settings->system->enable_xmlrpc) {
echo
'<p>' . __('XML/RPC interface is active. You should set the following parameters on your XML/RPC client:') . '</p>' .
'<ul>' .
'<li>' . __('Server URL:') . ' <strong><code>' .
sprintf(DC_XMLRPC_URL, $core->blog->url, $core->blog->id) .
'</code></strong></li>' .
'<li>' . __('Blogging system:') . ' <strong><code>Movable Type</code></strong></li>' .
'<li>' . __('User name:') . ' <strong><code>' . $core->auth->userID() . '</code></strong></li>' .
'<li>' . __('Password:') . ' <strong><code>&lt;' . __('your password') . '&gt;</code></strong></li>' .
'<li>' . __('Blog ID:') . ' <strong><code>1</code></strong></li>' .
'</ul>';
}
echo
'</div>';
// Search engines policies
echo '<div class="fieldset"><h4>' . __('Search engines robots policy') . '</h4>';
$i = 0;
foreach ($robots_policy_options as $k => $v) {
echo '<p><label for="robots_policy-' . $i . '" class="classic">' .
form::radio(['robots_policy', 'robots_policy-' . $i], $k, $blog_settings->system->robots_policy == $k) . ' ' . $v . '</label></p>';
$i++;
}
echo '</div>';
echo '<div class="fieldset"><h4>' . __('jQuery javascript library') . '</h4>' .
'<p><label for="jquery_needed" class="classic">' .
form::checkbox('jquery_needed', '1', $blog_settings->system->jquery_needed) .
__('Load the jQuery library') . '</label></p>' .
'<p><label for="jquery_version" class="classic">' . __('jQuery version to be loaded for this blog:') . '</label>' . ' ' .
form::combo('jquery_version', $jquery_versions_combo, $blog_settings->system->jquery_version) .
'</p>' .
'<br class="clear" />' . //Opera sucks
'</div>';
echo '<div class="fieldset"><h4>' . __('Blog security') . '</h4>' .
'<p><label for="prevents_clickjacking" class="classic">' .
form::checkbox('prevents_clickjacking', '1', $blog_settings->system->prevents_clickjacking) .
__('Protect the blog from Clickjacking (see <a href="https://en.wikipedia.org/wiki/Clickjacking">Wikipedia</a>)') . '</label></p>' .
'<br class="clear" />' . //Opera sucks
'</div>';
echo '</div>'; // End advanced
echo '<div id="plugins-pref"><h3>' . __('Plugins parameters') . '</h3>';
# --BEHAVIOR-- adminBlogPreferencesForm
$core->callBehavior('adminBlogPreferencesForm', $core, $blog_settings);
echo '</div>'; // End 3rd party, aka plugins
echo
'<p><input type="submit" accesskey="s" value="' . __('Save') . '" />' .
(!$standalone ? form::hidden('id', $blog_id) : '') .
'</p>' .
'</form>';
if ($core->auth->isSuperAdmin() && $blog_id != $core->blog->id) {
echo
'<form action="' . $core->adminurl->get("admin.blog.del") . '" method="post">' .
'<p><input type="submit" class="delete" value="' . __('Delete this blog') . '" />' .
form::hidden(['blog_id'], $blog_id) .
$core->formNonce() . '</p>' .
'</form>';
} else {
if ($blog_id == $core->blog->id) {
echo '<p class="message">' . __('The current blog cannot be deleted.') . '</p>';
} else {
echo '<p class="message">' . __('Only superadmin can delete a blog.') . '</p>';
}
}
echo '</div>';
#
# Users on the blog (with permissions)
$blog_users = $core->getBlogPermissions($blog_id, $core->auth->isSuperAdmin());
$perm_types = $core->auth->getPermissionsTypes();
echo
'<div class="multi-part" id="users" title="' . __('Users') . '">' .
'<h3 class="out-of-screen-if-js">' . __('Users on this blog') . '</h3>';
if (empty($blog_users)) {
echo '<p>' . __('No users') . '</p>';
} else {
if ($core->auth->isSuperAdmin()) {
$user_url_p = '<a href="' . $core->adminurl->get("admin.user", ['id' => '%1$s'], '&amp;', true) . '">%1$s</a>';
} else {
$user_url_p = '%1$s';
}
# Sort users list on user_id key
dcUtils::lexicalKeySort($blog_users);
$post_type = $core->getPostTypes();
$current_blog_id = $core->blog->id;
if ($blog_id != $core->blog->id) {
$core->setBlog($blog_id);
}
echo '<div>';
foreach ($blog_users as $k => $v) {
if (count($v['p']) > 0) {
echo
'<div class="user-perm' . ($v['super'] ? ' user_super' : '') . '">' .
'<h4>' . sprintf($user_url_p, html::escapeHTML($k)) .
' (' . html::escapeHTML(dcUtils::getUserCN(
$k, $v['name'], $v['firstname'], $v['displayname']
)) . ')</h4>';
if ($core->auth->isSuperAdmin()) {
echo
'<p>' . __('Email:') . ' ' .
($v['email'] != '' ? '<a href="mailto:' . $v['email'] . '">' . $v['email'] . '</a>' : __('(none)')) .
'</p>';
}
echo
'<h5>' . __('Publications on this blog:') . '</h5>' .
'<ul>';
foreach ($post_type as $type => $pt_info) {
$params = [
'post_type' => $type,
'user_id' => $k
];
echo '<li>' . sprintf(__('%1$s: %2$s'), __($pt_info['label']), $core->blog->getPosts($params, true)->f(0)) . '</li>';
}
echo
'</ul>';
echo
'<h5>' . __('Permissions:') . '</h5>' .
'<ul>';
if ($v['super']) {
echo '<li class="user_super">' . __('Super administrator') . '<br />' .
'<span class="form-note">' . __('All rights on all blogs.') . '</span></li>';
} else {
foreach ($v['p'] as $p => $V) {
if (isset($perm_types[$p])) {
echo '<li ' . ($p == 'admin' ? 'class="user_admin"' : '') . '>' . __($perm_types[$p]);
} else {
echo '<li>' . sprintf(__('[%s] (unreferenced permission)'), $p);
}
if ($p == 'admin') {
echo '<br /><span class="form-note">' . __('All rights on this blog.') . '</span>';
}
echo '</li>';
}
}
echo
'</ul>';
if (!$v['super'] && $core->auth->isSuperAdmin()) {
echo
'<form action="' . $core->adminurl->get('admin.user.actions') . '" method="post">' .
'<p class="change-user-perm"><input type="submit" class="reset" value="' . __('Change permissions') . '" />' .
form::hidden(['redir'], $core->adminurl->get("admin.blog.pref", ['id' => $k], '&')) .
form::hidden(['action'], 'perms') .
form::hidden(['users[]'], $k) .
form::hidden(['blogs[]'], $blog_id) .
$core->formNonce() .
'</p>' .
'</form>';
}
echo '</div>';
}
}
echo '</div>';
if ($current_blog_id != $core->blog->id) {
$core->setBlog($current_blog_id);
}
}
echo '</div>';
}
dcPage::helpBlock('core_blog_pref');
dcPage::close();

View File

@ -1,250 +0,0 @@
<?php
/**
* @package Dotclear
* @subpackage Backend
*
* @copyright Olivier Meunier & Association Dotclear
* @copyright GPL-2.0-only
*/
require dirname(__FILE__) . '/../inc/admin/prepend.php';
dcPage::check('admin');
# -- Loading themes --
$core->themes = new dcThemes($core);
$core->themes->loadModules($core->blog->themes_path, null);
# -- Page helper --
$list = new adminThemesList(
$core->themes,
$core->blog->themes_path,
$core->blog->settings->system->store_theme_url,
!empty($_GET['nocache'])
);
adminThemesList::$distributed_modules = explode(',', DC_DISTRIB_THEMES);
# -- Theme screenshot --
if (!empty($_GET['shot']) && $list->modules->moduleExists($_GET['shot'])) {
$f = path::real(empty($_GET['src']) ?
$core->blog->themes_path . '/' . $_GET['shot'] . '/screenshot.jpg' :
$core->blog->themes_path . '/' . $_GET['shot'] . '/' . path::clean($_GET['src'])
);
if (!file_exists($f)) {
$f = dirname(__FILE__) . '/images/noscreenshot.png';
}
http::cache(array_merge([$f], get_included_files()));
header('Content-Type: ' . files::getMimeType($f));
header('Content-Length: ' . filesize($f));
readfile($f);
exit;
}
# -- Display module configuration page --
if ($list->setConfiguration($core->blog->settings->system->theme)) {
# Get content before page headers
include $list->includeConfiguration();
# Gather content
$list->getConfiguration();
# Display page
dcPage::open(__('Blog appearance'),
dcPage::jsPageTabs() .
# --BEHAVIOR-- themesToolsHeaders
$core->callBehavior('themesToolsHeaders', $core, true),
dcPage::breadcrumb(
[
html::escapeHTML($core->blog->name) => '',
__('Blog appearance') => $list->getURL('', false),
'<span class="page-title">' . __('Theme configuration') . '</span>' => ''
])
);
# Display previously gathered content
$list->displayConfiguration();
dcPage::helpBlock('core_blog_theme_conf');
dcPage::close();
# Stop reading code here
return;
}
# -- Execute actions --
try {
$list->doActions();
} catch (Exception $e) {
$core->error->add($e->getMessage());
}
# -- Page header --
dcPage::open(__('Themes management'),
dcPage::jsLoad('js/_blog_theme.js') .
dcPage::jsPageTabs() .
# --BEHAVIOR-- themesToolsHeaders
$core->callBehavior('themesToolsHeaders', $core, false),
dcPage::breadcrumb(
[
html::escapeHTML($core->blog->name) => '',
'<span class="page-title">' . __('Blog appearance') . '</span>' => ''
])
);
# -- Display modules lists --
if ($core->auth->isSuperAdmin()) {
if (!$core->error->flag()) {
if (!empty($_GET['nocache'])) {
dcPage::success(__('Manual checking of themes update done successfully.'));
}
}
# Updated modules from repo
$modules = $list->store->get(true);
if (!empty($modules)) {
echo
'<div class="multi-part" id="update" title="' . html::escapeHTML(__('Update themes')) . '">' .
'<h3>' . html::escapeHTML(__('Update themes')) . '</h3>' .
'<p>' . sprintf(
__('There is one theme to update available from repository.', 'There are %s themes to update available from repository.', count($modules)),
count($modules)
) . '</p>';
$list
->setList('theme-update')
->setTab('themes')
->setModules($modules)
->displayModules(
/*cols */['checkbox', 'name', 'sshot', 'desc', 'author', 'version', 'current_version', 'parent'],
/* actions */['update', 'delete']
);
echo
'<p class="info vertical-separator">' . sprintf(
__("Visit %s repository, the resources center for Dotclear."),
'<a href="https://themes.dotaddict.org/galerie-dc2/">Dotaddict</a>'
) .
'</p>' .
'</div>';
} else {
echo
'<form action="' . $list->getURL('', false) . '" method="get">' .
'<p><input type="hidden" name="nocache" value="1" />' .
'<input type="submit" value="' . __('Force checking update of themes') . '" /></p>' .
'</form>';
}
}
# Activated modules
$modules = $list->modules->getModules();
if (!empty($modules)) {
echo
'<div class="multi-part" id="themes" title="' . __('Installed themes') . '">' .
'<h3>' . __('Installed themes') . '</h3>' .
'<p class="more-info">' . __('You can configure and manage installed themes from this list.') . '</p>';
$list
->setList('theme-activate')
->setTab('themes')
->setModules($modules)
->displayModules(
/* cols */['sshot', 'distrib', 'name', 'config', 'desc', 'author', 'version', 'parent'],
/* actions */['select', 'behavior', 'deactivate', 'delete']
);
echo
'</div>';
}
# Deactivated modules
$modules = $list->modules->getDisabledModules();
if (!empty($modules)) {
echo
'<div class="multi-part" id="deactivate" title="' . __('Deactivated themes') . '">' .
'<h3>' . __('Deactivated themes') . '</h3>' .
'<p class="more-info">' . __('Deactivated themes are installed but not usable. You can activate them from here.') . '</p>';
$list
->setList('theme-deactivate')
->setTab('themes')
->setModules($modules)
->displayModules(
/* cols */['name', 'distrib'],
/* actions */['activate', 'delete']
);
echo
'</div>';
}
if ($core->auth->isSuperAdmin() && $list->isWritablePath()) {
# New modules from repo
$search = $list->getSearch();
$modules = $search ? $list->store->search($search) : $list->store->get();
if (!empty($search) || !empty($modules)) {
echo
'<div class="multi-part" id="new" title="' . __('Add themes') . '">' .
'<h3>' . __('Add themes from repository') . '</h3>';
// '<p>'.__('Search and install themes directly from repository.').'</p>';
$list
->setList('theme-new')
->setTab('new')
->setModules($modules)
->displaySearch()
->displayIndex()
->displayModules(
/* cols */['expander', 'sshot', 'name', 'score', 'config', 'desc', 'author', 'version', 'parent', 'details', 'support'],
/* actions */['install'],
/* nav limit */true
);
echo
'<p class="info vertical-separator">' . sprintf(
__("Visit %s repository, the resources center for Dotclear."),
'<a href="https://themes.dotaddict.org/galerie-dc2/">Dotaddict</a>'
) .
'</p>' .
'</div>';
}
# Add a new plugin
echo
'<div class="multi-part" id="addtheme" title="' . __('Install or upgrade manually') . '">' .
'<h3>' . __('Add themes from a package') . '</h3>' .
'<p class="more-info">' . __('You can install themes by uploading or downloading zip files.') . '</p>';
$list->displayManualForm();
echo
'</div>';
}
# --BEHAVIOR-- themesToolsTabs
$core->callBehavior('themesToolsTabs', $core);
# -- Notice for super admin --
if ($core->auth->isSuperAdmin() && !$list->isWritablePath()) {
echo
'<p class="warning">' . __('Some functions are disabled, please give write access to your themes directory to enable them.') . '</p>';
}
dcPage::helpBlock('core_blog_theme');
dcPage::close();

View File

@ -1,185 +0,0 @@
<?php
/**
* @package Dotclear
* @subpackage Backend
*
* @copyright Olivier Meunier & Association Dotclear
* @copyright GPL-2.0-only
*/
require dirname(__FILE__) . '/../inc/admin/prepend.php';
dcPage::check('usage,contentadmin');
# Filters
$status_combo = array_merge(
['-' => ''],
dcAdminCombos::getBlogStatusesCombo()
);
$sortby_combo = [
__('Last update') => 'blog_upddt',
__('Blog name') => 'UPPER(blog_name)',
__('Blog ID') => 'B.blog_id',
__('Status') => 'blog_status'
];
$order_combo = [
__('Descending') => 'desc',
__('Ascending') => 'asc'
];
# Actions
if ($core->auth->isSuperAdmin()) {
$blogs_actions_page = new dcBlogsActionsPage($core, $core->adminurl->get("admin.blogs"));
if ($blogs_actions_page->process()) {
return;
}
}
# Requests
$q = !empty($_GET['q']) ? $_GET['q'] : '';
$status = isset($_GET['status']) ? $_GET['status'] : '';
$sortby = !empty($_GET['sortby']) ? $_GET['sortby'] : 'blog_upddt';
$order = !empty($_GET['order']) ? $_GET['order'] : 'desc';
$show_filters = false;
$page = !empty($_GET['page']) ? max(1, (integer) $_GET['page']) : 1;
$nb_per_page = 30;
if (!empty($_GET['nb']) && (integer) $_GET['nb'] > 0) {
if ($nb_per_page != (integer) $_GET['nb']) {
$show_filters = true;
}
$nb_per_page = (integer) $_GET['nb'];
}
# - Search filter
if ($q) {
$params['q'] = $q;
$show_filters = true;
}
# - Status filter
if ($status !== '' && in_array($status, $status_combo, true)) {
$params['blog_status'] = $status;
$show_filters = true;
} else {
$status = '';
}
# - Sortby and order filter
if ($sortby !== '' && in_array($sortby, $sortby_combo, true)) {
if ($order !== '' && in_array($order, $order_combo, true)) {
$params['order'] = $sortby . ' ' . $order;
} else {
$order = 'desc';
}
} else {
$sortby = 'blog_upddt';
$order = 'desc';
}
if ($sortby != 'blog_upddt' || $order != 'desc') {
$show_filters = true;
}
$params['limit'] = [(($page - 1) * $nb_per_page), $nb_per_page];
try {
$counter = $core->getBlogs($params, 1);
$rs = $core->getBlogs($params);
$nb_blog = $counter->f(0);
$rsStatic = $rs->toStatic();
if (($sortby != 'blog_upddt') && ($sortby != 'blog_status')) {
// Sort blog list using lexical order if necessary
$rsStatic->extend('rsExtUser');
$rsStatic = $rsStatic->toExtStatic();
$rsStatic->lexicalSort(($sortby == 'UPPER(blog_name)' ? 'blog_name' : 'blog_id'), $order);
}
$blog_list = new adminBlogList($core, $rs, $counter->f(0));
} catch (Exception $e) {
$core->error->add($e->getMessage());
}
/* DISPLAY
-------------------------------------------------------- */
dcPage::open(__('List of blogs'),
dcPage::jsLoad('js/_blogs.js') . dcPage::jsFilterControl($show_filters),
dcPage::breadcrumb(
[
__('System') => '',
__('List of blogs') => ''
])
);
if (!$core->error->flag()) {
if ($core->auth->isSuperAdmin()) {
echo '<p class="top-add"><a class="button add" href="' . $core->adminurl->get("admin.blog") . '">' . __('Create a new blog') . '</a></p>';
}
echo
'<form action="' . $core->adminurl->get("admin.blogs") . '" method="get" id="filters-form">' .
'<h3 class="out-of-screen-if-js">' . __('Show filters and display options') . '</h3>' .
'<div class="table">' .
'<div class="cell">' .
'<h4>' . __('Filters') . '</h4>' .
'<p><label for="q" class="ib">' . __('Search:') . '</label> ' .
form::field('q', 20, 255, html::escapeHTML($q)) . '</p>' .
($core->auth->isSuperAdmin() ?
'<p><label for="status" class="ib">' . __('Status:') . '</label> ' .
form::combo('status', $status_combo, $status) . '</p>' : '') .
'</div>' .
'<div class="cell filters-options">' .
'<h4>' . __('Display options') . '</h4>' .
'<p><label for="sortby" class="ib">' . __('Order by:') . '</label> ' .
form::combo('sortby', $sortby_combo, html::escapeHTML($sortby)) . '</p>' .
'<p><label for="order" class="ib">' . __('Sort:') . '</label> ' .
form::combo('order', $order_combo, html::escapeHTML($order)) . '</p>' .
'<p><span class="label ib">' . __('Show') . '</span> <label for="nb" class="classic">' .
form::number('nb', 0, 999, $nb_per_page) . ' ' . __('blogs per page') . '</label></p>' .
'</div>' .
'</div>' .
'<p><input type="submit" value="' . __('Apply filters and display options') . '" />' .
'<br class="clear" /></p>' . //Opera sucks
'</form>';
# Show blogs
$blog_list->display($page, $nb_per_page,
($core->auth->isSuperAdmin() ?
'<form action="' . $core->adminurl->get("admin.blogs") . '" method="post" id="form-blogs">' : '') .
'%s' .
($core->auth->isSuperAdmin() ?
'<div class="two-cols clearfix">' .
'<p class="col checkboxes-helpers"></p>' .
'<p class="col right"><label for="action" class="classic">' . __('Selected blogs action:') . '</label> ' .
form::combo('action', $blogs_actions_page->getCombo(),
['class' => 'online', 'extra_html' => 'title="' . __('Actions') . '"']) .
$core->formNonce() .
'<input id="do-action" type="submit" value="' . __('ok') . '" /></p>' .
'</div>' .
'<p><label for="pwd" class="classic">' . __('Please give your password to confirm blog(s) deletion:') . '</label> ' .
form::password('pwd', 20, 255, ['autocomplete' => 'current-password']) . '</p>' .
form::hidden(['sortby'], $sortby) .
form::hidden(['order'], $order) .
form::hidden(['status'], $status) .
form::hidden(['page'], $page) .
form::hidden(['nb'], $nb_per_page) .
'</form>' : ''),
$show_filters
);
}
dcPage::helpBlock('core_blogs');
dcPage::close();

View File

@ -1,219 +0,0 @@
<?php
/**
* @package Dotclear
* @subpackage Backend
*
* @copyright Olivier Meunier & Association Dotclear
* @copyright GPL-2.0-only
*/
require dirname(__FILE__) . '/../inc/admin/prepend.php';
dcPage::check('categories');
# Remove a categories
if (!empty($_POST['delete'])) {
$keys = array_keys($_POST['delete']);
$cat_id = (int) $keys[0];
# Check if category to delete exists
$c = $core->blog->getCategory((integer) $cat_id);
if ($c->isEmpty()) {
dcPage::addErrorNotice(__('This category does not exist.'));
$core->adminurl->redirect("admin.categories");
}
$name = $c->cat_title;
unset($c);
try {
# Delete category
$core->blog->delCategory($cat_id);
dcPage::addSuccessNotice(sprintf(__('The category "%s" has been successfully deleted.'), html::escapeHTML($name)));
$core->adminurl->redirect("admin.categories");
} catch (Exception $e) {
$core->error->add($e->getMessage());
}
}
# move post into a category
if (!empty($_POST['mov']) && !empty($_POST['mov_cat'])) {
try {
# Check if category where to move posts exists
$keys = array_keys($_POST['mov']);
$cat_id = (int) $keys[0];
$mov_cat = (int) $_POST['mov_cat'][$cat_id];
$mov_cat = $mov_cat ?: null;
if ($mov_cat !== null) {
$c = $core->blog->getCategory($mov_cat);
if ($c->isEmpty()) {
throw new Exception(__('Category where to move entries does not exist'));
}
$name = $c->cat_title;
unset($c);
}
# Move posts
if ($mov_cat != $cat_id) {
$core->blog->changePostsCategory($cat_id, $mov_cat);
}
dcPage::addSuccessNotice(sprintf(__('The entries have been successfully moved to category "%s"'),
html::escapeHTML($name)));
$core->adminurl->redirect("admin.categories");
} catch (Exception $e) {
$core->error->add($e->getMessage());
}
}
# Update order
if (!empty($_POST['save_order']) && !empty($_POST['categories_order'])) {
$categories = json_decode($_POST['categories_order']);
foreach ($categories as $category) {
if (!empty($category->item_id) && !empty($category->left) && !empty($category->right)) {
$core->blog->updCategoryPosition($category->item_id, $category->left, $category->right);
}
}
dcPage::addSuccessNotice(__('Categories have been successfully reordered.'));
$core->adminurl->redirect("admin.categories");
}
# Reset order
if (!empty($_POST['reset'])) {
try
{
$core->blog->resetCategoriesOrder();
dcPage::addSuccessNotice(__('Categories order has been successfully reset.'));
$core->adminurl->redirect("admin.categories");
} catch (Exception $e) {
$core->error->add($e->getMessage());
}
}
/* Display
-------------------------------------------------------- */
$rs = $core->blog->getCategories();
$starting_script = "";
$core->auth->user_prefs->addWorkspace('accessibility');
if (!$core->auth->user_prefs->accessibility->nodragdrop
&& $core->auth->check('categories', $core->blog->id)
&& $rs->count() > 1) {
$starting_script .= dcPage::jsLoad('js/jquery/jquery-ui.custom.js');
$starting_script .= dcPage::jsLoad('js/jquery/jquery.ui.touch-punch.js');
$starting_script .= dcPage::jsLoad('js/jquery/jquery.mjs.nestedSortable.js');
}
$starting_script .= dcPage::jsConfirmClose('form-categories');
$starting_script .= dcPage::jsLoad('js/_categories.js');
dcPage::open(__('Categories'), $starting_script,
dcPage::breadcrumb(
[
html::escapeHTML($core->blog->name) => '',
__('Categories') => ''
])
);
if (!empty($_GET['del'])) {
dcPage::success(__('The category has been successfully removed.'));
}
if (!empty($_GET['reord'])) {
dcPage::success(__('Categories have been successfully reordered.'));
}
if (!empty($_GET['move'])) {
dcPage::success(__('Entries have been successfully moved to the category you choose.'));
}
$categories_combo = dcAdminCombos::getCategoriesCombo($rs);
echo
'<p class="top-add"><a class="button add" href="' . $core->adminurl->get("admin.category") . '">' . __('New category') . '</a></p>';
echo
'<div class="col">';
if ($rs->isEmpty()) {
echo '<p>' . __('No category so far.') . '</p>';
} else {
echo
'<form action="' . $core->adminurl->get("admin.categories") . '" method="post" id="form-categories">' .
'<div id="categories">';
$ref_level = $level = $rs->level - 1;
while ($rs->fetch()) {
$attr = 'id="cat_' . $rs->cat_id . '" class="cat-line clearfix"';
if ($rs->level > $level) {
echo str_repeat('<ul><li ' . $attr . '>', $rs->level - $level);
} elseif ($rs->level < $level) {
echo str_repeat('</li></ul>', -($rs->level - $level));
}
if ($rs->level <= $level) {
echo '</li><li ' . $attr . '>';
}
echo
'<p class="cat-title"><label class="classic" for="cat_' . $rs->cat_id . '"><a href="' .
$core->adminurl->get("admin.category", ['id' => $rs->cat_id]) . '">' . html::escapeHTML($rs->cat_title) .
'</a></label> </p>' .
'<p class="cat-nb-posts">(<a href="' . $core->adminurl->get("admin.posts", ['cat_id' => $rs->cat_id]) . '">' .
sprintf(($rs->nb_post > 1 ? __('%d entries') : __('%d entry')), $rs->nb_post) . '</a>' .
', ' . __('total:') . ' ' . $rs->nb_total . ')</p>' .
'<p class="cat-url">' . __('URL:') . ' <code>' . html::escapeHTML($rs->cat_url) . '</code></p>';
echo
'<p class="cat-buttons">';
if ($rs->nb_total > 0) {
// remove current category
echo
'<label for="mov_cat_' . $rs->cat_id . '">' . __('Move entries to') . '</label> ' .
form::combo(['mov_cat[' . $rs->cat_id . ']', 'mov_cat_' . $rs->cat_id], array_filter($categories_combo,
function ($cat) {return $cat->value != $GLOBALS['rs']->cat_id;}
), '', '') .
' <input type="submit" class="reset" name="mov[' . $rs->cat_id . ']" value="' . __('OK') . '"/>';
$attr_disabled = ' disabled="disabled"';
$input_class = 'disabled ';
} else {
$attr_disabled = '';
$input_class = '';
}
echo
' <input type="submit"' . $attr_disabled . ' class="' . $input_class . 'delete" name="delete[' . $rs->cat_id . ']" value="' . __('Delete category') . '"/>' .
'</p>';
$level = $rs->level;
}
if ($ref_level - $level < 0) {
echo str_repeat('</li></ul>', -($ref_level - $level));
}
echo
'</div>';
echo '<div class="clear">';
if ($core->auth->check('categories', $core->blog->id) && $rs->count() > 1) {
if (!$core->auth->user_prefs->accessibility->nodragdrop) {
echo '<p class="form-note hidden-if-no-js">' . __('To rearrange categories order, move items by drag and drop, then click on “Save categories order” button.') . '</p>';
}
echo
'<p><span class="hidden-if-no-js">' .
'<input type="hidden" id="categories_order" name="categories_order" value=""/>' .
'<input type="submit" name="save_order" id="save-set-order" value="' . __('Save categories order') . '" />' .
'</span> ';
} else {
echo '<p>';
}
echo
'<input type="submit" class="reset" name="reset" value="' . __('Reorder all categories on the top level') . '" />' .
$core->formNonce() . '</p>' .
'</div></form>';
}
echo '</div>';
dcPage::helpBlock('core_categories');
dcPage::close();

View File

@ -1,263 +0,0 @@
<?php
/**
* @package Dotclear
* @subpackage Backend
*
* @copyright Olivier Meunier & Association Dotclear
* @copyright GPL-2.0-only
*/
require dirname(__FILE__) . '/../inc/admin/prepend.php';
dcPage::check('categories');
$cat_id = '';
$cat_title = '';
$cat_url = '';
$cat_desc = '';
$cat_position = '';
$blog_settings = new dcSettings($core, $core->blog->id);
$blog_lang = $blog_settings->system->lang;
# Getting existing category
if (!empty($_REQUEST['id'])) {
try {
$rs = $core->blog->getCategory($_REQUEST['id']);
} catch (Exception $e) {
$core->error->add($e->getMessage());
}
if (!$core->error->flag() && !$rs->isEmpty()) {
$cat_id = (integer) $rs->cat_id;
$cat_title = $rs->cat_title;
$cat_url = $rs->cat_url;
$cat_desc = $rs->cat_desc;
}
unset($rs);
# Getting hierarchy information
$parents = $core->blog->getCategoryParents($cat_id);
$rs = $core->blog->getCategoryParent($cat_id);
$cat_parent = $rs->isEmpty() ? 0 : (integer) $rs->cat_id;
unset($rs);
# Allowed parents list
$children = $core->blog->getCategories(['start' => $cat_id]);
$allowed_parents = [__('Top level') => 0];
$p = [];
while ($children->fetch()) {
$p[$children->cat_id] = 1;
}
$rs = $core->blog->getCategories();
while ($rs->fetch()) {
if (!isset($p[$rs->cat_id])) {
$allowed_parents[] = new formSelectOption(
str_repeat('&nbsp;&nbsp;', $rs->level - 1) . ($rs->level - 1 == 0 ? '' : '&bull; ') . html::escapeHTML($rs->cat_title),
$rs->cat_id
);
}
}
unset($rs);
# Allowed siblings list
$siblings = [];
$rs = $core->blog->getCategoryFirstChildren($cat_parent);
while ($rs->fetch()) {
if ($rs->cat_id != $cat_id) {
$siblings[html::escapeHTML($rs->cat_title)] = $rs->cat_id;
}
}
unset($rs);
}
# Changing parent
if ($cat_id && isset($_POST['cat_parent'])) {
$new_parent = (integer) $_POST['cat_parent'];
if ($cat_parent != $new_parent) {
try {
$core->blog->setCategoryParent($cat_id, $new_parent);
dcPage::addSuccessNotice(__('The category has been successfully moved'));
$core->adminurl->redirect("admin.categories");
} catch (Exception $e) {
$core->error->add($e->getMessage());
}
}
}
# Changing sibling
if ($cat_id && isset($_POST['cat_sibling'])) {
try {
$core->blog->setCategoryPosition($cat_id, (integer) $_POST['cat_sibling'], $_POST['cat_move']);
dcPage::addSuccessNotice(__('The category has been successfully moved'));
$core->adminurl->redirect("admin.categories");
} catch (Exception $e) {
$core->error->add($e->getMessage());
}
}
# Create or update a category
if (isset($_POST['cat_title'])) {
$cur = $core->con->openCursor($core->prefix . 'category');
$cur->cat_title = $cat_title = $_POST['cat_title'];
if (isset($_POST['cat_desc'])) {
$cur->cat_desc = $cat_desc = $_POST['cat_desc'];
}
if (isset($_POST['cat_url'])) {
$cur->cat_url = $cat_url = $_POST['cat_url'];
} else {
$cur->cat_url = $cat_url;
}
try
{
# Update category
if ($cat_id) {
# --BEHAVIOR-- adminBeforeCategoryUpdate
$core->callBehavior('adminBeforeCategoryUpdate', $cur, $cat_id);
$core->blog->updCategory($_POST['id'], $cur);
# --BEHAVIOR-- adminAfterCategoryUpdate
$core->callBehavior('adminAfterCategoryUpdate', $cur, $cat_id);
dcPage::addSuccessNotice(__('The category has been successfully updated.'));
$core->adminurl->redirect("admin.category", ['id' => $_POST['id']]);
}
# Create category
else {
# --BEHAVIOR-- adminBeforeCategoryCreate
$core->callBehavior('adminBeforeCategoryCreate', $cur);
$id = $core->blog->addCategory($cur, (integer) $_POST['new_cat_parent']);
# --BEHAVIOR-- adminAfterCategoryCreate
$core->callBehavior('adminAfterCategoryCreate', $cur, $id);
dcPage::addSuccessNotice(sprintf(__('The category "%s" has been successfully created.'),
html::escapeHTML($cur->cat_title)));
$core->adminurl->redirect("admin.categories");
}
} catch (Exception $e) {
$core->error->add($e->getMessage());
}
}
$title = $cat_id ? html::escapeHTML($cat_title) : __('New category');
$elements = [
html::escapeHTML($core->blog->name) => '',
__('Categories') => $core->adminurl->get("admin.categories")
];
if ($cat_id) {
while ($parents->fetch()) {
$elements[html::escapeHTML($parents->cat_title)] = $core->adminurl->get("admin.category", ['id' => $parents->cat_id]);
}
}
$elements[$title] = '';
$category_editor = $core->auth->getOption('editor');
$rte_flag = true;
$rte_flags = @$core->auth->user_prefs->interface->rte_flags;
if (is_array($rte_flags) && in_array('cat_descr', $rte_flags)) {
$rte_flag = $rte_flags['cat_descr'];
}
dcPage::open($title,
dcPage::jsConfirmClose('category-form') .
dcPage::jsLoad('js/_category.js') .
($rte_flag ? $core->callBehavior('adminPostEditor', $category_editor['xhtml'], 'category', ['#cat_desc'], 'xhtml') : ''),
dcPage::breadcrumb($elements)
);
if (!empty($_GET['upd'])) {
dcPage::success(__('Category has been successfully updated.'));
}
echo
'<form action="' . $core->adminurl->get("admin.category") . '" method="post" id="category-form">' .
'<h3>' . __('Category information') . '</h3>' .
'<p><label class="required" for="cat_title"><abbr title="' . __('Required field') . '">*</abbr> ' . __('Name:') . '</label> ' .
form::field('cat_title', 40, 255, [
'default' => html::escapeHTML($cat_title),
'extra_html' => 'required placeholder="' . __('Name') . '" lang="' . $blog_lang . '" spellcheck="true"'
]) .
'</p>';
if (!$cat_id) {
$rs = $core->blog->getCategories();
echo
'<p><label for="new_cat_parent">' . __('Parent:') . ' ' .
'<select id="new_cat_parent" name="new_cat_parent" >' .
'<option value="0">' . __('(none)') . '</option>';
while ($rs->fetch()) {
echo '<option value="' . $rs->cat_id . '" ' . (!empty($_POST['new_cat_parent']) && $_POST['new_cat_parent'] == $rs->cat_id ? 'selected="selected"' : '') . '>' .
str_repeat('&nbsp;&nbsp;', $rs->level - 1) . ($rs->level - 1 == 0 ? '' : '&bull; ') . html::escapeHTML($rs->cat_title) . '</option>';
}
echo
'</select></label></p>';
unset($rs);
}
echo
'<div class="lockable">' .
'<p><label for="cat_url">' . __('URL:') . '</label> '
. form::field('cat_url', 40, 255, html::escapeHTML($cat_url)) .
'</p>' .
'<p class="form-note warn" id="note-cat-url">' .
__('Warning: If you set the URL manually, it may conflict with another category.') . '</p>' .
'</div>' .
'<p class="area"><label for="cat_desc">' . __('Description:') . '</label> ' .
form::textarea('cat_desc', 50, 8,
[
'default' => html::escapeHTML($cat_desc),
'extra_html' => 'lang="' . $blog_lang . '" spellcheck="true"'
]) .
'</p>' .
'<p><input type="submit" accesskey="s" value="' . __('Save') . '" />' .
($cat_id ? form::hidden('id', $cat_id) : '') .
$core->formNonce() .
'</p>' .
'</form>';
if ($cat_id) {
echo
'<h3 class="border-top">' . __('Move this category') . '</h3>' .
'<div class="two-cols">' .
'<div class="col">' .
'<form action="' . $core->adminurl->get("admin.category") . '" method="post" class="fieldset">' .
'<h4>' . __('Category parent') . '</h4>' .
'<p><label for="cat_parent" class="classic">' . __('Parent:') . '</label> ' .
form::combo('cat_parent', $allowed_parents, $cat_parent) . '</p>' .
'<p><input type="submit" accesskey="s" value="' . __('Save') . '" />' .
form::hidden(['id'], $cat_id) . $core->formNonce() . '</p>' .
'</form>' .
'</div>';
if (count($siblings) > 0) {
echo
'<div class="col">' .
'<form action="' . $core->adminurl->get("admin.category") . '" method="post" class="fieldset">' .
'<h4>' . __('Category sibling') . '</h4>' .
'<p><label class="classic" for="cat_sibling">' . __('Move current category') . '</label> ' .
form::combo('cat_move', [__('before') => 'before', __('after') => 'after'],
['extra_html' => 'title="' . __('position: ') . '"']) . ' ' .
form::combo('cat_sibling', $siblings) . '</p>' .
'<p><input type="submit" accesskey="s" value="' . __('Save') . '" />' .
form::hidden(['id'], $cat_id) . $core->formNonce() . '</p>' .
'</form>' .
'</div>';
}
echo '</div>';
}
dcPage::helpBlock('core_category');
dcPage::close();

View File

@ -1,252 +0,0 @@
<?php
/**
* @package Dotclear
* @subpackage Backend
*
* @copyright Olivier Meunier & Association Dotclear
* @copyright GPL-2.0-only
*/
require dirname(__FILE__) . '/../inc/admin/prepend.php';
dcPage::check('usage,contentadmin');
$comment_id = null;
$comment_dt = '';
$comment_author = '';
$comment_email = '';
$comment_site = '';
$comment_content = '';
$comment_ip = '';
$comment_status = '';
$comment_trackback = 0;
$comment_spam_status = '';
$comment_editor = $core->auth->getOption('editor');
# Status combo
$status_combo = dcAdminCombos::getCommentStatusescombo();
# Adding comment (comming from post form, comments tab)
if (!empty($_POST['add']) && !empty($_POST['post_id'])) {
try
{
$rs = $core->blog->getPosts(['post_id' => $_POST['post_id'], 'post_type' => '']);
if ($rs->isEmpty()) {
throw new Exception(__('Entry does not exist.'));
}
$cur = $core->con->openCursor($core->prefix . 'comment');
$cur->comment_author = $_POST['comment_author'];
$cur->comment_email = html::clean($_POST['comment_email']);
$cur->comment_site = html::clean($_POST['comment_site']);
$cur->comment_content = $core->HTMLfilter($_POST['comment_content']);
$cur->post_id = (integer) $_POST['post_id'];
# --BEHAVIOR-- adminBeforeCommentCreate
$core->callBehavior('adminBeforeCommentCreate', $cur);
$comment_id = $core->blog->addComment($cur);
# --BEHAVIOR-- adminAfterCommentCreate
$core->callBehavior('adminAfterCommentCreate', $cur, $comment_id);
dcPage::addSuccessNotice(__('Comment has been successfully created.'));
} catch (Exception $e) {
$core->error->add($e->getMessage());
}
http::redirect($core->getPostAdminURL($rs->post_type, $rs->post_id, false) . '&co=1');
}
if (!empty($_REQUEST['id'])) {
$params['comment_id'] = $_REQUEST['id'];
try {
$rs = $core->blog->getComments($params);
if (!$rs->isEmpty()) {
$comment_id = $rs->comment_id;
$post_id = $rs->post_id;
$post_type = $rs->post_type;
$post_title = $rs->post_title;
$comment_dt = $rs->comment_dt;
$comment_author = $rs->comment_author;
$comment_email = $rs->comment_email;
$comment_site = $rs->comment_site;
$comment_content = $rs->comment_content;
$comment_ip = $rs->comment_ip;
$comment_status = $rs->comment_status;
$comment_trackback = (boolean) $rs->comment_trackback;
$comment_spam_status = $rs->comment_spam_status;
}
} catch (Exception $e) {
$core->error->add($e->getMessage());
}
}
if (!$comment_id && !$core->error->flag()) {
$core->error->add(__('No comments'));
}
if (!$core->error->flag() && isset($rs)) {
$can_edit = $can_delete = $can_publish = $core->auth->check('contentadmin', $core->blog->id);
if (!$core->auth->check('contentadmin', $core->blog->id) && $core->auth->userID() == $rs->user_id) {
$can_edit = true;
if ($core->auth->check('delete', $core->blog->id)) {
$can_delete = true;
}
if ($core->auth->check('publish', $core->blog->id)) {
$can_publish = true;
}
}
# update comment
if (!empty($_POST['update']) && $can_edit) {
$cur = $core->con->openCursor($core->prefix . 'comment');
$cur->comment_author = $_POST['comment_author'];
$cur->comment_email = html::clean($_POST['comment_email']);
$cur->comment_site = html::clean($_POST['comment_site']);
$cur->comment_content = $core->HTMLfilter($_POST['comment_content']);
if (isset($_POST['comment_status'])) {
$cur->comment_status = (integer) $_POST['comment_status'];
}
try
{
# --BEHAVIOR-- adminBeforeCommentUpdate
$core->callBehavior('adminBeforeCommentUpdate', $cur, $comment_id);
$core->blog->updComment($comment_id, $cur);
# --BEHAVIOR-- adminAfterCommentUpdate
$core->callBehavior('adminAfterCommentUpdate', $cur, $comment_id);
dcPage::addSuccessNotice(__('Comment has been successfully updated.'));
$core->adminurl->redirect("admin.comment", ['id' => $comment_id]);
} catch (Exception $e) {
$core->error->add($e->getMessage());
}
}
if (!empty($_POST['delete']) && $can_delete) {
try {
# --BEHAVIOR-- adminBeforeCommentDelete
$core->callBehavior('adminBeforeCommentDelete', $comment_id);
$core->blog->delComment($comment_id);
dcPage::addSuccessNotice(__('Comment has been successfully deleted.'));
http::redirect($core->getPostAdminURL($rs->post_type, $rs->post_id) . '&co=1', false);
} catch (Exception $e) {
$core->error->add($e->getMessage());
}
}
if (!$can_edit) {
$core->error->add(__("You can't edit this comment."));
}
}
/* DISPLAY
-------------------------------------------------------- */
if ($comment_id) {
$breadcrumb = dcPage::breadcrumb(
[
html::escapeHTML($core->blog->name) => '',
html::escapeHTML($post_title) => $core->getPostAdminURL($post_type, $post_id) . '&amp;co=1#c' . $comment_id,
__('Edit comment') => ''
]);
} else {
$breadcrumb = dcPage::breadcrumb(
[
html::escapeHTML($core->blog->name) => '',
html::escapeHTML($post_title) => $core->getPostAdminURL($post_type, $post_id),
__('Edit comment') => ''
]);
}
dcPage::open(__('Edit comment'),
dcPage::jsConfirmClose('comment-form') .
dcPage::jsLoad('js/_comment.js') .
$core->callBehavior('adminPostEditor', $comment_editor['xhtml'], 'comment', ['#comment_content'], 'xhtml') .
# --BEHAVIOR-- adminCommentHeaders
$core->callBehavior('adminCommentHeaders'),
$breadcrumb
);
if ($comment_id) {
if (!empty($_GET['upd'])) {
dcPage::success(__('Comment has been successfully updated.'));
}
$comment_mailto = '';
if ($comment_email) {
$comment_mailto = '<a href="mailto:' . html::escapeHTML($comment_email)
. '?subject=' . rawurlencode(sprintf(__('Your comment on my blog %s'), $core->blog->name))
. '&amp;body='
. rawurlencode(sprintf(__("Hi!\n\nYou wrote a comment on:\n%s\n\n\n"), $rs->getPostURL()))
. '">' . __('Send an e-mail') . '</a>';
}
echo
'<form action="' . $core->adminurl->get("admin.comment") . '" method="post" id="comment-form">' .
'<div class="fieldset">' .
'<h3>' . __('Information collected') . '</h3>' .
'<p>' . __('IP address:') . ' ' .
'<a href="' . $core->adminurl->get("admin.comments", ['ip' => $comment_ip]) . '">' . $comment_ip . '</a></p>' .
'<p>' . __('Date:') . ' ' .
dt::dt2str(__('%Y-%m-%d %H:%M'), $comment_dt) . '</p>' .
'</div>' .
'<h3>' . __('Comment submitted') . '</h3>' .
'<p><label for="comment_author" class="required"><abbr title="' . __('Required field') . '">*</abbr>' . __('Author:') . '</label>' .
form::field('comment_author', 30, 255, [
'default' => html::escapeHTML($comment_author),
'extra_html' => 'required placeholder="' . __('Author') . '"'
]) .
'</p>' .
'<p><label for="comment_email">' . __('Email:') . '</label>' .
form::email('comment_email', 30, 255, html::escapeHTML($comment_email)) .
'<span>' . $comment_mailto . '</span>' .
'</p>' .
'<p><label for="comment_site">' . __('Web site:') . '</label>' .
form::url('comment_site', 30, 255, html::escapeHTML($comment_site)) .
'</p>' .
'<p><label for="comment_status">' . __('Status:') . '</label>' .
form::combo('comment_status', $status_combo,
['default' => $comment_status, 'disabled' => !$can_publish]) .
'</p>' .
# --BEHAVIOR-- adminAfterCommentDesc
$core->callBehavior('adminAfterCommentDesc', $rs) .
'<p class="area"><label for="comment_content">' . __('Comment:') . '</label> ' .
form::textarea('comment_content', 50, 10,
[
'default' => html::escapeHTML($comment_content),
'extra_html' => 'lang="' . $core->auth->getInfo('user_lang') . '" spellcheck="true"'
]) .
'</p>' .
'<p>' . form::hidden('id', $comment_id) .
$core->formNonce() .
'<input type="submit" accesskey="s" name="update" value="' . __('Save') . '" /> ';
if ($can_delete) {
echo '<input type="submit" class="delete" name="delete" value="' . __('Delete') . '" />';
}
echo
'</p>' .
'</form>';
}
dcPage::helpBlock('core_comments');
dcPage::close();

View File

@ -1,302 +0,0 @@
<?php
/**
* @package Dotclear
* @subpackage Backend
*
* @copyright Olivier Meunier & Association Dotclear
* @copyright GPL-2.0-only
*/
require dirname(__FILE__) . '/../inc/admin/prepend.php';
dcPage::check('usage,contentadmin');
if (!empty($_POST['delete_all_spam'])) {
try {
$core->blog->delJunkComments();
$_SESSION['comments_del_spam'] = true;
$core->adminurl->redirect("admin.comments");
} catch (Exception $e) {
$core->error->add($e->getMessage());
}
}
# Creating filter combo boxes
# Filter form we'll put in html_block
$status_combo = array_merge(
['-' => ''],
dcAdminCombos::getCommentStatusescombo()
);
$type_combo = [
'-' => '',
__('Comment') => 'co',
__('Trackback') => 'tb'
];
$sortby_combo = [
__('Date') => 'comment_dt',
__('Entry title') => 'post_title',
__('Entry date') => 'post_dt',
__('Author') => 'comment_author',
__('Status') => 'comment_status'
];
$sortby_lex = [
// key in sorty_combo (see above) => field in SQL request
'post_title' => 'post_title',
'comment_author' => 'comment_author',
'comment_spam_filter' => 'comment_spam_filter'];
$order_combo = [
__('Descending') => 'desc',
__('Ascending') => 'asc'
];
/* Get comments
-------------------------------------------------------- */
$author = isset($_GET['author']) ? $_GET['author'] : '';
$status = isset($_GET['status']) ? $_GET['status'] : '';
$type = !empty($_GET['type']) ? $_GET['type'] : '';
$sortby = !empty($_GET['sortby']) ? $_GET['sortby'] : 'comment_dt';
$order = !empty($_GET['order']) ? $_GET['order'] : 'desc';
$ip = !empty($_GET['ip']) ? $_GET['ip'] : '';
$email = !empty($_GET['email']) ? $_GET['email'] : '';
$site = !empty($_GET['site']) ? $_GET['site'] : '';
$with_spam = $author || $status || $type || $sortby != 'comment_dt' || $order != 'desc' || $ip;
$show_filters = false;
$page = !empty($_GET['page']) ? max(1, (integer) $_GET['page']) : 1;
$nb_per_page = 30;
if (!empty($_GET['nb']) && (integer) $_GET['nb'] > 0) {
if ($nb_per_page != (integer) $_GET['nb']) {
$show_filters = true;
}
$nb_per_page = (integer) $_GET['nb'];
}
$params['limit'] = [(($page - 1) * $nb_per_page), $nb_per_page];
$params['no_content'] = true;
# Author filter
if ($author !== '') {
$params['q_author'] = $author;
$show_filters = true;
} else {
$author = '';
}
# - Type filter
if ($type == 'tb' || $type == 'co') {
$params['comment_trackback'] = ($type == 'tb');
$show_filters = true;
} else {
$type = '';
}
# - Status filter
if ($status !== '' && in_array($status, $status_combo)) {
$params['comment_status'] = $status;
$show_filters = true;
} elseif (!$with_spam) {
$params['comment_status_not'] = -2;
$status = '';
} else {
$status = '';
}
# - IP filter
if ($ip) {
$params['comment_ip'] = $ip;
$show_filters = true;
}
# - email filter
if ($email) {
$params['comment_email'] = $email;
$show_filters = true;
}
# - site filter
if ($site) {
$params['comment_site'] = $site;
$show_filters = true;
}
// Add some sort order if spams displayed
if ($with_spam || ($status == -2)) {
$sortby_combo[__('IP')] = 'comment_ip';
$sortby_combo[__('Spam filter')] = 'comment_spam_filter';
}
# Sortby and order filter
if ($sortby !== '' && in_array($sortby, $sortby_combo)) {
if (array_key_exists($sortby, $sortby_lex)) {
$params['order'] = $core->con->lexFields($sortby_lex[$sortby]);
} else {
$params['order'] = $sortby;
}
if ($order !== '' && in_array($order, $order_combo)) {
$params['order'] .= ' ' . $order;
} else {
$order = 'desc';
}
if ($sortby != 'comment_dt' || $order != 'desc') {
$show_filters = true;
}
} else {
$sortby = 'comment_dt';
$order = 'desc';
}
# Actions combo box
$combo_action = [];
$default = '';
if ($core->auth->check('delete,contentadmin', $core->blog->id) && $status == -2) {
$default = 'delete';
}
$comments_actions_page = new dcCommentsActionsPage($core, $core->adminurl->get("admin.comments"));
if ($comments_actions_page->process()) {
return;
}
/* Get comments
-------------------------------------------------------- */
try {
$comments = $core->blog->getComments($params);
$counter = $core->blog->getComments($params, true);
$comment_list = new adminCommentList($core, $comments, $counter->f(0));
} catch (Exception $e) {
$core->error->add($e->getMessage());
}
/* DISPLAY
-------------------------------------------------------- */
dcPage::open(__('Comments and trackbacks'),
dcPage::jsLoad('js/_comments.js') . dcPage::jsFilterControl($show_filters),
dcPage::breadcrumb(
[
html::escapeHTML($core->blog->name) => '',
__('Comments and trackbacks') => ''
])
);
if (!empty($_GET['upd'])) {
dcPage::success(__('Selected comments have been successfully updated.'));
} elseif (!empty($_GET['del'])) {
dcPage::success(__('Selected comments have been successfully deleted.'));
}
if (!$core->error->flag()) {
if (isset($_SESSION['comments_del_spam'])) {
dcPage::message(__('Spam comments have been successfully deleted.'));
unset($_SESSION['comments_del_spam']);
}
$spam_count = $core->blog->getComments(['comment_status' => -2], true)->f(0);
if ($spam_count > 0) {
echo
'<form action="' . $core->adminurl->get("admin.comments") . '" method="post" class="fieldset">';
if (!$with_spam || ($status != -2)) {
if ($spam_count == 1) {
echo '<p>' . sprintf(__('You have one spam comment.'), '<strong>' . $spam_count . '</strong>') . ' ' .
'<a href="' . $core->adminurl->get("admin.comments", ['status' => -2]) . '">' . __('Show it.') . '</a></p>';
} elseif ($spam_count > 1) {
echo '<p>' . sprintf(__('You have %s spam comments.'), '<strong>' . $spam_count . '</strong>') . ' ' .
'<a href="' . $core->adminurl->get("admin.comments", ['status' => -2]) . '">' . __('Show them.') . '</a></p>';
}
}
echo
'<p>' .
$core->formNonce() .
'<input name="delete_all_spam" class="delete" type="submit" value="' . __('Delete all spams') . '" /></p>';
# --BEHAVIOR-- adminCommentsSpamForm
$core->callBehavior('adminCommentsSpamForm', $core);
echo '</form>';
}
echo
'<form action="' . $core->adminurl->get("admin.comments") . '" method="get" id="filters-form">' .
'<h3 class="out-of-screen-if-js">' . __('Show filters and display options') . '</h3>' .
'<div class="table">' .
'<div class="cell">' .
'<h4>' . __('Filters') . '</h4>' .
'<p><label for="type" class="ib">' . __('Type:') . '</label> ' .
form::combo('type', $type_combo, $type) . '</p> ' .
'<p><label for="status" class="ib">' . __('Status:') . '</label> ' .
form::combo('status', $status_combo, $status) . '</p>' .
'</div>' .
'<div class="cell filters-sibling-cell">' .
'<p><label for="author" class="ib">' . __('Author:') . '</label> ' .
form::field('author', 20, 255, html::escapeHTML($author)) . '</p>' .
'<p><label for="ip" class="ib">' . __('IP address:') . '</label> ' .
form::field('ip', 20, 39, html::escapeHTML($ip)) . '</p>' .
'<p><label for="email" class="ib">' . __('Email:') . '</label> ' .
form::field('email', 20, 255, html::escapeHTML($email)) . '</p>' .
'<p><label for="site" class="ib">' . __('Web site:') . '</label> ' .
form::field('site', 20, 255, html::escapeHTML($site)) . '</p>' .
'</div>' .
'<div class="cell filters-options">' .
'<h4>' . __('Display options') . '</h4>' .
'<p><label for="sortby" class="ib">' . __('Order by:') . '</label> ' .
form::combo('sortby', $sortby_combo, $sortby) . '</p>' .
'<p><label for="order" class="ib">' . __('Sort:') . '</label> ' .
form::combo('order', $order_combo, $order) . '</p>' .
'<p><span class="label ib">' . __('Show') . '</span> <label for="nb" class="classic">' .
form::number('nb', 0, 999, $nb_per_page) . ' ' .
__('comments per page') . '</label></p>' .
'</div>' .
'</div>' .
'<p><input type="submit" value="' . __('Apply filters and display options') . '" />' .
'<br class="clear" /></p>' . //Opera sucks
'</form>';
# Show comments
$comment_list->display($page, $nb_per_page,
'<form action="' . $core->adminurl->get("admin.comments") . '" method="post" id="form-comments">' .
'%s' .
'<div class="two-cols">' .
'<p class="col checkboxes-helpers"></p>' .
'<p class="col right"><label for="action" class="classic">' . __('Selected comments action:') . '</label> ' .
form::combo('action', $comments_actions_page->getCombo(),
['default' => $default, 'extra_html' => 'title="' . __('Actions') . '"']) .
$core->formNonce() .
'<input id="do-action" type="submit" value="' . __('ok') . '" /></p>' .
form::hidden(['type'], $type) .
form::hidden(['sortby'], $sortby) .
form::hidden(['order'], $order) .
form::hidden(['author'], html::escapeHTML(preg_replace('/%/', '%%', $author))) .
form::hidden(['status'], $status) .
form::hidden(['ip'], preg_replace('/%/', '%%', $ip)) .
form::hidden(['page'], $page) .
form::hidden(['nb'], $nb_per_page) .
form::hidden(['email'], html::escapeHTML(preg_replace('/%/', '%%', $email))) .
form::hidden(['site'], html::escapeHTML(preg_replace('/%/', '%%', $site))) .
'</div>' .
'</form>',
$show_filters,
($with_spam || ($status == -2))
);
}
dcPage::helpBlock('core_comments');
dcPage::close();

View File

@ -1,30 +0,0 @@
<?php
/**
* @package Dotclear
* @subpackage Backend
*
* @copyright Olivier Meunier & Association Dotclear
* @copyright GPL-2.0-only
*
* @deprecated It is only used for plugins compatibility
*/
require dirname(__FILE__) . '/../inc/admin/prepend.php';
dcPage::check('usage,contentadmin');
if (isset($_REQUEST['redir'])) {
$u = explode('?', $_REQUEST['redir']);
$uri = $u[0];
if (isset($u[1])) {
parse_str($u[1], $args);
}
$args['redir'] = $_REQUEST['redir'];
} else {
$uri = $core->adminurl->get("admin.comments");
$args = [];
}
$comments_actions_page = new dcCommentsActionsPage($core, $uri, $args);
$comments_actions_page->setEnableRedirSelection(false);
$comments_actions_page->process();

View File

@ -1,106 +0,0 @@
<?php
/**
* @package Dotclear
* @subpackage Backend
*
* @copyright Olivier Meunier & Association Dotclear
* @copyright GPL-2.0-only
*/
// From: https://github.com/nico3333fr/CSP-useful
//
// Note: this script requires PHP ≥ 5.4.
// Inspired from https://mathiasbynens.be/notes/csp-reports
// Dareboost wants it? Not a problem.
header('X-Content-Type-Options: "nosniff"');
require dirname(__FILE__) . '/../inc/admin/prepend.php';
// Specify admin CSP log file if necessary
if (!defined('LOGFILE')) {
define('LOGFILE', path::real(DC_VAR) . '/csp/csp_report.json');
}
// Get the raw POST data
$data = file_get_contents('php://input');
// Only continue if its valid JSON that is not just `null`, `0`, `false` or an
// empty string, i.e. if it could be a CSP violation report.
if ($data = json_decode($data, true)) {
// get source-file and blocked-URI to perform some tests
$source_file = isset($data['csp-report']['source-file']) ? $data['csp-report']['source-file'] : '';
$line_number = isset($data['csp-report']['line-number']) ? $data['csp-report']['line-number'] : '';
$blocked_uri = isset($data['csp-report']['blocked-uri']) ? $data['csp-report']['blocked-uri'] : '';
$document_uri = isset($data['csp-report']['document-uri']) ? $data['csp-report']['document-uri'] : '';
$violated_directive = isset($data['csp-report']['violated-directive']) ? $data['csp-report']['violated-directive'] : '';
if (
// avoid false positives notifications coming from Chrome extensions (Wappalyzer, MuteTab, etc.)
// bug here https://code.google.com/p/chromium/issues/detail?id=524356
strpos($source_file, 'chrome-extension://') === false
// avoid false positives notifications coming from Safari extensions (diigo, evernote, etc.)
&& strpos($source_file, 'safari-extension://') === false
&& strpos($blocked_uri, 'safari-extension://') === false
// search engine extensions ?
&& strpos($source_file, 'se-extension://') === false
// added by browsers in webviews
&& strpos($blocked_uri, 'webviewprogressproxy://') === false
// Google Search App see for details https://github.com/nico3333fr/CSP-useful/commit/ecc8f9b0b379ae643bc754d2db33c8b47e185fd1
&& strpos($blocked_uri, 'gsa://onpageload') === false
) {
// Prepare report data (hash => info)
$hash = hash('md5', $blocked_uri . $document_uri . $source_file . $line_number . $violated_directive);
try {
// Check report dir (create it if necessary)
files::makeDir(dirname(LOGFILE), true);
// Check if report is not already stored in log file
$contents = '';
if (file_exists(LOGFILE)) {
$contents = file_get_contents(LOGFILE);
if ($contents && $contents != '') {
if (substr($contents, -1) == ',') {
// Remove final comma if present
$contents = substr($contents, 0, -1);
}
if ($contents != '') {
$list = json_decode('[' . $contents . ']', true);
if (is_array($list)) {
foreach ($list as $idx => $value) {
if (isset($value['hash']) && $value['hash'] == $hash) {
// Already stored, ignore
return;
}
}
}
}
}
}
// Add report to the file
if (!($fp = @fopen(LOGFILE, 'a'))) {
// Unable to open file, ignore
return;
}
// Prettify the JSON-formatted data
$violation = array_merge(['hash' => $hash], $data['csp-report']);
$output = json_encode($violation, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
// The file content will have to be enclosed in brackets [] before
// beeing decoded with json_decoded(<content>,true);
fprintf($fp, ($contents != '' ? ',' : '') . '%s', $output);
} catch (Exception $e) {
return;
}
}
}

View File

@ -1,34 +0,0 @@
<?php
# -- BEGIN LICENSE BLOCK ---------------------------------------
#
# This file is part of Dotclear 2.
#
# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
# Licensed under the GPL version 2.0 license.
# See LICENSE file or
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
#
# -- END LICENSE BLOCK -----------------------------------------
# Delete users
if (!empty($_REQUEST['dispatch_action']))
{
if ($_REQUEST['dispatch_action'] == 'deleteuser')
{
if (!empty($_REQUEST['user_id'])) {
$delete_users = $_REQUEST['user_id'];
}
include dirname(__FILE__).'/users.php';
exit;
}
elseif ($_REQUEST['dispatch_action'] == 'setpermissions')
{
include dirname(__FILE__).'/permissions_blog.php';
exit;
}
}
echo '<p>What the hell are you doing here?</p>';
exit;
?>

View File

@ -1,95 +0,0 @@
<?php
/**
* @package Dotclear
* @subpackage Backend
*
* @copyright Olivier Meunier & Association Dotclear
* @copyright GPL-2.0-only
*/
require dirname(__FILE__) . '/../inc/admin/prepend.php';
dcPage::check('usage,contentadmin');
$helpPage = function (...$args) {
$ret = ['content' => '', 'title' => ''];
if (empty($args)) {
return $ret;
}
;
global $__resources;
if (empty($__resources['help'])) {
return $ret;
}
$content = '';
$title = '';
foreach ($args as $v) {
if (is_object($v) && isset($v->content)) {
$content .= $v->content;
continue;
}
if (!isset($__resources['help'][$v])) {
continue;
}
$f = $__resources['help'][$v];
if (!file_exists($f) || !is_readable($f)) {
continue;
}
$fc = file_get_contents($f);
if (preg_match('|<body[^>]*?>(.*?)</body>|ms', $fc, $matches)) {
$content .= $matches[1];
if (preg_match('|<title[^>]*?>(.*?)</title>|ms', $fc, $matches)) {
$title = $matches[1];
}
} else {
$content .= $fc;
}
}
if (trim($content) == '') {
return $ret;
}
$ret['content'] = $content;
if ($title != '') {
$ret['title'] = $title;
}
return $ret;
};
$help_page = !empty($_GET['page']) ? html::escapeHTML($_GET['page']) : 'index';
$content_array = $helpPage($help_page);
if (($content_array['content'] == '') || ($help_page == 'index')) {
$content_array = $helpPage('index');
}
if ($content_array['title'] != '') {
$breadcrumb = dcPage::breadcrumb(
[
__('Global help') => $core->adminurl->get("admin.help"),
$content_array['title'] => ''
]);
} else {
$breadcrumb = dcPage::breadcrumb(
[
__('Global help') => ''
]);
}
/* DISPLAY
-------------------------------------------------------- */
dcPage::open(__('Global help'),
dcPage::jsPageTabs('first-step'),
$breadcrumb
);
echo $content_array['content'];
// Prevents global help link display
$GLOBALS['__resources']['ctxhelp'] = true;
dcPage::close();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><title>attachment</title><path d="M9.5 19.75a4.25 4.25 0 0 1-4.25-4.25v-6.5a2.75 2.75 0 0 1 5.5 0v6h-1.5v-6a1.25 1.25 0 0 0-2.5 0v6.5a2.75 2.75 0 0 0 5.5 0v-11.5a2.25 2.25 0 0 0-4.5 0v1h-1.5v-1a3.75 3.75 0 0 1 7.5 0v11.5a4.25 4.25 0 0 1-4.25 4.25z" fill="#ff0000"/></svg>

Before

Width:  |  Height:  |  Size: 332 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 586 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 149 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 226 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 601 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 419 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 B

View File

@ -1,11 +0,0 @@
<svg
id="mask"
viewbox="0 0 16 16"
preserveAspectRatio="xMinYMin meet"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M7.9 7.9l2.1 7.5 1.7-2.6 3.2 3.2 1.1-1.1-3.3-3.2 2.7-1.6z">
</path>
<path d="M8 12h-7v-9h12v5.4l1 0.2v-6.6h-14v11h8.2z">
</path>
</svg>

Before

Width:  |  Height:  |  Size: 313 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 176 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 162 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 296 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 246 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 858 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 350 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 139 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 510 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 661 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 369 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 240 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 404 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 302 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 194 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 514 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 366 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 439 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 343 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 298 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 511 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 730 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 467 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 448 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 820 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 256 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 273 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 309 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 490 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 194 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 200 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 925 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 367 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 540 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 219 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 330 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 908 B

Some files were not shown because too many files have changed in this diff Show More